[MFC] 윈도우 프로그래밍 기초 - 팝업메뉴 만들기(리소스의 이해)
오늘 실습은 팝업 메뉴 만드는 방법에 대해 실습할 계획입니다.
실습과 더불어 간단하게 리소스의 큰 그림을 이해할 수 있도록 작성하였습니다.
|
출력 결과 |
1. 프로젝트 생성하기
1. Visual Studio 2013을 켭니다.
2. 새 프로젝트를 만듭니다.
프로젝트 명은 Lecture로 하겠습니다.
3. 다음은 MFC 프로그램에 대한 기본 환경 설정입니다.
아래와 같이 설정하고 마침을 누르겠습니다.
2. 리소스 뷰에 대한 설명(숲 그리기)
2-1. 리소스란?
사전적 의미로 자원이란 의미를 가지고 있습니다.
전쟁으로 비유하면,
리소스는 위의 그림과 같은 관계가 될 수 있습니다.
Figure 2-1. <Source And Resource> - Relational Model
소스코드와 리소스는 각각 컴파일되어서, 소스코드는 *.obj로 변환되고, 리소스 파일은 *.rc로 컴파일이 됩니다.
이들이 Link 단계에서 결합 후에 Execution File로서 결합됩니다.
이번 실습에서의 큰 그림은 아래와 같이 소개할 수 있습니다.
2-2. 리소스 뷰
앞서 설명한 이야기를 이해하였으면, 실제 리소스가 MFC에서 어떻게 사용되는지 소개하겠습니다.
프로젝트를 앞서 생성했으면, 왼쪽에 리소스 뷰란 탭을 클릭하면 아래와 같은 창을 살펴볼 수 있습니다.
|
|
리소스 뷰 |
리소스 파일의 위치 (솔루션 탐색기) |
리소스 파일 생성에 관해 말씀드리면, MFC 라이브러리를 이용하지 않는 프로그램이면 이용하면 리소스에 대해 관리가 될 수 있다고 보이나 MFC를 이용한 파일이면 굳이 자동으로 생성되는 만큼 별도로 추가 구성을 할 필요가 없습니다.
.rc라는 파일은 즉, 다수의 리소스를 모아놓은 하나의 집합이라고 정의할 수 있습니다.
2-3. 리소스 식별 접두어 (관례)
* 사용자 정의 리소스 식별 매크로의 접두어
설명 |
접두어 |
아이콘 |
IDI_ |
커서 |
IDC_ |
비트맵 |
IDB_ |
문자열 항목 |
IDS_ 또는 IDM_ |
메뉴 |
IDR_ |
메뉴 항목 |
IDM_ |
엑셀러레이터 |
IDR_ |
엑셀러레이터 키 |
IDM_ |
도구 모음 |
IDR_ |
도구 모음 버튼 |
IDM_ |
대화 상자 |
IDD_ |
컨트롤 |
IDC_ |
* MFC 내장 리소스 식별 매크로의 접두어
설명 |
접두어 |
아이콘 |
AFX_IDI_ |
커서 |
AFX_IDC_ |
비트맵 |
AFX_IDB_ |
버전 |
VS_VERSION |
문자열 항목 |
AFX_IDS_ 또는 ID_ |
메뉴 항목 |
ID_ |
엑셀러레이터 |
AFX_IDR_ |
엑셀러레이터 키 |
ID_ |
도구 모음 버튼 |
ID_ |
대화 상자 |
AFX_IDD_ |
컨트롤 |
AFX_IDC_ 또는 ID_ |
2-4. 리소스 뷰 간단하게 살펴보기
3. 실습(팝업 메뉴 만들기)
이번 실습은 "팝업 메뉴 만들기"라는 주제로 실습을 하겠습니다.
3-1. 메뉴 만들기
리소스 추가를 클릭합니다.
Menu를 선택하고 새로 만들기(N)을 클릭합니다.
3-2. 아래와 같이 메뉴를 꾸며주기.
|
|
메뉴 구성하기 |
리소스뷰 - 방금 만든 메뉴 리소스 ID 변경 -> IDR_POPUP |
3-3. 클래스 뷰의 CMainFrame 설정하기
WM_CONTEXTMENU라는 영역에 OnContextMenu를 생성하는 방법을 실습해보겠습니다.
<Add> OnContextMenu를 클릭하면
MainFrm.cpp과 MainFrm.h의 파일에 자동 생성되어 구현할 수 있는 상태로 코드가 생성됩니다.
즉, MainFrm.cpp의 함수 원형을 변경할 경우, MainFrm.h 쪽도 저장하셔야합니다.
(참고)
|
기본 생성된 MainFrm.h의 OnContextMenu 원형 구조 |
|
기본 생성된 MainFrm.cpp의 구현 구조 |
3-4. 코딩하기
void CMainFrame::OnContextMenu(CWnd *pWnd, CPoint point) { CMenu popup; CMenu* pMenu;
popup.LoadMenuW(IDR_POPUP); pMenu = popup.GetSubMenu(0);
pMenu->TrackPopupMenu(TPM_LEFTALIGN || TPM_RIGHTBUTTON, point.x, point.y, this);
}
|
수정) MainFrm.cpp |
void CMainFrame::OnContextMenu(CWnd *pWnd, CPoint point); |
수정) MainFrm.h |
(참고) 팝업 메뉴 소스코드 분석
* < LoadMenu() >의 원형
* BOOL CMenu::LoadMenu(LPCTSTR lpszResourceName) |
메뉴 리소스를 읽어오는 함수를 의미합니다.
* < GetSubMenu() >의 원형
* CMenu *CMenu::GetSubMenu(int nPos) const |
GetSubMenu() 함수는 메뉴 표시줄에서 하위 메뉴를 구하는 함수입니다.
즉, 구하고자 하는 함수의 하위 메뉴는 0부터 시작함.
* <TrackPopupMenu() > 의 원형
* BOOL CMenu::TrackPopupMenu( UINT nFlags, int x, int y, CWnd *pWnd, LPCRECT lpRect = NULL ) |
uFlags에는 여러가지 조합으로 사용가능
인수 uFlags에는 여러 가지 값을 조합하여 설정할 수 있는데, 팝업 메뉴의 정렬과 동작 설정 값을 비트 OR 연산자로 연결해 지정할 수 있음.
<팝업 메뉴의 정렬 설정 값>
값 |
내용 |
TPM_LEFTALIGN |
팝업 메뉴를 지정한 위치에서 좌측 정렬 |
TPM_RIGHTALIGN |
팝업 메뉴를 지정한 위치에서 우측 정렬 |
TPM_CENTERALIGN |
팝업 메뉴를 지정한 위치에서 가운데 정렬 |
TPM_TOPALIGN |
팝업 메뉴를 지정한 위치에서 위쪽 정렬 |
TPM_BOTTOMALIGN |
팝업 메뉴를 지정한 위치에서 바닥 정렬 |
TPM_VCENTERALIGN |
팝업 메뉴를 지정한 위치에서 수직 중앙 정렬 |
<팝업 메뉴의 동작 설정 값>
값 |
내용 |
TPM_LEFTBUTTON |
마우스 왼쪽 버튼 클릭시 메뉴 수행 |
TPM_RIGHTBUTTON |
마우스 오른쪽 버튼 클릭시 메뉴 수행 |
TPM_NONOTIFY |
메뉴 항목이 선택되었을 때 통지 메시지를 보내지 않음 |
TPM_RETURNCMD |
메뉴 항목이 선택되었을 때 선택된 메뉴 항목의 ID를 반환 |
* int x, int y
-> Point의 좌표 (eg: point.x, point y)
* pWnd
pWnd는 팝업 메뉴를 소유하고 있는 윈도우를 지정해주면 됨.
-> pWnd
3-5. 컴파일 해보기
마우스 오른쪽 버튼을 클릭해보면, 아래와 같이 정상 동작함을 확인할 수 있습니다.