TrackPopupMenu

원형

BOOL TrackPopupMenu(HMENU hMenu, UINT uFlags, int x, int y, int nReserved, HWND hWnd, CONST RECT *prcRect);

MFC 원형

BOOL CMenu::TrackPopupMenu( UINT nFlags, int x, int y, CWnd* pWnd, LPCRECT lpRect = NULL );

인수

▶hMenu : 출력할 팝업 메뉴의 핸들. 보통 GetSubMenu 함수로 구한다.

▶uFlags : 팝업 메뉴를 출력할 옵션. 위치와 메뉴 항목 선택에 관한 여러 가지 옵션이 있다.

▶(x,y) : 팝업 메뉴를 출력할 화면 좌표

▶nReserved : 사용하지 않는 인수이며 0으로 주면 된다.

▶hWnd : 팝업 메뉴의 부모 윈도우 핸들이며 팝업 메뉴가 선택되었을 때 이 윈도우로 WM_COMMAND 메시지가 전달된다.

▶prcRect : 사용하지 않는 인수이며 NULL로 주면 된다.

리턴

성공하면 0이 아닌값을 리턴하며 실패시 0을 리턴한다. uFlags에 TPM_RETURNCMD 플래그를 주었을 경우 리턴값은 선택한 메뉴 항목의 ID가 되며 항목 선택을 취소하면 0이 리턴된다.

설명

화면의 임의 위치에 팝업 메뉴를 출력한다. 팝업 메뉴는 주로 마우스 버튼을 누른 위치에 곧바로 열리므로 선택하기 편리하며 꼭 필요한 항목만을 포함하므로 메인 메뉴에 비해서는 사용하기 쉽다는 장점이 있다. 또한 마우스를 누른 위치나 상황에 따라 다른 메뉴를 보여줄 수도 있으므로 훨신 더 직관적이다.

팝업 메뉴를 만드려면 리소스에 메뉴를 만들고 LoadMenu, GetSubMenu 함수로 메뉴의 핸들을 구한 후 이 함수를 호출하면 된다. (x,y)는 팝업 메뉴가 출력될 좌표이되 팝업 메뉴는 화면상의 어디서나 열릴 수 있으므로 이 좌표는 작업 영역 좌표가 아닌 화면 좌표가 된다. 일반적으로 팝업 메뉴는 WM_CONTEXTMENU 메시지에서 여는데 이 메시지는 lParam으로 화면 좌표를 전달해 주므로 이 좌표에 팝업 메뉴를 열면 무난하다.

uFlags에는 여러가지 옵션의 조합을 줄 수 있는데 플래그는 성격에 따라 몇가지 그룹으로 분류할 수 있다. 다음 플래그들은 팝업 메뉴가 출력될 좌표를 해석하는 방법을 지정한다. 이 플래그들의 조합에 따라 (x,y)좌표를 팝업 메뉴의 어디로 해석할 것인가가 결정된다.

플래그 설명

TPM_LEFTALIGN

팝업 메뉴를 지정한 위치에서 좌측 정렬한다.

TPM_RIGHTALIGN 팝업 메뉴를 지정한 위치에서 우측 정렬한다.
TPM_CENTERALIGN 팝업 메뉴를 지정한 위치에서 수평 중앙 정렬한다.
TPM_TOPALIGN 팝업 메뉴를 지정한 위치에서 위쪽에 정렬한다.
TPM_BOTTOMALIGN 팝업 메뉴를 지정한 위치에서 바닥에 정렬한다.
TPM_VCENTERALIGN 팝업 메뉴를 지정한 위치에서 수직 중앙 정렬한다.

디폴트는 수평으로 좌측, 수직으로 위쪽에 정렬(TPM_LEFTALIGN | TPM_TOPALIGN)되며 이 위치가 가장 이상적이다. 수평으로 왼쪽 정렬된다는 것은 x좌표가 팝업 메뉴의 왼쪽 좌표라는 뜻이며 따라서 마우스 커서의 오른쪽에 팝업 메뉴가 열린다. 다음은 몇가지 플레그의 조합으로 팝업 메뉴의 출력 위치를 변경해 본 것이다.

디폴트

TPM_CENTERALIGN |
TPM_VCENTERALIGN

TPM_RIGHTALIGN

다음 플래그들은 팝업 메뉴의 항목을 선택했을 때 이 함수의 동작을 정의한다.

플래그 설명

TPM_LEFTBUTTON

왼쪽 버튼을 눌렀을 때만 메뉴 항목을 선택할 수 있다. 이 플래그는 디폴트이므로 굳이 지정할 필요가 없다.

TPM_RIGHTBUTTON

오른쪽 버튼으로도 메뉴 항목을 선택할 수 있다. 팝업 메뉴는 오른쪽 마우스 버튼으로 여는 경우가 많으므로 이 플래그를 지정해 놓으면 메뉴 항목을 더 편리하게 선택할 수 있다.

TPM_NONOTIFY 메뉴 항목이 선택되었을 때 통지 메시지를 보내지 않는다.
TPM_RETURNCMD 메뉴 항목이 선택되었을 때 선택된 메뉴 항목의 ID를 리턴한다.

