06: 사용자인터페이스 학습목표 메뉴명령을처리하고메뉴항목을적절하게갱신하는기법을익 힌다. 컨텍스트메뉴와시스템메뉴를다루는방법을익힌다. 툴바를생성하고사용하는방법을익힌다. 상태바를생성하고사용하는방법을익힌다.
메뉴용어 (1/6) 최상위메뉴 = 메뉴바 최상위메뉴 = 메뉴바 1
메뉴용어 (2/6) 메뉴항목 용어 의미 1 명령항목명령 (Command) 을수행하는메뉴항목. 선택하면 WM_COMMAND 메시지가발생한다. 2 팝업항목하위메뉴를화면에표시하는메뉴항목. 선택해도 WM_COMMAND 메시지가발생하지않는다. 명령항목 팝업항목 2
메뉴용어 (3/6) 하위메뉴 팝업항목을선택했을때화면에나타나는메뉴 드랍다운메뉴 최상위메뉴항목을클릭했을때펼쳐지는메뉴 드랍다운메뉴 = 팝업메뉴 3
메뉴용어 (4/6) 컨텍스트메뉴 = 단축메뉴 마우스오른쪽버튼을누를때열리는메뉴 마우스커서의위치또는현재작업하고있는내용에따라서로다른메뉴항목이표시됨 컨텍스트메뉴 = 단축메뉴 = 팝업메뉴 4
메뉴용어 (5/6) 팝업메뉴 사용자가무엇인가를선택했을때메뉴가튀어나온다 (Pop Up) 는뜻으로만든용어 드랍다운메뉴와컨텍스트메뉴가여기에속함 시스템메뉴 = 윈도우메뉴 시스템메뉴 = 윈도우메뉴 5
메뉴용어 (6/6) 액세스키와단축키 액세스키 메뉴가열린상태에서특정항목을키보드로빠르게선택 단축키 메뉴가열리지않은상태에서도키조합으로메뉴항목의기능을곧바로실행 액세스키 단축키 6
메뉴클래스 MFC 클래스 CMenu 메뉴를다룰수있는다양한함수제공 CCmdUI CObject의파생클래스가아닌독립된클래스 메뉴와툴바및상태바에필요한기능지원 7
메뉴생성 (1/9) 두가지방법 메뉴리소스 프로그램실행중메뉴생성 메뉴리소스작성 8
메뉴생성 (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; 9
메뉴생성 (3/9) 메뉴항목속성 속성 ID Caption Separator Pop-up 의미 내부적으로메뉴항목을구분하는번호이며일반적으로 ID_ 메뉴이름 _ 항목이름형태로만든다. 예 ) ID_EDIT_CUT 화면에표시되는문자열로액세스키를지정하려면해당문자앞에 '&' 기호를사용한다. 단축키를사용할경우 ' t' 기호를삽입하여단축키를나타내는문자열이탭위치에정렬되도록한다. 예 ) 잘라내기 (&T) tctrl+x 메뉴항목을구분하는가로줄이표시된다. 설정하면명령항목이아닌팝업항목이된다. 최상위메뉴는대개 Pop-up 속성을가진다. 10
메뉴생성 (4/9) 메뉴항목속성 (cont'd) 속성 Inactive Break Checked 의미메뉴항목이표시되지만사용하지는못한다. 일반적으로메뉴항목은하나의열 (Column) 에표시되지만항목의개수가많을경우두개이상의열에표시되게할수있다. Break 속성으로 Column 또는 Bar를선택하면이때부터는다음열에메뉴항목이표시된다. Column 과 Bar 속성은기본적으로같은기능을하지만 Bar 속성을선택하면열구분선 ( 세로줄 ) 이생긴다. 메뉴항목의왼쪽에체크표시를한다. 11
메뉴생성 (5/9) 메뉴항목속성 (cont'd) 속성 Grayed Help Prompt 의미 메뉴항목이흐리게표시되어현재사용할수없음을나타낸다. 윈도우의오른쪽끝위치에메뉴가표시되도록한다. 주로 Help 메뉴항목에이속성을설정한다. MFC로작성한프로그램에서만사용할수있는속성으로, 툴바와상태바에표시될문자열을나타낸다.'\n' 을기준으로앞쪽문자열은상태바에표시되며뒤쪽문자열은툴팁에표시된다. 예 ) 선택부분을잘라내어클립보드에넣습니다 \n잘라내기 12
메뉴생성 (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)"); ); 13
메뉴생성 (7/9) 프로그램실행중전체메뉴생성하기 (cont'd) menumain.appendmenu(mf_popup, (UINT_PTR)menuPopup.Detach(), " 색상 (&C)"); SetMenu(&menuMain); menumain.detach(); } return 0; 14
메뉴생성 (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"); 15
메뉴생성 (9/9) 프로그램실행중추가메뉴생성하기 (cont'd) Popup2.AppendMenu(MF_POPUP, 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(), p (), " 연습 (&X)"); ); } return 0; 16
메뉴명령처리 (1/3) 메뉴명령처리과정 1 명령항목을마우스나키보드로선택 2 WM_COMMAND 메시지발생 3 WM_COMMAND 메시지핸들러에서메뉴명령처리 MFC 의메뉴명령처리방법 각각의메뉴항목에대해함수를따로작성 명령핸들러 (Command Handler) ON_COMMAND( 메뉴ID, 함수명 ) 매크로를이용하여메뉴항목과함수연결 명령라우팅 명령핸들러를작성하는위치에관계없이처리 17
메뉴명령처리 (2/3) 메뉴명령처리예 BEGIN_MESSAGE_MAP(CChildView,CWnd MAP(CChildView CWnd )... ON_COMMAND(ID_COLOR_RED, OnColorRed) ON_COMMAND(ID_COLOR_GREEN, COLOR OnColorGreen) ON_COMMAND(ID_COLOR_BLUE, OnColorBlue)... END_MESSAGE_MAP() MAP() void CChildView::OnColorRed() { m_color = RGB(255, 0, 0); Invalidate(); } 18
메뉴명령처리 (3/3) 메뉴명령처리예 (cont'd) void CChildView::OnColorGreen() { m_color = RGB(0, 255, 0); Invalidate(); } void CChildView::OnColorBlue() C l { m_color = RGB(0, 0, 255); Invalidate(); } 19
메뉴항목갱신 (1/5) 메뉴항목갱신예 20
메뉴항목갱신 (2/5) MFC 의메뉴항목갱신방법 각각의메뉴항목에대해함수를따로작성 명령갱신핸들러 (Command Update Handler) ON_UPDATE_COMMAND_UI( 메뉴 ID, 함수명 ) 매크로를이용하여메뉴항목과함수연결 명령라우팅 명령핸들러와마찬가지로명령갱신핸들러도작성하는위치에관계없이처리 21
메뉴항목갱신 (3/5) 메뉴항목갱신예 BEGIN_MESSAGE_MAP(CChildView,CWnd MAP(CChildView CWnd )... ON_UPDATE_COMMAND_UI(ID_COLOR_RED, OnUpdateColorRed) ON_UPDATE_COMMAND_UI(ID_COLOR_GREEN, UI(ID COLOR OnUpdateColorGreen) ON_UPDATE_COMMAND_UI(ID_COLOR_BLUE, OnUpdateColorBlue)... END_MESSAGE_MAP() void CChildView::OnUpdateColorRed(CCmdUI* d C l d(cc dui* pcmdui) { pcmdui->setcheck(m_color == RGB(255, 0, 0)); } 22
메뉴항목갱신 (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)); } 23
메뉴항목갱신 (5/5) CCmdUI 클래스멤버함수 멤버함수의미사용예 Enable( ) 활성화상태변경 pcmdui->enable(b_drawmode); SetCheck( ) 체크상태변경 pcmdui->setcheck(m >SetCheck(m_colorcolor == RGB(255, 0, 0)); SetRadio( ) 라디오표시상태변경 pcmdui->setradio(m_color == RGB(255, 0, 0)); SetText( ) 문자열변경 pcmdui->settext("light On"); 24
컨텍스트메뉴 (1/4) WM_CONTEXTMENU 메시지발생상황 클라이언트영역또는비클라이언트영역에서마우스오른쪽버튼을클릭하는경우 Shift + F10 키조합을누른경우 가상키코드 VK_APPS 에해당하는키 ( ) 를누른경우 WM_CONTEXTMENU NU 메시지핸들러 afx_msg void OnContextMenu (CWnd* pwnd, CPoint pos) ; pwnd - 마우스커서아래쪽에있는윈도우 pos - 마우스커서의위치 ( 스크린좌표 ) 25
컨텍스트메뉴 (2/4) CMenu::TrackPopupMenu() 함수 BOOL TrackPopupMenu (UINT nflags, int x, int y, CWnd* pwnd, LPCRECT lprect = 0) ; nflags TPM_LEFTALIGN, TPM_CENTERALIGN, TPM_RIGHTALIGN TPM_LEFTBUTTON, TPM_RIGHTBUTTON 26
컨텍스트메뉴 (3/4) x, y 컨텍스트메뉴가표시될위치 ( 스크린좌표 ) pwnd 컨텍스트메뉴에서발생한 WM_COMMAND 메시지를받을윈도우 lprect 마우스버튼을클릭하더라도컨텍스트메뉴가닫히지않는사각형영역 ( 스크린좌표 ) 27
컨텍스트메뉴 (4/4) 컨텍스트메뉴사용예 void CChildView::OnContextMenu(CWnd* C tm d* pwnd, CPoint point) { CMenu menu; menu.loadmenu(idr_mainframe); CMenu* pmenu = menu.getsubmenu(4); pmenu->trackpopupmenu( p p TPM_LEFTALIGN TPM_RIGHTBUTTON, point.x, point.y, AfxGetMainWnd()); } 28
시스템메뉴 (1/2) 시스템메뉴조작하기 CWnd::GetSystemMenu() 함수를이용하여시스템메뉴에대한 CMenu 포인터를얻는다. CMenu 클래스가제공하는다양한함수 (AppendMenu(), InsertMenu(), DeleteMenu(),...) 를적용한다. 29
시스템메뉴 (2/2) 주의사항 시스템메뉴를변경하려면 GetSystemMenu(FALSE) 를, 시스템메뉴를초기상태로되돌리려면 GetSystemMenu(TRUE) 를호출한다. 시스템메뉴에새로운메뉴항목을추가할때메뉴 ID는반드시 16의정수배가되어야한다. 시스템메뉴항목을선택하면 WM_COMMAND 가아닌 WM_SYSCOMMAND 메시지가발생한다. 30
가속기 가속기 = 단축키 메뉴항목을곧바로실행할수있는키조합 가속기리소스추가 31
툴바 (1/4) 툴바 MFC 클래스 선택하면 WM_COMMAND 메시지발생! 32
툴바 (2/4) 툴바리소스 33
툴바 (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 34
툴바 (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); ANY); DockControlBar(&m_wndToolBar); } return 0; 35
상태바 (1/4) 상태바 MFC 클래스 36
상태바 (2/4) 상태바리소스 static UINT indicators[ ] = { ID_SEPARATOR, }; ID_INDICATOR_CAPS, INDICATOR CAPS ID_INDICATOR_NUM, ID_INDICATOR_SCRL, 37
상태바 (3/4) 상태바코드 class CMainFrame : public CFrameWnd { // 생략... protected: CStatusBar m_wndstatusbar; CToolBar m_wndtoolbar; CChildView m_wndview; // 생략... }; 38
상태바 (4/4) 상태바코드 (cont'd) int CMainFrame::OnCreate(LPCREATESTRUCT C lpcreatestruct) t) { // 생략... if (!m_wndstatusbar.create(this)!m_wndstatusbar.setindicators(indicators, sizeof(indicators)/sizeof(uint))) ( ))) } { TRACE0("Failed to create status bar\n"); return -1; } // 생략... 39