WINAPI - WM_COMMAND
- WM_COMMAND
⇒ 프로그램 실행중에 사용자가 메뉴 항목을 선택하면 WM_COMMAND 메시지가 발생한다.
⇒ 이 때 어떤 메뉴 항목이 선택되었는가는 wParam의 하위 워드로 전달되므로 LOWORD(wParam)을 읽어 판단할 수 있다. 그래서 Menu.cpp의 WndProc에서는 WM_COMMAND 메시지를 받을 경우 switch 문으로 다시 LOWORD(wParam)의 값에 따라 분기를 하여 각 메뉴 항목에 따른 처리를 발생한다.
⇒ ID_FILE_MENU1 메뉴 항목(Menu1)이 선택되었을 경우 메시지 박스를 열어 메뉴 항목이 선택되었음을 알려주고 ID_FILE_EXIT메뉴 항목(Exit)이 선택되었을 경우 프로그램을 종료한다.
⇒ WM_COMMAND 메시지는 메뉴 항목을 선택할 뿐만 아니라 액셀러레이터를 누를 때도 발생하며 도한 버튼, 에디트 박스 등의 컨트롤이 부모 윈도우로 통지 메시지를 보낼 때도 발생한다. 이 메시지의 추가 정보는 다음과 같은 구조를 가진다.
값 |
설명 |
lParam LOWORD(wParam) HIWORD(wParam)
|
통지 메시지를 발생시킨 컨트롤의 윈도우 핸들 메뉴나 액셀러레이터, 컨트롤의 ID 컨트롤이 보내는 통지 메시지, 메뉴가 선택된 경우는 0이 되며 액셀러레이터가 선택된 경우는 1이 된다. |
⇒ WM_COMMAND 메시지가 워낙 여려가지 명령을 받아들이는 메시지이다 보니 추가 정보도 복잡하다. 여기서 우리가 사용한 값은 메뉴 ID가 전달되는 LOWORD(wParam)뿐이다. 기억할 것은 메뉴 선택시 WM_COMMAND 메시지가 전달되며 LOWORD(wParam)을 읽어 어떤 메뉴 항목이 선택되었는지를 판단할 수 있다는 것.
- 메뉴 편집기
⇒ 메뉴 편집기는 사용자가 편집한 메뉴를 텍스트 형태로 리소스 파일에 기록한다.
- 새 메뉴의 작성
⇒ 새로운 메뉴를 작성할 때는 리소스 뷰의 팝업 메뉴에서 리소스 추가(또는 Insert) 항목을 선택한다.
⇒ 위와 같이 자동으로 IDR_MENU2가 생성되었다.(위에 IDR_NENU1 이 이미 만들어져 있으므로 IDR_MENU2가 되었다.)
- 메뉴 항목의 추가
⇒ 빈칸에 새로운 메뉴를 추가하려면 곧바로 캡션을 입력하거나 빈칸을 더블클릭하여 속성 편집기를 열고 캡션과 기타 속성들을 입력한다. 좌상단의 빈칸을 더블 클릭하여 File이라는 캡션을 주면 다음과 같이 된다.
⇒ 오른쪽과 아래쪽에 각각 빈칸이 나타나는데 이 빈칸들에 또 메뉴 항목을 만들 수 있으며 아래와 같은 식으로 메뉴 생성이 가능하다.
- 메뉴 항목의 수정
⇒ 기존에 만들어져 있는 메뉴의 이름이나 속성을 변경하려면 속성 편집기에서 원하는 속성을 다시 입력하면 된다.
- 메뉴 항목의 삽입
⇒ 기존에 작성되어 있는 메뉴 리스트에서 삽입할 위치에 커서를 위치한 후 키보드에서 Insert 키를 누르면 커서 위치에 빈카닝 새로 생성되며 이 빈칸에 원하는 항목을 입력한다.
- 메뉴 항목의 삭제
⇒ 삭제하고자 하는 메뉴 항목에 커서를 위치한 후 Delete 키를 누른다. 단, 메뉴 리스트의 메뉴 항목은 그냥 삭제되지만 하위 메뉴를 거느린 팝업 메뉴를 삭제할 때는 바로 삭제하지 않고 경고 메시지 창이 출력된다.
- 메뉴의 이동
⇒ 이동하고자 하는 메뉴를 마우스로 드래그하여 원하는 위치로 이동할 수 있다. 이 기능을 이용해 메뉴 바에 있는 메뉴를 하위 메뉴로 만들 수 있다.
⇒ 예로 Edit 메뉴를 File 메뉴의 Save와 Print 사이에 끼워 넣으면 다음과 같이 Edit 메뉴 전체가 File 메뉴의 하위 메뉴가 된다.
- 복사 및 붙여넣기
⇒ 메뉴의 복사, 붙여넣기는 워드 프로세서에서 클립보드를 사용하여 문서의 일부분을 복사하는 것과 개념적으로 동일하다.
기타 리소스
- 아이콘, 커서
⇒ 아이콘이나 커서도 리소스의 일종이며 각각의 편집기를 사용하여 제작할 수 있다.
⇒ 메뉴의 Insert → resource 대화상자에서 ICON을 선택하여 새로운 아이콘을 만든다.
⇒ 다음으로 Insert → resource 대화상자에서 CURSOR을 선택하여 새로운 커서를 만든다.
⇒ 커서를 만든 후 커서 편집기를 닫고 이번에는 만들어 놓은 커서와 아이콘을 사용하도록 코드를 수정한다.
WndClass.hCursor = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_CURSOR1)); |
⇒ 아래와 같이 아이콘과 커서가 생성된 것을 확인 할 수 있다.
- 액셀러레이터
⇒ 액셀러레이터(Accelerator)는 쉽게 말해 단축키이다. Ctrl+C는 Copy, Ctrl+V는 Paste 등이 있다.
⇒ 단, 윈도우wm에서 단축키와 Accelerator를 구별하는 이유는 윈도우즈에서 단축키(ShortCut)가 다른 의미로 사용되고 있기 때문이다. 메뉴 이름에 &를 넣어 Alt키와 함께 사용하는 키를 단축키라고 하며 액셀러레이터와는 의미가 조금 다르다.
⇒ 단축키는 반드시 Alt키와 함께 사용해야 하며 메뉴에 있는 항목을 키보드로 선택하는 빠른 방법이지만 액셀러레이터는 메뉴와 상관없이 언제든지 사용이 가능하다.
- 실습
⇒ 리소스 뷰에서 IDR_MENU1을 더블클릭하면 메뉴 편집기가 열린다.
⇒ File 팝업 메뉴의 속성 윈도우에서 Caption을 &file로 바꾼다.
⇒ File 메뉴 아래 세 개의 메뉴 항목에서 각 항목의 캡션을 다음과 같이 수정한다.
수정 전 |
수정 후 |
Menu1 |
Menu&1\tCtrl+A |
Menu2 |
Menu&1\tCtrl+B |
Exit |
&Exit\tCtrl+C |
⇒ 아래는 수정중인 화면이다.
⇒ 메뉴를 만들 때와 같은 방법으로 리소스 추가 대화상자에서 Accelerator를 선택한다. 다음과 같은 액셀러레이터 편집기가 열린다. 각 란에 다음과 같이 입력한다.
⇒
⇒ 다음은 리소스를 코드에서 사용하도록 소스를 수정한다. WinMain의 선두에 hAccel 변수를 선언하고 메시지 루프만 다음과 같이 수정한다.
hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));
while(GetMessage(&Message, NULL, 0, 0))
{
if(!TranslateAccelerator(hWnd, hAccel, &Message))
{
TranslateMessage(&Message);
DispatchMessage(&Message);
}
}
⇒ Accel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));
→ 이 함수는 리소스로부터 액셀러레이터 테이블을 읽어들인다. 두 번째 인수 lpTableName은 액셀러레이터 테이블의 이름 문자열 포인터이되 우리가 작성한 액셀러레이터 테이블 IDR_ACCELERATOR1은 정수값이므로 MAKEINTRESOURCE 매크로를 사용해야 한다.
→ 이 함수는 리소스에서 액셀러레이터 테이블을 읽은 후 그 핸들을 리턴한다. 이 핸들값을 hAccel이라는 변수에 대입해 두면 다음부터 hAccel을 통해 액셀러레이터 테이블을 읽을 수 있다.
⇒ int TranslateAccelerator(HWND hWnd, HACCEL hAccTable, LPMSG lpMsg);
→ 이 함수는 키보드 메시지를 WM_COMMAND 메시지로 변경하여 액셀러레이터가 동작할 수 있도록 한다. 액셀러레이터 Ctrl+A가 입력되었다고 해 보자. Ctrl+A는 액셀러레이터이기 이전에 키보드로부터의 입력이므로 먼저 WM_KEYDOWN 메시지가 발생할 것이고 그대로 내버려 주면 WndProc의 WM_KEYDOWN 메시지 처리 루틴에서 먼저 이 키값을 처리해 버릴 것이다.
→ TranslateAccelerator 함수는 lpMsg의 키보드 입력값을 읽어 이 키값이 hAccTable에 있는지 먼저 살펴보고 있을 경우 그 키에 해당하는 WM_COMMAND 메시지를 hWnd 윈도우로 전달하고 TRUE를 리턴해 버린다.
→ 그래서 액셀러레이터가 입력되었을 경우 TranslateMessage, DispatchMessage 함수가 실행되지 못하게 막아 버리며 다음 번의 WM_COMMAND 메시지가 처리되도록 한다.
→ WM_KEYDOWN 메시지는 중간에 다른 메시지로 변형되거나(WM_COMMAND) 추가로 메시지를 발생(WM_CHAR)시키는 경우가 빈번하다.
'내장형 하드웨어 > WINAPI' 카테고리의 다른 글
WINAPI - 그래픽(색상) (0) | 2011.09.08 |
---|---|
WINAPI - 그래픽(GDI 오브젝트) (0) | 2011.09.07 |
WINAPI - 리소스(메뉴 생성 첫번째) (0) | 2011.09.05 |
WINAPI - 소스분석 첫번째 (0) | 2011.08.22 |
WINAPI - 변수 명명 법, 유니코드, 윈도우 생성 첫번째 (0) | 2011.08.18 |