다음 플래그들은 팝업 메뉴가 열릴 때의 애니메이션 동작을 지정한다. 단 이 플래그들은 98 ME, 윈도우즈 2000이상에서만 사용할 수 있으며 조합하여 지정할 수도 있다.

플래그 설명

TPM_HORNEGANIMATION

오른쪽에서 왼쪽으로

TPM_HORPOSANIMATION 왼쪽에서 오른쪽으로
TPM_NOANIMATION 애니메이션을 하지 않음
TPM_VERNEGANIMATION 아래쪽에서 위쪽으로
TPM_VERPOSANIMATION 위쪽에서 아래쪽으로

예제 1

다음 예제는 이 함수로 팝업 메뉴를 출력하는 가장 전형적인 예제이다. 리소스에는 메뉴가 다음과 같이 정의되어 있다.

메뉴 바는 사용하지 않으므로 더미 항목을 만들어 두고 이 항목 아래에 원하는 팝업 메뉴를 작성해 놓는다. 더 필요한 팝업 메뉴가 있으면 같은 메뉴 아래 여러 개의 팝업 메뉴를 같이 만들어도 상관없다. 그리고 다음과 같이 코드를 작성한다.

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
	HMENU hMenu, hPopup;

	switch(iMessage) {
	case WM_CONTEXTMENU:
		hMenu=LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_MENU1));
		hPopup=GetSubMenu(hMenu, 0);

		TrackPopupMenu(hPopup, TPM_RIGHTBUTTON, LOWORD(lParam), HIWORD(lParam), 
			0, hWnd, NULL);
		DestroyMenu(hMenu);
		return 0;
	case WM_COMMAND:
		switch(LOWORD(wParam)) {
		case IDM_POPUP1:
			MessageBox(hWnd,"첫 번째 팝업 메뉴를 선택했습니다","알림",MB_OK);
			break;
		case IDM_POPUP2:
			MessageBox(hWnd,"두 번째 팝업 메뉴를 선택했습니다","알림",MB_OK);
			break;
		case IDM_POPUP3:
			MessageBox(hWnd,"세 번째 팝업 메뉴를 선택했습니다","알림",MB_OK);
			break;
		}
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}

마우스 오른쪽 버튼을 누를 때 전달되는 WM_CONTEXTMENU 메시지에서 팝업 메뉴를 출력하였다. LoadMenu 함수로 메뉴 리소스를 읽고 GetSubMenu로 첫번째 팝업 메뉴를 구하여 출력하면 된다. 팝업 메뉴의 항목을 선택하면 부모 윈도우로 WM_COMMNAND 메시지를 보내주므로 통지 메시지를 받았을 때 해당되는 처리를 하면 된다. 예제에서는 메시지 박스를 띄워 팝업 메뉴가 선택되었음을 확인만 하였다.

예제 2

다음 예제는 팝업 메뉴에서 선택된 메뉴 항목을 처리하는 또 다른 방법을 보여준다.

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
	HMENU hMenu, hPopup;
	int idm;

	switch(iMessage) {
	case WM_CONTEXTMENU:
		hMenu=LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_MENU1));
		hPopup=GetSubMenu(hMenu, 0);

		idm=TrackPopupMenu(hPopup, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, 
			LOWORD(lParam), HIWORD(lParam), 
			0, hWnd, NULL);

		switch(idm) {
		case IDM_POPUP1:
			MessageBox(hWnd,"첫 번째 팝업 메뉴를 선택했습니다","알림",MB_OK);
			break;
		case IDM_POPUP2:
			MessageBox(hWnd,"두 번째 팝업 메뉴를 선택했습니다","알림",MB_OK);
			break;
		case IDM_POPUP3:
			MessageBox(hWnd,"세 번째 팝업 메뉴를 선택했습니다","알림",MB_OK);
			break;
		}
		DestroyMenu(hMenu);
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}

TPM_RETURNCMD 플래그를 사용하면 선택한 메뉴 항목의 ID를 곧바로 리턴해 주므로 따로 메시지 핸들러를 작성하지 않고 곧바로 선택한 항목에 대한 처리를 할 수 있다. 메뉴 항목의 의미가 간단할 경우는 메뉴를 연 후 메시지를 보내지 않고 곧바로 처리를 할 수 있으므로 이 방법을 사용하는 것이 훨씬 더 간단하다.

팝업 메뉴를 여는 윈도우가 포그라운드 윈도우가 아닌 경우 팝업 메뉴의 바깥을 선택했을 때 메뉴가 사라지지 않는 버그가 있다. 이 버그는 트레이에 등록된 아이콘으로부터 팝업 메뉴를 열 때 쉽게 확인할 수 있다. 이 경우 팝업 메뉴를 호출하기 전에 SetForegroundWindow 함수로 해당 윈도우를 포그라운드로 만들어 준 후 이 함수를 호출하고 함수 리턴 직후에 WM_NULL 메시지를 큐에 붙이면 문제를 해결할 수 있다.

SetForegroundWindow(hWnd);
TrackPopupMenu( ...
PostMessage(hWnd, WM_NULL, 0, 0);

참고함수

TrackPopupMenuEx : 동일한 함수이되 팝업 메뉴가 출력되지 말아야 할 영역을 지정할 수 있다.

플랫폼

95이상

참조

팝업 메뉴에 대한 일반적인 사용예는 19-2에 있다.


written by http://www.winapi.co.kr