메뉴 명령을 처리하고 메뉴 항목을 적절하게 갱신하는 기법을 익힌다. 컨텍스트 메뉴와 시스템 메뉴를 다루는 방법을 익힌다. 툴바를 생성하고 사용하는 방법을 익힌다. 상태바를 생성하고 사용하는 방법을 익힌다.
메뉴 용어 (1/6) 최상위 메뉴 = 메뉴 바 최상위 메뉴 = 메뉴 바
메뉴 용어 (2/6) 메뉴 항목 명령 항목 팝업 항목 용어 의미 ① 명령 항목 명령(Command)을 수행하는 메뉴 항목. 선택하면 WM_COMMAND 메시지가 발생한다. ② 팝업 항목 하위 메뉴를 화면에 표시하는 메뉴 항목. 선택해도 WM_COMMAND 메시지가 발생하지 않는다. 명령 항목 팝업 항목
메뉴 용어 (3/6) 하위 메뉴 드랍다운 메뉴 팝업 항목을 선택했을 때 화면에 나타나는 메뉴 최상위 메뉴 항목을 클릭했을 때 펼쳐지는 메뉴 드랍다운 메뉴 = 팝업 메뉴
메뉴 용어 (4/6) 컨텍스트 메뉴 = 단축 메뉴 마우스 오른쪽 버튼을 누를 때 열리는 메뉴 마우스 커서의 위치 또는 현재 작업하고 있는 내용에 따라 서로 다른 메뉴 항목이 표시됨 컨텍스트 메뉴 = 단축 메뉴 = 팝업 메뉴
메뉴 용어 (5/6) 팝업 메뉴 시스템 메뉴 = 윈도우 메뉴 사용자가 무엇인가를 선택했을 때 메뉴가 튀어나온다(Pop Up)는 뜻으로 만든 용어 드랍다운 메뉴와 컨텍스트 메뉴가 여기에 속함 시스템 메뉴 = 윈도우 메뉴 시스템 메뉴 = 윈도우 메뉴
메뉴 용어 (6/6) 액세스키와 단축키 액세스키 단축키 메뉴가 열린 상태에서 특정 항목을 키보드로 빠르게 선택 메뉴가 열리지 않은 상태에서도 키 조합으로 메뉴 항목의 기능을 곧바로 실행 액세스키 단축키
메뉴 클래스 MFC 클래스 CMenu CCmdUI 메뉴를 다룰 수 있는 다양한 함수 제공 CObject의 파생 클래스가 아닌 독립된 클래스 메뉴와 툴바 및 상태바에 필요한 기능 지원
메뉴 생성 (1/9) 두 가지 방법 메뉴 리소스 프로그램 실행 중 메뉴 생성 메뉴 리소스 작성
메뉴 생성 (2/9) AppWizard가 생성한 코드 BOOL CSimple2App::InitInstance() { CMainFrame* pFrame = new CMainFrame; m_pMainWnd = pFrame; pFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL, NULL); pFrame->ShowWindow(SW_SHOW); pFrame->UpdateWindow(); return TRUE; }
메뉴 생성 (3/9) 메뉴 항목 속성 의미 내부적으로 메뉴 항목을 구분하는 번호이며 일반적으로 ID_메뉴이름_항목이름 형태로 만든다. 예) ID_EDIT_CUT 화면에 표시되는 문자열로 액세스키를 지정하려면 해당 문자 앞에 '&' 기호를 사용한다. 단축키를 사용할 경우 '\t' 기호를 삽입하여 단축키를 나타내는 문자열이 탭 위치에 정렬되도록 한다. 예) 잘라내기(&T)\tCtrl+X 메뉴 항목을 구분하는 가로줄이 표시된다. 설정하면 명령 항목이 아닌 팝업 항목이 된다. 최상위 메뉴는 대개 Pop-up 속성을 가진다. 속성 ID Caption Separator Pop-up
메뉴 생성 (4/9) 메뉴 항목 속성 (cont'd) 메뉴 항목이 표시되지만 사용하지는 못한다. 일반적으로 메뉴 항목은 하나의 열(Column)에 표시되지만 항목의 개수가 많을 경우 두 개 이상의 열에 표시되게 할 수 있다. Break 속성으로 Column 또는 Bar를 선택하면 이때부터는 다음 열에 메뉴 항목이 표시된다. Column과 Bar 속성은 기본적으로 같은 기능을 하지만 Bar 속성을 선택하면 열 구분선(세로줄)이 생긴다. 메뉴 항목의 왼쪽에 체크 표시를 한다. Inactive Break Checked 의미 속성
메뉴 생성 (5/9) 메뉴 항목 속성 (cont'd) 메뉴 항목이 흐리게 표시되어 현재 사용할 수 없음을 나타낸다. 윈도우의 오른쪽 끝 위치에 메뉴가 표시되도록 한다. 주로 Help 메뉴 항목에 이 속성을 설정한다. MFC로 작성한 프로그램에서만 사용할 수 있는 속성으로, 툴바와 상태바에 표시될 문자열을 나타낸다. '\n'을 기준으로 앞쪽 문자열은 상태바에 표시되며 뒤쪽 문자열은 툴팁에 표시된다. 예) 선택 부분을 잘라내어 클립보드에 넣습니다\n잘라내기 Grayed Help Prompt 의미 속성
메뉴 생성 (6/9) 프로그램 실행 중 전체 메뉴 생성하기 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { // 생략... CMenu menuMain; menuMain.CreateMenu(); CMenu menuPopup; menuPopup.CreatePopupMenu(); menuPopup.AppendMenu(MF_STRING, 201, "빨강(&R)"); menuPopup.AppendMenu(MF_STRING, 202, "초록(&G)"); menuPopup.AppendMenu(MF_STRING, 203, "파랑(&B)");
메뉴 생성 (7/9) 프로그램 실행 중 전체 메뉴 생성하기 (cont'd) menuMain.AppendMenu(MF_POPUP, (UINT_PTR)menuPopup.Detach(), "색상(&C)"); SetMenu(&menuMain); menuMain.Detach(); return 0; }
메뉴 생성 (8/9) 프로그램 실행 중 추가 메뉴 생성하기 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { // 생략... CMenu Popup1; Popup1.CreatePopupMenu(); Popup1.AppendMenu(MF_STRING, 301, "&1"); Popup1.AppendMenu(MF_STRING, 302, "&2"); Popup1.AppendMenu(MF_STRING, 303, "&3"); Popup1.AppendMenu(MF_STRING, 304, "&4"); CMenu Popup2; Popup2.CreatePopupMenu(); Popup2.AppendMenu(MF_STRING|MF_CHECKED, 201, "Item&1");
메뉴 생성 (9/9) 프로그램 실행 중 추가 메뉴 생성하기 (cont'd) Popup2.AppendMenu(MF_POPUP, (UINT_PTR)Popup1.Detach(), "Item&2"); Popup2.AppendMenu(MF_STRING, 203, "Item&3"); CMenu *pTopLevel = GetMenu(); pTopLevel->AppendMenu(MF_POPUP, (UINT_PTR)Popup2.Detach(), "연습(&X)"); return 0; }
메뉴 명령 처리 (1/3) 메뉴 명령 처리 과정 MFC의 메뉴 명령 처리 방법 명령 라우팅 ① 명령 항목을 마우스나 키보드로 선택 ② WM_COMMAND 메시지 발생 ③ WM_COMMAND 메시지 핸들러에서 메뉴 명령 처리 MFC의 메뉴 명령 처리 방법 각각의 메뉴 항목에 대해 함수를 따로 작성 명령 핸들러(Command Handler) ON_COMMAND(메뉴ID, 함수명) 매크로를 이용하여 메뉴 항목과 함수 연결 명령 라우팅 명령 핸들러를 작성하는 위치에 관계없이 처리
메뉴 명령 처리 (2/3) 메뉴 명령 처리 예 BEGIN_MESSAGE_MAP(CChildView,CWnd ) ... ON_COMMAND(ID_COLOR_RED, OnColorRed) ON_COMMAND(ID_COLOR_GREEN, OnColorGreen) ON_COMMAND(ID_COLOR_BLUE, OnColorBlue) END_MESSAGE_MAP() void CChildView::OnColorRed() { m_color = RGB(255, 0, 0); Invalidate(); }
메뉴 명령 처리 (3/3) 메뉴 명령 처리 예 (cont'd) void CChildView::OnColorGreen() { m_color = RGB(0, 255, 0); Invalidate(); } void CChildView::OnColorBlue() m_color = RGB(0, 0, 255);
메뉴 항목 갱신 (1/5) 메뉴 항목 갱신 예
메뉴 항목 갱신 (2/5) MFC의 메뉴 항목 갱신 방법 명령 라우팅 각각의 메뉴 항목에 대해 함수를 따로 작성 명령 갱신 핸들러(Command Update Handler) ON_UPDATE_COMMAND_UI(메뉴ID, 함수명) 매크로를 이용하여 메뉴 항목과 함수 연결 명령 라우팅 명령 핸들러와 마찬가지로 명령 갱신 핸들러도 작성하는 위치에 관계없이 처리
메뉴 항목 갱신 (3/5) 메뉴 항목 갱신 예 BEGIN_MESSAGE_MAP(CChildView,CWnd ) ... ON_UPDATE_COMMAND_UI(ID_COLOR_RED, OnUpdateColorRed) ON_UPDATE_COMMAND_UI(ID_COLOR_GREEN, OnUpdateColorGreen) ON_UPDATE_COMMAND_UI(ID_COLOR_BLUE, OnUpdateColorBlue) END_MESSAGE_MAP() void CChildView::OnUpdateColorRed(CCmdUI* pCmdUI) { pCmdUI->SetCheck(m_color == RGB(255, 0, 0)); }
메뉴 항목 갱신 (4/5) 메뉴 항목 갱신 예 (cont'd) void CChildView::OnUpdateColorGreen(CCmdUI* pCmdUI) { pCmdUI->SetCheck(m_color == RGB(0, 255, 0)); } void CChildView::OnUpdateColorBlue(CCmdUI* pCmdUI) pCmdUI->SetCheck(m_color == RGB(0, 0, 255));
메뉴 항목 갱신 (5/5) CCmdUI 클래스 멤버 함수 멤버 함수 의미 사용 예 Enable( ) 활성화 상태 변경 pCmdUI->Enable(b_DrawMode); SetCheck( ) 체크 상태 변경 pCmdUI->SetCheck(m_color == RGB(255, 0, 0)); SetRadio( ) 라디오 표시 상태 변경 pCmdUI->SetRadio(m_color == RGB(255, 0, 0)); SetText( ) 문자열 변경 pCmdUI->SetText("Light On");
컨텍스트 메뉴 (1/4) WM_CONTEXTMENU 메시지 발생 상황 WM_CONTEXTMENU 메시지 핸들러 클라이언트 영역 또는 비 클라이언트 영역에서 마우스 오른쪽 버튼을 클릭하는 경우 Shift + F10 키 조합을 누른 경우 가상 키코드 VK_APPS에 해당하는 키( )를 누른 경우 WM_CONTEXTMENU 메시지 핸들러 pWnd - 마우스 커서 아래쪽에 있는 윈도우 pos - 마우스 커서의 위치(스크린 좌표) afx_msg void OnContextMenu (CWnd* pWnd, CPoint pos) ;
컨텍스트 메뉴 (2/4) CMenu::TrackPopupMenu() 함수 nFlags TPM_LEFTALIGN, TPM_CENTERALIGN, TPM_RIGHTALIGN TPM_LEFTBUTTON, TPM_RIGHTBUTTON BOOL TrackPopupMenu (UINT nFlags, int x, int y, CWnd* pWnd, LPCRECT lpRect = 0) ;
컨텍스트 메뉴 (3/4) x, y pWnd lpRect 컨텍스트 메뉴가 표시될 위치(스크린 좌표) 컨텍스트 메뉴에서 발생한 WM_COMMAND 메시지를 받을 윈도우 lpRect 마우스 버튼을 클릭하더라도 컨텍스트 메뉴가 닫히지 않는 사각형 영역(스크린 좌표)
컨텍스트 메뉴 (4/4) 컨텍스트 메뉴 사용 예 void CChildView::OnContextMenu(CWnd* pWnd, CPoint point) { CMenu menu; menu.LoadMenu(IDR_MAINFRAME); CMenu* pMenu = menu.GetSubMenu(4); pMenu->TrackPopupMenu( TPM_LEFTALIGN|TPM_RIGHTBUTTON, point.x, point.y, AfxGetMainWnd()); }
시스템 메뉴 (1/2) 시스템 메뉴 조작하기 CWnd::GetSystemMenu() 함수를 이용하여 시스템 메뉴에 대한 CMenu 포인터를 얻는다. CMenu 클래스가 제공하는 다양한 함수(AppendMenu(), InsertMenu(), DeleteMenu(), ...)를 적용한다.
시스템 메뉴 (2/2) 주의 사항 시스템 메뉴를 변경하려면 GetSystemMenu(FALSE)를, 시스템 메뉴를 초기 상태로 되돌리려면 GetSystemMenu(TRUE)를 호출한다. 시스템 메뉴에 새로운 메뉴 항목을 추가할 때 메뉴 ID는 반드시 16의 정수배가 되어야 한다. 시스템 메뉴 항목을 선택하면 WM_COMMAND가 아닌 WM_SYSCOMMAND 메시지가 발생한다.
가속기 가속기 = 단축키 메뉴 항목을 곧바로 실행할 수 있는 키 조합 가속기 리소스 추가
툴바 (1/4) 툴바 MFC 클래스 선택하면 WM_COMMAND 메시지 발생!
툴바 (2/4) 툴바 리소스
툴바 (3/4) 툴바 코드 class CMainFrame : public CFrameWnd { // 생략 ... protected: CStatusBar m_wndStatusBar; CToolBar m_wndToolBar; CChildView m_wndView; }; int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD |
툴바 (4/4) 툴바 코드 (cont'd) WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) { TRACE0("Failed to create toolbar\n"); return -1; } // 생략 ... m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); EnableDocking(CBRS_ALIGN_ANY); DockControlBar(&m_wndToolBar); return 0;
상태바 (1/4) 상태바 MFC 클래스
상태바 (2/4) 상태바 리소스 static UINT indicators[ ] = { ID_SEPARATOR, ID_INDICATOR_CAPS, ID_INDICATOR_NUM, ID_INDICATOR_SCRL, };
상태바 (3/4) 상태바 코드 class CMainFrame : public CFrameWnd { // 생략 ... protected: CStatusBar m_wndStatusBar; CToolBar m_wndToolBar; CChildView m_wndView; };
상태바 (4/4) 상태바 코드 (cont'd) int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { // 생략 ... if (!m_wndStatusBar.Create(this) || !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT))) TRACE0("Failed to create status bar\n"); return -1; }