[Develog] 메모장프로그래밍 4 - Acclerator

이성훈·2021년 12월 23일
0

DEVELOG

목록 보기
4/14

이전까지 메뉴바의 기본형태를 만들고 코드는 작성하지않았다.
안드로이드에서 layout을 xml로 관리하듯, Win32프로그래밍에서는 .rc파일과 resource.h(ID값..등)을 통해 Resource(지금은 메뉴바)들을 관리한다.

먼저, 리소스뷰의 메뉴의 속성들을 전부 지정해주었다.

(새로만들기 단축키는 Ctrl-N으로 바꿨음..)
전부순서대로 MENU1, MENU2... 편집에서도 ID_EDIT_MENU1.. 로 지정해주었는데
여기서 캡션의경우는 단축키를 보여주도록 \t캐릭터를 이용했다. &뒤의 문자가 단축키가된다
(예: &FILE => F가 단축키)

그리고 소스코드로돌아와서 WndProc에 해당 메뉴들을 선택했을때의 동작들을 추가해주면됬다.

여기선 예제로 Menu 1이라는 메세지상자를 보여주도록 하였다.

OK버튼이있는 메세지상자가 정상적으로 출력되었다.

이제 단축키를 제대로 지정해보자.
먼저 리소스뷰의 Accelerator폴더에 기존 파일을 좀만 손봐주면된다.

여기서 중요한것이 ID값을 연결되는 메뉴바의 ID값과 동일하게 설정해주면 WndProc함수의 WM_COMMAND는 수정할 필요가 없다.

이제 설정한 엑셀레이터를 등록해줘야하는데, 기존의 while문으로 메시지를 받는 루프를 수정해줘야한다.

	//프로그램에 전달된 메시지를 번역, 실행하는부분
	//Win32 프로그램은 운영체제나 다른 프로그램상에
	//메시지를 주고받는 방식. 그래서 항상 메시지를 받도록
	//메시지 큐를 가지고있고 전달받은 메시지로 프로그램을 실행
	MSG msg; //메시지 구조체
	//평상시는 메시지에 0이아닌값을 받으나
	//VM_QUIT메시지를 받으면 0값으로, 반복문이 종료됨
	HACCEL hAccel;
	hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));

	while (GetMessage(&msg, NULL, 0, 0)) { 
		////메시지가 가상키관련시, 아스키값으로 해석된 추가 메시지를 발생
		//TranslateMessage(&msg); 
		////WndProc함수를 호출.
		//DispatchMessage(&msg);
		//바뀐부분. 엑셀레이터테이블에 등록된 값이 받아지면은 자동으로
		//WndProc로 넘어가기때문에 if문을 추가해준 모습
		if (!TranslateAccelerator(hWnd, hAccel, &msg)) {
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

엑셀레이터 핸들을 추가해주고, 기존의 루프에 if문을 추가해주었다.
이제 단축키만 입력해도 메뉴가실행이된다.

또, 추가적으로 파일, 편집 서식, 보기등도 단축키를 설정해주기위하여

&뒤의 문자가단축키가되도록 해준다.

추가적으로 모든 &를 괄호( )안의 영문자 앞으로 옮겨준다. (앞에서 잘못 붙였었다)
이렇게하면 이제 3가지방법으로 메뉴바에 접근가능하다

  1. 마우스로 전부 클릭한다
  2. 단축키(Ctrl + N등)를 이용하여 접근
  3. Alt + F - N 으로 접근

전체소스코드

#include "pch.h"
#include "framework.h"
#include "MEMO.h"

//윈도우에서 발생한 메시지를 처리하는 함수
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
	//처리하고싶은 내용들을 작성하는 부분
	//종료메시지를 받지않고 윈도우자체가 파괴된경우 (X 눌렀을때)
	//자신의 응용프로그램에 VM_QUIT메시지를 보내 종료시킴
	if (uMsg == WM_DESTROY)PostQuitMessage(0); //중요

	switch (uMsg) {
	case WM_CREATE:
		return 0;
	case WM_COMMAND:
		switch (LOWORD(wParam)) {
		case ID_FILE_MENU1:
			MessageBox(hWnd, TEXT("Menu 1"), TEXT("Menu1 Caption"), MB_OK);
			break;
		}
	}
	

	//만약내가 처리하지않은 기본 메시지들을 대신 처리해주는 함수
	return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

//윈도우 클래스 등록
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPSTR lpCmdLine, int nCmdShow) {

	WNDCLASS wc;
	wchar_t my_class_name[] = L"아리랑";
	wc.cbClsExtra = NULL; //추가메모리 사용X
	wc.cbWndExtra = NULL; //추가메모리 사용,X
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); //배경을 흰색으로
	wc.hCursor = LoadCursor(NULL, IDC_ARROW); //커서의 핸들값 저장
	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); //아이콘의 핸들값 저장
	wc.hInstance = hInstance; 
	wc.lpfnWndProc = WndProc;
	wc.lpszClassName = my_class_name;
	wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
	wc.style = CS_HREDRAW | CS_VREDRAW;

	RegisterClass(&wc);

	//윈도우를 생성하는부분
	//hWnd : 윈도우 핸들
	HWND hWnd = CreateWindow(my_class_name, L"test",
		WS_OVERLAPPEDWINDOW, 100, 100, 400, 400, NULL, NULL,
		hInstance, NULL);
	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);

	//프로그램에 전달된 메시지를 번역, 실행하는부분
	//Win32 프로그램은 운영체제나 다른 프로그램상에
	//메시지를 주고받는 방식. 그래서 항상 메시지를 받도록
	//메시지 큐를 가지고있고 전달받은 메시지로 프로그램을 실행
	MSG msg; //메시지 구조체
	//평상시는 메시지에 0이아닌값을 받으나
	//VM_QUIT메시지를 받으면 0값으로, 반복문이 종료됨
	HACCEL hAccel;
	hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));

	while (GetMessage(&msg, NULL, 0, 0)) { 
		////메시지가 가상키관련시, 아스키값으로 해석된 추가 메시지를 발생
		//TranslateMessage(&msg); 
		////WndProc함수를 호출.
		//DispatchMessage(&msg);
		//바뀐부분. 엑셀레이터테이블에 등록된 값이 받아지면은 자동으로
		//WndProc로 넘어가기때문에 if문을 추가해준 모습
		if (!TranslateAccelerator(hWnd, hAccel, &msg)) {
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}
	//반복문의 종료는 프로그램의 종료이다.
	return msg.wParam;
}
profile
I will be a socially developer

0개의 댓글