[퍼옴]MFC05

WindowsPrograming : 2007. 3. 11. 09:24
반응형

5.메뉴,도구바,상태바

본장은 메뉴와 도구바 상태바를 컨트롤 하는 방법에 대해서 설명합니다.이 3개의 컨트롤은 AppWizard로 프로젝트를 만들면 기본적인것이 설정됩니다. 이 기본적인 상태에서 우리가 원하는 형태로 바꾸고자할때 사용하는 방법과 기존에 설정된 도구바와 상태바를 제어하거나 변경하는 방법을 본장을 통해서 이해하실수 있을겁니다.



1.메뉴

지금까지 예제를 다루면서 메뉴에 새로운 항목을 만드는 방법과 항목에 의해서 함수를 생성하는 방법들을 설명했습니다. 이외에 메뉴가 선택되었을때 이메뉴항목이 어떤 의미로 설정되는가에 대한 도움말이 상태바에 출력되는 부분이 필요하며 메뉴에 설정된 내용들이 활성 비활성 또는 체크되는 방법들이 필요합니다. 예제를 제작해 가면서 이런 방법들에 대해서 설명합니다.


MExMenu 프로젝트 만들기

새로운 프로젝트 MExMenu는 SDI형입니다. 지금까지 본책을 읽어 왔다면 SDI형의 프로젝트를 만드는 방법은 아실것입니다. 이프로젝트를 만들면 메뉴 ID가 IDR_MAINFRAME로 설정됩니다. 이메뉴에서 View항목에 3개의 메뉴 항목을 설정합니다. 그림 1은 3개의 메뉴항목을 설정한 화면입니다.


               (그림 1) 3개의 메뉴 항목 설정화면

Window1는 의 ID는 ID_WINDOW1 이며 Window2는 ID_WINDOW2, Window3는 ID_WINDOW3로 설정합니다. 본 예제에서 하고자 하는 것은 Window1 메뉴항목을 설정하면 Window1이 체크되어 있고 Window2를 설정하면 Window2가 체크되어 있고 Window3를 설정하면 Window3메뉴항목이 체크되는 형태를 만들고자 합니다. 또한 Edit메뉴에서 메뉴의 선택때 마다 활성과 비활성을 설정하는 것을 만들고자 합니다. 처음에는  Edit메뉴에서 Copy와 Cut 항목만 활성상태로 있어야 하며 Paste 항목은  비활성 상태로 있어야 합니다. 이때 Copy항목을 선택하면 데이터가 복사된상태이므로(예제에서는 복사를 하지는 않지만) Paste항목이 활성화 되도록 하는 것입니다. 

즉 메뉴에서 활성 비활성 체크부분을 컨트롤 하는 방법을 배우게 됩니다.


활성,비활성,체크 상태 만들기

활성이란 메뉴가 현재 사용가능한 것을 말하며 비활성이란 회색으로 처리되어 메뉴항목을 사용하지 못하는 것을 의미합니다. 메뉴에서 활성 비활성을 처리하는 부분의 각메뉴의 UPDATE_COMMAND_UI항목입니다. 예제를 작성해 보면서 설명하겠습니다. CMainFrame클래스의 헤더 즉 MainFrm.h에 다음과 같이 플러그를 설정합니다.

        BOOL m_bCopy;

위 플러그를 생성자에서 다음과 같이 FALSE값을 설정해 줍니다.

CMainFrame::CMainFrame()

{

       // TODO: add member initialization code here

       m_bCopy=FALSE;

}

위와 같이 만든 이유는 Copy항목이나 또는 Cut항목을 설정하면 이플러그를 TRUE로 설정하여 현재 Copy나 Cut항목을 선택했다는 것을 알려주기 위함입니다.

이와 같이 만든다음 자원의 메뉴에서 (IDR_MAINFRAME) 에서 Copy를 선택했을때의 함수와 Cut 를 선택하였을때 함수를 만들고 이함수에서 m_bCopy를 TRUE로 설정합니다.


void CMainFrame::OnEditCut()

{

       // TODO: Add your command handler code here

       m_bCopy=TRUE;       

}


void CMainFrame::OnEditCopy()

{

       // TODO: Add your command handler code here

       m_bCopy=TRUE;              

}

위와 같이 설정한후에 Paste 메뉴항목에서 (ID가 ID_EDIT_PASTE)에서 UPDATE_COMMAND_UI가 발생되었을때의 함수를 만듭니다. 이함수는 다음과 같습니다.

void CMainFrame::OnUpdateEditPaste(CCmdUI* pCmdUI)

{

       // TODO: Add your command update UI handler code here

       

}

UPDATE_COMMAND_UI는 모든 메뉴항목 COMMAND와 함께 설정되어있는 메시지 항목입니다. 이항목은 메뉴를 선택하였을때는 모든 메뉴항목에 동시에 발생되는 메시지입니다. 위의 OnUpdateEditPaste 함수와 함께 들어오는 CCmdUI형의 pCmdUI에는 각메뉴의 아이디와 메뉴 핸들러 등이 정의되어 있고 현재 선택된 메뉴의 활성 비활성 체크를 할수 있는 맴버 함수들이 구성되어 있습니다.

이 pCmdUI함수를 이용하여 m_bCopy 가 TRUE일경우 메뉴가 활성시키고 m_bCopy가 FALSE일경우 비활성시킬경우로 수정한 OnUpdateEditPaste는 다음과 같습니다.


void CMainFrame::OnUpdateEditPaste(CCmdUI* pCmdUI)

{

       // TODO: Add your command update UI handler code here

       pCmdUI->Enable(m_bCopy);

}

Enable함수 안의 인자가 TRUE일경우 해당항목이 활성화 되는 것이며 FALSE일경우에는 비활성화 됩니다. 처음 프로그램이 실행되면 m_bCopy는 FALSE이 이기 때문에 Paste항목은 비활성화 됩니다. 이후에 Copy나 Cut항목을 클릭하면 m_bCopy가 TRUE가 되므로 활성화가 됩니다. 그림 2는 위와같이 프로그램을 수정하고 컴파일 하여 실행했을때 메뉴의 변화된 결과입니다.


         (초기 메뉴 화면)         (Cut 항목을 설정했을 때의 화면)

        (그림 2) MExMenu실행후 메뉴 선택결과


이제 MExMenu에서 Window1부터 Window3까지의 항목을 선택했을대 체크되는 메뉴를 만들어 보겠습니다. 항목을 선택했을때 선택한 항목의 값을 기억하는 플러그를 만듭니다. CMainFrame에 헤더에 다음과 같은 변수를 설정합니다.


        int m_nWindowNum;


m_nWindowNum은 생성자에서 0으로 설정합니다.


CMainFrame::CMainFrame()

{

       // TODO: add member initialization code here

       m_bCopy=FALSE;

       m_nWindowNum=0;

}


메뉴항목에서 Window1을 선택하면 m_nWindowNum은 1로 Window2를 선택하면 m_nWindowNum을 2로 바꿉니다. 이렇게 하여 어느 메뉴를 선택하엿는가를 m_nWindowNum의 값으로 알수가 있는 것입니다. Window1부터 Window3까지의 항목을 선택 했을때의 함수를 만들고 이함수를 다음과 같이 수정합니다.


void CMainFrame::OnWindow1()

{

       // TODO: Add your command handler code here

       m_nWindowNum=1;     

}


void CMainFrame::OnWindow2()

{

       // TODO: Add your command handler code here

       m_nWindowNum=2;     

}


void CMainFrame::OnWindow3()

{

       // TODO: Add your command handler code here

       m_nWindowNum=3;     

}


이제 Window1부터 Window3항목에서 UPDATE_COMMAND_UI 메시지가 발생되었을 때의 함수를 만들고 다음과 같이 수정합니다.


void CMainFrame::OnUpdateWindow1(CCmdUI* pCmdUI)

{

       // TODO: Add your command update UI handler code here

       if(m_nWindowNum==1)

               pCmdUI->SetCheck(TRUE);

       else

               pCmdUI->SetCheck(FALSE);

}


void CMainFrame::OnUpdateWindow2(CCmdUI* pCmdUI)

{

       // TODO: Add your command update UI handler code here

       if(m_nWindowNum==2)

               pCmdUI->SetCheck(TRUE);

       else

               pCmdUI->SetCheck(FALSE);   

}


void CMainFrame::OnUpdateWindow3(CCmdUI* pCmdUI)

{

       // TODO: Add your command update UI handler code here

       if(m_nWindowNum==3)

               pCmdUI->SetCheck(TRUE);

       else

               pCmdUI->SetCheck(FALSE);   

}


각 메뉴에서 해당되는 번호가 일치하면 SetCheck(TRUE)가 실행되고 그렇지 않을 경우에는 SetCheck(FALSE)가 실행됩니다. CCmdUI의 멤버함수이 SetCheck함수는 메뉴에 체크를 설정해 주는 함수입니다. 이함수의 인자가 TRUE일경우 체크되며 FALSE일경우 체크가 해제 됩니다. 위와 같이하면 Window1항목을 선택했을때 m_nWindowNum이 1로 설정되기 때문에 Window1항목은 체크된 형태로 됩니다.

위와 같이 프로그램을 수정하고 컴파일하고 실행하고 Window1~Window3까지의 항목을 선택하면 선택한 항목이 체크되어 나타납니다. 그림3은 MExMenu에서 Window1을 선택하였을때 의 화면입니다.


        (Window1을 선택하는 화면)   (Window1을 선택후에 체크된 화면)

        (그림 3)MExMenu에 체크 기능을 추가한 결과


메뉴 항목과 도움말 연결

어플리케이션 프로그램에서 메뉴를 선택하면 현재 위치 의 메뉴에 대한 도움말이 상태바에 출력됩니다. 예를 들어 “새파일”이라는 항목이 현재 위치된 메뉴라면 하단부 상태바 윈도우에 “새로운 파일을 엽니다” 라는 메시지가 출력됩니다. 이렇게 출력하게 하기 위해서는 이용하는 것은 매우 간단합니다. 자원에서 해당메뉴를 선택하고 해당메뉴의 속성에 문자열을 기록하면 됩니다.

Window1이라는 항목에 마우스커서가 위치하거나 또는 화살표키를 이용하여 이 메뉴가 그림3의 좌측화면처럼 선택되었을때 “Window1 이 설정되었습니다” 라는 도움말이 상태바에 출력해 보겠습니다.

먼저 ResoruceView에서 IDR_MAINFRAME를 선택하여 메뉴를 선택한다음 메뉴에서 Window1을 선택하고 Alt+Enter키를 눌러서 속성대화상자를 출력합니다.

               (그림 3) Window1항목에서 속성대화상자 출력

속성 대화상자에서 Prompt 항목에 “Window1 이 설정되었습니다.” 라는 문장을 기입하였습니다. 이와 같이 하고 프로그램을 컴파일한후 실행시키고 Window1메뉴에 위치하면 그림 4와 같이 프로그램 하단부 상태바에 “Window1 이 설정되었습니다” 라는 문자열이 출력됩니다.

        (그림 4)Windo1메뉴에 위치되었을때 상태바에 출력되는 도움말


컨텍스트 메뉴만들기

컨텍스트 메뉴란 우측 마우스 버튼을 클릭했을때 메뉴가 출력되게 하는 메뉴를 의미합니다. 우측 마우스 버튼을 클릭하면 WM_CONTEXTMENU가 발생됩니다. 이메시지에 의한 함수를 CMainFrame에 만들면 다음과 같은 함수가 만들어 집니다.


void CMainFrame::OnContextMenu(CWnd* pWnd, CPoint point)

{

       

}


처음 인자는 윈도우 클래스이며 두번째 인자는 마우스가 클릭된 위치입니다. 이함수를 받고 이함수에서 메뉴를 만들면 됩니다.

메뉴를 로드하거나 출력하는 클래스는 CMenu입니다. 이 CMenu를 이용하면 메뉴에대한 모든 것을 제어 할수 있습니다. 본항목에서는 CMenu를 이용하여 IDR_MAINFRAME메뉴를 로드하고 이메뉴의 첫번째 팝업 메뉴를 받아보겟습니다.


        CMenu contmenu;

        CMenu *pMenu;

        contmenu.LoadMenu(IDR_MAINFRAME);//IDR_MAINFRAME메뉴를 로드

        pMenu=contmenu.GetSubMenu(0);//첫번째 팝업 메뉴를 pMenu가 받는다.

메뉴 자원을 로드하는 CMenu의 맴버함수는 LoadMenu입니다. 이함수를 이용하여 contmenu에 IDR_MAINFRAME를 받습니다. 그리고 이메뉴중에 첫번째 서브메뉴 (본예제에서는 File항목 메뉴) 이항목 메뉴를 pMenu에 받습니다. 이렇게 한개의 메뉴를 받는 이유는 컨텍스트 메뉴는 한개의 팝업메뉴를 이용하기 때문입니다. 이메뉴를 받은후에 이것을 로드하는 함수가 CMenu의 맴버인 TrackPopupMenu 입니다.


BOOL TrackPopupMenu(

UINT nFlags,//메뉴 출력 플러그

int x, int y, //x,y 출력 위치

CWnd* pWnd,// CWnd클래스 포인터

LPCRECT lpRect = NULL //출력 영역 보통 NULL로 설정안함

);

nFlags는 다음과 같은 값을 설정할수 있습니다.

TPM_CENTERALIGN : 중앙에 정렬하여 출력

TPM_LEFTALIGN : 좌측으로 정렬하여 출력

TPM_RIGHTALIGN: 우측으로 정렬하여 출력

TPM_LEFTBUTTON: 좌측 마우스 버튼이 클릭 되었을때

TPM_RIGHTBUTTON: 우측 마우스 버튼이 클릭되었을때


TrackPopupMenu을 이용하여 위의 pMenu를  우측마우스 버튼을 클릭하였을때 좌측을 기준으로 정렬하여 메뉴를 출력하는 OnContextMenu함수는 다음과 같습니다.


void CMainFrame::OnContextMenu(CWnd* pWnd, CPoint point)

{

       CMenu contmenu;

       CMenu *pMenu;

       contmenu.LoadMenu(IDR_MAINFRAME);

       pMenu=contmenu.GetSubMenu(0);

       pMenu->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON

                       ,point.x,point.y,this);     

}

위와 같이한후에 컴파일하고 실행시킨후에 우측버튼을 클릭하면 그림5와같은 화면이 출력됩니다.

       (그림 5) 컨텍스트 메뉴를 결합시킨 MExMenu 출력결과



2.도구바


도구바 수정하기


AppWizard를 이용하여 프로그램을 제작하면 기본적인 도구바가 설정되어 있습니다. 이도구바에서는 File Open,File New,File Save와 Edit항목 그리고 프린터와 도움말에 대한 항목들이 연결되어 있습니다. 이 도구바를 수정하고자 할때는 Project Workspace에서 ResourceView항목을 선택하고 Toolbar 항목을 선택한후에 IDR_MAINFRAME를 선택하면 됩니다. 그림 6은 MExMenu에서 IDR_MAINFRAME툴바를 선택한 화면 입니다.

            (그림 6)IDR_MAINFRAME Toolbar


툴바를 로드하고 버튼을 설정하면 설정된 그림이 메인 윈도우에 나타납니다. 이때 Colors 도구바를 이용하여 원하는 형태로 고치면 됩니다. 특정 툴바 버튼을 선택한다음 Alt+Enter키를 누르면 속성 대화상자 가 나타납니다. 이곳에서는 버튼의 가로와 세로크기 그리고 ID와 Prompt가 설정되어 있습니다. 그림 6에서는 Prompt에 "Create a new document\nNew"로 설정되어 있습니다. 여기에서 '\n'코드를 기준으로 우측에 있는 문장은 상태바에 출력되고 \n이후에 문장은 마우스가 툴바위에 위치할때 출력됩니다. 즉 풍선도움말(마우스가 툴바의 특정 버튼위에 있을때 마우스 옆에 조그마한 박스윈도우가 나오고 그곳에 글자가 출력되는 도움말)에 출력할 문장을 의미합니다. 실제로 MExMenu에서 툴바의 첫번째 버튼  즉 ID_FILE_NEW항목을 가진 버튼위에 마우스를 위치하게 되면 “New"라는 문자가 마우스 옆에 조그마한 박스로 출력이 될것입니다. 툴바는 메뉴와 연계해서 많이 사용합니다. 또는 툴바만 독립적으로 사용하기도 합니다. 지금까지 제작한 MExMenu에서 ”Window1"부터 "Window3"까지의 항목이 있습니다. 이항목을 툴바에 만들어 보겠습니다.

툴바의 마지막부분 비공간에 3개의 버튼을 만듭니다. 그림 7은 3개의 버튼을 만든 툴바의 형태입니다.

       (그림 7)IDD_MAINFRAME 툴바 수정화면

첫번째 빨간색 버튼의 'W'는 ID_WINDOW1  이며 다음으로 연결되면서 ID_WINDOW2,ID_WINDOW3 가 있는 형태로 만들었습니다. 위와 같이 만든 후에 컴파일하고 실행하고 새로만든 버튼 ID_WINDOW1에 위치하면 "Window1"이라는 풍선 도움말이 나오는 것을 볼수 있습니다.

기존의 도구바에서 새로운 버튼을 삽입하는 방법은 실제 코딩없이 단순하게 새로운 버튼만 추가하면 됩니다. IDD_MAINFRAME에 다양한 버튼을 만들어 넣으면서 실행시켜 보세요.



새로운 도구바 만들기

AppWizard에서 프로젝트를 만들었을때 만들어진 도구바외에 또다른 도구바를 만들고자 할경우가 있을것입니다. MExMenu 새로운 도구바를 하나 만들어 보겠습니다. MExMenu 프로젝트가 오픈 되어 있는 상태에서 Ctrl+6키를 누르거나 또는 Resource 도구바에서 “New Toolbar"항목을 클릭하여 새로운 도구바를 만듭니다.

그림 8은 새롭게 만든 도구바의 형태입니다.

       (그림 8)새롭게 만든 도구바 IDR_TOOLBAR

IDR_TOOLBAR는 각각의 ID가 ID_COLORGREEN,ID_COLORYELLOW,ID_COLOR_BLUE입니다. 이 도구바와 연결된 새로운 메뉴를 그림 9처럼 IDR_MAINFAME에 설정하였습니다.

       (그림 9) 새로 설정된 color 메뉴

메뉴에서 Green을 클릭하면 IDR_TOOLBAR에서 첫번째 툴바를 클릭한것과 같은 의미입니다. 이렇게 메뉴에 새로운 항목을 만들고 이와 연결되는 툴바를 만드는 것으로 툴바를 출력하기 위한 기본작업이 끝나게 됩니다.

툴바 자원을 만든다음 이자원을 연결하는 클래스를 설정해야 합니다. 툴바를 컨트롤하는 클래스는 CToolBar 입니다. MainFrm.h에 보면 다음과 같은 항목이 있을것입니다.

        CToolBar    m_wndToolBar;


위의 항목은 CToolBar 클래스형을 가진 맴버 변수 m_wndToolBar가 있으며 바로 이 맴버 변수는 기존에 설정된 IDR_MAINFRAME라는 툴바를 컨트롤 하는 변수입니다.

위의 변수와 같이 또하나의 CToolBar를 MainFrm.h에 설정합니다.

        CToolBar       m_wndColorBar;


위와 같이 설정한이유는 새로만든 툴바 IDR_TOOLBAR를 컨트롤하는 툴바를 만들기 위해서입니다. 툴바를 m_wndColorBar에 설정하는 내용은 CMainFrame의 OnCreate에서 합니다. OnCreate는 WM_CREATE메세지에 의해서 만들어진 함수입니다. CMainFrame의 OnCreate 함수는 프로젝트를 만들때 이미 만들어져 있습니다. 그이유는 OnCreate함수에서 기존의 툴바와 상태바를 설정해야 하기 때문입니다. 이함수에 보면 다음과 같은 내용이 있을것입니다.

        if (!m_wndToolBar.Create(this) ||

                !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))

        {

                TRACE0("Failed to create toolbar\n");

                return -1;      // fail to create

        }

위의 내용을 해석하자면 m_wndToolBar 윈도우를 만들고 이툴바 윈도우에 자원에 있는 툴바의 ID가 IDR_MAINFRAME 를 로드하라는 의미입니다. 만일 툴바윈도우를 만드는것이나 또는 툴바 자원으로 로드하는것이 실패하면 그럼 -1를 리턴하고 위함수를 빠져나가라는 의미입니다. TRACE0 라는 함수는 디버거 할때  output윈도우에 에러 메시지를 출력하라는 의미입니다. 프로그램을 Visual C++에서 실행하지 않고 그냥 독립적으로 실행하면 TRACE0라는 함수는 구동되지 않습니다.

위의 내용을 본다면 툴바를 로드하기 위해서는 윈도우를 만들어야 하며 그리고 LoadToolBar함수를 이용하여 자원에 설정한 툴바를 로드해야 합니다. 이와 같은 방법으로 IDR_TOOLBAR를 로드해 보겠습니다.

먼저 Create함수를 이용하여 툴바를 로드할 윈도우를 만듭니다.

       

        m_wndColorBar.Create(this);


CToolBar의 맴버 함수인 Create함수의 첫번째 인자는 CWnd* 로써 툴바의 부모윈도우의 CWnd포인터를 받습니다. 본 툴바의 부모윈도우는 CMainFrame입니다. 따라서 this라는 인자를 사용한것입니다.

위와 같이 툴바윈도우를 만든다음 자원을 로드합니다.

       

        m_wndColorBar.LoadToolBar(IDR_TOOLBAR);


위와 같이 하면 m_wndColorBar에 툴바를 로드하는 것이 완료됩니다. 이내용을 기록한 CMainFrame클래스의 맴버함수 OnCreate의 일부는 다음과 같습니다.


        if (!m_wndToolBar.Create(this) ||

                !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))

        {

                TRACE0("Failed to create toolbar\n");

                return -1;      // fail to create

        }

        m_wndColorBar.Create(this);//툴바윈도우를 만들고

        m_wndColorBar.LoadToolBar(IDR_TOOLBAR);//툴바를 로드한다.


수정한 두줄의 내용을 다음과 같이 고쳐서 에러를 검색하는 방법도 좋은 방법입니다.

if(!m_wndColorBar.Create(this) ||

       !m_wndColorBar.LoadToolBar(IDR_TOOLBAR))

{

       TRACE0("Failed to create toolbar\n");

       return -1;

}

즉 자동으로 기록된 내용과 같은 형식으로 프로그램을 하는 것입니다.

지금까지 한것은 툴바를 만든부분입니다. 이렇게 툴바를 만들고 난후에 이툴바가 도킹이 가능하게 하고 또한 메인프레임에 붙여 주어야 합니다.

도킹이 가능하다는 의미는 툴바가 프레임에 붙어 있었다가 떨어졌다가 할수 있다는 의미입니다. 툴바가 윈도우에 붙어 있다는 것을 Docking라고 하며 떨어져 있는 상태를 Floating라고 합니다. Docking를 하기 위해서는 서로 도킹을 하는 두개의 윈도구가 Doking할수 있는 준비가 되어 있어야 합니다. 마징가와 홈바파인터가 도킹할때 홈바파인더만 도킹할려고 해보았자 마징가가 나타나지 않으면 불가능합니다.(보통 잠실경기장이 갈라지면서 도킹할수 있도록 마징가가 나타난다고 하잖아요) 마찬가지로 CMainFrame 도 도킹이 가능하도록 되어 있어야 하며 툴바 또한 도킹이 가능하도록 되어 있어야 합니다. 이렇게 도킹이 가능하도록 만드는 함수가 EnableDocking 이함수는 CFrameWnd와 CControlBar 의 멤버 함수입니다. CToolBar는 CControlBar를 상속받은 클래스이기 때문에 이함수가 있습니다.

먼저 CMainFrame이 도킹이 가능하도록 하기 위해서는 다음과 같이 OnCreate함수에 EnableDocking함수가 설정되어 있어야 합니다.

       

EnableDocking(CBRS_ALIGN_ANY);


실제로 보면 CMainFrame의 OnCreate함수 안에는 EnableDocking함수가 위과 같이 기록되어 있습니다. 따라서 직접 기록할 필요는 없습니다. 위와 같은 상태에서 새로만든 m_wndColorBar 또한 도킹이 가능한 상태로 만듭니다.


        m_wndColorBar.EnableDocking(CBRS_ALIGN_ANY);


위와 같이하면 툴바 또한 도킹이 가능한 상태가 되는 것입니다. 이상태에서 툴바를 윈도우에 붙일때 (Docking 시킬때) CMainFrame의 맴버 함수인 DockControlBar 함수를 이용합니다. 이함수는 컨트롤바를 프레임에 붙일때 사용하는 함수입니다. m_nwdColorBar를 붙이고자 한다면 다음과 같이 하면 됩니다.


        DockControlBar(&m_wndColorBar);

위와 같이하면 컨트롤바가 바로 프레임에 도킹이 되는 것입니다. DockControlBar함수와 대조되는 함수가 FloatControlBar 입니다. 이것은 도킹되었던 컨트롤 바를 다시 분리시킨는 함수입니다.

본내용을 삽입한 CMainFrame의 OnCreate함수의 일부는  다음과 같습니다.


        m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);

        m_wndColorBar.EnableDocking(CBRS_ALIGN_ANY);//<--칼라바 활성

        EnableDocking(CBRS_ALIGN_ANY);

        DockControlBar(&m_wndToolBar);

        DockControlBar(&m_wndColorBar);//<--칼라바 도킹


지금까지 수정하고 컴파일하고 실행시키면 칼라바가 회색형태로 메뉴에 붙어 있는 것을 보실수 있을것입니다. m_wndColorBar에 이제 마지막 한작업으로 풍선 도움말이 가능하도록 해야 합니다. 풍선 도움말이 가능하도록 하기 위해서는 툴바의 스타일에 CBRS_TOOLTIPS 의 스타일을 삽입해야 합니다. 실제 OnCreate함수에서 기존에 설정된 m_wndToolBar의 스타일에 CBRS_TOOLTIPS 설정한 내용이 다음과 같이 기록되어 있습니다.

       

        m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |

                CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);


CToolBar의 맴버중에 GetBarStyle()는 현재 스타일을 얻는 함수이고 CBRS_TOOLTIPS는 툴팁(풍선도움말 기능)이 가능하게 하는 것이면 CBRS_FLYBY 는 출력 메시지 문자가 갱신되면 바로 툴팁에 수정될수 있도록 하는 스타읿니다. CBRS_SIZE_DYNAMIC 은 컨트롤바의 크기가 자유롭게 변하는 형태를 의미압니다. 위의 함수를 보면 GetBarStyle()에 의해 툴바의 스타일을 얻고 이툴바에 3개의 스타일을 추가하여 이값을 SetBarStyle함수에의해서 툴바 스타일에 저장한것입니다. 위와 같은 방법으로 m_wndColorBar또한 툴팁기능이 가능하고 윈도우 크기가 자유롭게 변화될수 있도록 하기 위해서 다음과 같이 합니다.


        // TODO: Remove this if you don't want tool tips or a resizeable toolbar

        m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |

                CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);

        //칼라 바설정한 부분

        m_wndColorBar.SetBarStyle(m_wndColorBar.GetBarStyle() |

                CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);


위와 같이하면 바로 m_wndColorBar또한 풍선 도움말이 가능하도록 한것입니다.

CMainFrame의 OnCreate의 전체 소스는 다음과 같습니다.


int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

       if (CFrameWnd::OnCreate(lpCreateStruct) == -1)

               return -1;

       

       if (!m_wndToolBar.Create(this) ||

               !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))

       {

               TRACE0("Failed to create toolbar\n");

               return -1;      // fail to create

       }

       m_wndColorBar.Create(this);//툴바윈도우를 만들고

       m_wndColorBar.LoadToolBar(IDR_TOOLBAR);//툴바를 로드한다.

       if (!m_wndStatusBar.Create(this) ||

               !m_wndStatusBar.SetIndicators(indicators,

                 sizeof(indicators)/sizeof(UINT)))

       {

               TRACE0("Failed to create status bar\n");

               return -1;      // fail to create

       }


// TODO: Remove this if you don't want tool tips or a resizeable toolbar

       m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |

               CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);

       m_wndColorBar.SetBarStyle(m_wndColorBar.GetBarStyle() |

               CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);

       // TODO: Delete these three lines if you don't want the toolbar to

       //  be dockable

       m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);

       m_wndColorBar.EnableDocking(CBRS_ALIGN_ANY);//<--칼라바 활성

       EnableDocking(CBRS_ALIGN_ANY);

       DockControlBar(&m_wndToolBar);

       DockControlBar(&m_wndColorBar);//<--칼라바 도킹


       return 0;

}

위와 같이 OnCreate함수를 수정한후에 컴파일하고 실행시키면 그림 10과 같은 화면이 출력됩니다.

             (그림 10) MExMenu에 새로운 도구바 삽입형태


도구바에 보이가와 감추기

프로젝트를 만들면 자동적으로 설정되어 있는 View메뉴의 Toolbar항목을 선택하면 화면에 보임과 감추어짐이 토글로 이루어 집니다. 새로만든 칼라 툴바 또한 이런기능을 넣어 보겟습니다. 프레임 윈도우에 설정된 도구바를 감추거나 보이고자 할때는 ShowControlBar 함수를 사용합니다. 이함수는 CMainFrame클래스의 맴버 함수로써 다음과 같은 형태입니다.


CFrameWnd::ShowControlBar

void ShowControlBar( CControlBar* pBar, BOOL bShow, BOOL bDelay );


pBar는 화면에 보이거나 또는 감출 도구바클래스의 포인터 입니다. bShow가 TRUE이면 도구바를 화면에 보여주고 bShow가 FALSE이면 화면에 감춥니다. bDelay값이 TRUE이면 도구바를 화면에 보여줄때 약간의 지연이 있으며 FALSE이면 지연이 없이 바로 보여줍니다. 예를 들어서 m_wndColorBar를 화면에서 감추고자 한다면 다음과 같이 할수 있습니다.

ShowControlBar(&m_wndColorBar,TRUE,FALSE);

MExMenu에서 View메뉴에 ControlBar항목을 추가합니다. 이항목의 ID는 ID_COLORBAR 입니다.

         (그림 11) 메뉴에 Color Bar항목을 추가한 형태

위와 같이 메뉴에 ColorBar를 설정한후에 클래스위저드를 이용하여 이 항목을 선택했을때의 함수와 UPDATE_COMMAND_UI 함수를 만듭니다. 그리고 이함수에 다음과 같이 코딩을 합니다.


void CMainFrame::OnColorbar()

{

       // TODO: Add your command handler code here

       if(m_wndColorBar.IsWindowVisible())

               ShowControlBar(&m_wndColorBar,FALSE,FALSE);

       else

               ShowControlBar(&m_wndColorBar,TRUE,FALSE); 

}


void CMainFrame::OnUpdateColorbar(CCmdUI* pCmdUI)

{

       // TODO: Add your command update UI handler code here

       if(m_wndColorBar.IsWindowVisible())

               pCmdUI->SetCheck(TRUE);

       else

               pCmdUI->SetCheck(FALSE);

       

}


IsWindowVisible함수는 윈도우가 현재 화면에 보이는가 안보이는 가를 확인하는 CWnd의 맴버 함수입니다. 이함수를 실행시켰을때 현재 윈도우가 보이면 TRUE를 보이지 않으면 FALSE를 리턴합니다. CToolBar또한 윈도우이기 때문에 CWnd를 상속받았습니다. (“모든 윈도우는 CWnd로 부터시작된다” 이거 꼭 기억하셔야 합니다. 정말로 꼭 기억하셔야 합니다!) 따라서 CToolBar에서도 IsWindowVisible함수를 이용할수 있는 것입니다. OnColorbar()  함수에서 m_wndColorBar.IsWindowVisible() 함수를 실행하였을때 TRUE가 리턴되면 툴바가 화면에 보이는 형태이니까 감추고 그리고 그외는 툴바가 화면에 보이지 않은 형태이므로 화면에 보이는 함수가 실행되는 것입니다.

OnUpdateColorbar 함수에서는 m_wndColorBar.IsWindowVisible() 함수를 이용하여 현재 윈도우가 화면에 보이면 메뉴를 체크하고 화면에 보이지 않으면 메뉴를 FALSE한것입니다.

이제 마지막으로 Color메뉴에서 Green,Yellow,Blue항목를 클릭했을때의 함수를 CMainFrame에 만들어 보겠습니다. 만든 함수는 다음과 같습니다.


void CMainFrame::OnColorgreen()

{

       // TODO: Add your command handler code here

       AfxMessageBox("green"); 

}


void CMainFrame::OnColoryellow()

{

       // TODO: Add your command handler code here

       AfxMessageBox("yellow");              

}


void CMainFrame::OnColorblue()

{

       // TODO: Add your command handler code here

       AfxMessageBox("blue");        

}


위의 3개의 함수는 메뉴를 선택햇을때 단순하게 해당 메뉴의 항목문자를 메시지 박스로 출력할뿐입니다. 이함수를 만들기 전에는 툴바자체게 회색형태로 되어 있을것입니다. 이함수를 만들어 줌으로써 툴바자체가 원하는 색으로 나올것입니다.

위와 같이 한후 컴파일하고 실행하면 그림 12와 같은 화면이 출력됩니다.

               (그림 12) MExMenu 출력 결과



3.다이얼로그바 (Dialog Bar)

다이얼로그바란 대화상자와 같은 형태로인데 도구바처럼 프레임에 도킹이 되고 또는 플로팅이 되는 형태의 바를 이야기합니다.

다이얼로그바 만들기

다이얼로그바를 만들기위해서는 기본적으로 대화상자형태의 자원을 만들어야 합니다. MExMenu프로그램에 다이얼로드바를 붙이기 위해서 하나의 대화상자 자원을 만든 형태가 그림 13과 같습니다.

       (그림 13) 다이얼로그바에 설정할 대화상자 형태

다이얼로그바에 설정할 대화상자는 그림 13과 같이 style가 Child이어야 합니다. 또한 Border은 None로 하였습니다. Child라는 것은 부모윈도우가 있고 자신이 부모윈도우에 붙어서 출력할수 있는 형태라는 것입니다. 위의 대화상자 ID는 IDD_DIALOG1으로 설정되어 있습니다. 이 대화상자를 컨트롤 하는 다이얼로그바 클래스는 CDialogBar입니다. MainFrm.h에 에 CDialogBar클래스이 형을 가진 맴버 변수를 다음과 같이 설정합니다.

        CDialogBar m_wndDialogBar;


이제 m_wndDialogBar에 그림 13처럼 만든 IDC_DIALOG1를 로드하면 됩니다. 툴바를 만드는것과 달리 다이얼로그바는 Create 함수 한개만으로 자원을 로드하면서 설정할수 있습니다.  CDialogBart의 Create함수는 다음과 같습니다.


CDialogBar::Create

BOOL Create( CWnd* pParentWnd, UINT nIDTemplate, UINT nStyle, UINT nID );


pParentWnd는 부모윈도우 클래스 포인터 이며 nIDTemplate는 로드할 대화상자 자원 ID입니다. nStyle는 어떤 형태로 도구바를 출력시킬것인가의 플러그입니다. 이플러그는 CBRS_계열의 값을 취할수 있는데 CBRS_TOP는 도킹시 상단부에 CBRS_LEFT는 도킹시 좌측에 CBRS_BOTTOM 하단분에 CBRS_RIGHT는 우측에 해당됩니다. nID는 이 도구바 컨트롤 ID입니다. 이번호는 여러분이 원하는 대로 설정할수 있습니다. 이번호는 WM_COMMAND에서 wParam으로 넘어올때 LOWORD에 설정되는 ID입니다. 일반 프로그램에서는 별로 많이 사용되지 않기 때문에 아무값이나 넣어도 됩니다.

CMainFrame에 설정한 맴버변수 m_wndDialogBar 에 IDC_DIALOG1를 로드하고 다이얼로그바를 만드는 Create함수는 다음과 같습니다.


        m_wndDialogBar.Create(this,IDD_DIALOG1,CBRS_LEFT,555);


위와 같이한후 도킹을 하는 방법은 CToolBar와 같습니다. CToolBar는 CControlBar를 상속받았으며 마찬가지로 CDialogBar또한 CControlBar를 상속받았기 때문입니다. 도킹및 플로팅은 모두 CControlBar의 함수를 이용합니다.

즉 도킹이 가능하게 EnableDocking 함수를 사용하고 다음 MainFrame의 DockControlBar 함수를 이용하여 대화상자를 붙입니다. DockControlBar를 사용하여 대화상자를 붙이면 Create에 설정한 CBRS_LEFT에 의해서 윈도우 좌측에 붙게 됩니다. 대화상자를 붙인 CMainFrame의 OnCreate함수는 다음과 같습니다.


int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

       if (CFrameWnd::OnCreate(lpCreateStruct) == -1)

               return -1;

       

       if (!m_wndToolBar.Create(this) ||

               !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))

       {

               TRACE0("Failed to create toolbar\n");

               return -1;      // fail to create

       }

       m_wndColorBar.Create(this);//툴바윈도우를 만들고

       m_wndColorBar.LoadToolBar(IDR_TOOLBAR);//툴바를 로드한다.

       m_wndDialogBar.Create(this,IDD_DIALOG1,CBRS_LEFT,555);


       if (!m_wndStatusBar.Create(this) ||

               !m_wndStatusBar.SetIndicators(indicators,

                 sizeof(indicators)/sizeof(UINT)))

       {

               TRACE0("Failed to create status bar\n");

               return -1;      // fail to create

       }


// TODO: Remove this if you don't want tool tips or a resizeable toolbar

       m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |

               CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);

       m_wndColorBar.SetBarStyle(m_wndColorBar.GetBarStyle() |

               CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);

       // TODO: Delete these three lines if you don't want the toolbar to

       //  be dockable

       m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);

       m_wndColorBar.EnableDocking(CBRS_ALIGN_ANY);//<--칼라바 활성

       m_wndDialogBar.EnableDocking(CBRS_ALIGN_ANY);

       EnableDocking(CBRS_ALIGN_ANY);

       DockControlBar(&m_wndToolBar);

       DockControlBar(&m_wndColorBar);//<--칼라바 도킹

       DockControlBar(&m_wndDialogBar);

       return 0;

}

위와 같이 수정을 한후에 컴파일하고 실행하면 그림 14와 같은 화면이 출력됩니다.

             (그림 14) MExMenu에 다이얼로그바를 추가한 화면



다이얼로그바 보이기와 감추기

다이얼로그바의 보이기와 감추기는 툴바와 같습니다. 툴바를 만들때와 같이 View메뉴에 DialogBar라는 항목을 만들고 이항목과 연결되는 두개의 함수( COMMAND 와 UPDATE_COMMAND_UI 에의한 함수)를 만듭니다. 이함수를 수정한 소스는 다음과 같습니다.


//메뉴에서 Dialog Bar 선택화면

void CMainFrame::OnDialogbar()

{

       if(m_wndDialogBar.IsWindowVisible())

               ShowControlBar(&m_wndDialogBar,FALSE,FALSE);

       else

               ShowControlBar(&m_wndDialogBar,TRUE,FALSE);       

       

}

//메뉴의 체크

void CMainFrame::OnUpdateDialogbar(CCmdUI* pCmdUI)

{

       // TODO: Add your command update UI handler code here

       if(m_wndDialogBar.IsWindowVisible())

               pCmdUI->SetCheck(TRUE);

       else

               pCmdUI->SetCheck(FALSE);   

}

위와 같이 코딩을 한후에 컴파일하고 실행시킨후에 메뉴에서 DialogBar라는 항목을 클릭하면 화면에서 다이얼로그바가 토글형태로 나타나거나 사라지거나 합니다. 그림 15는 메뉴에서 DialogBar항목을 선택한 화면입니다.


               (그림 15)DialogBar 항목 선택화면



다이얼로그바 이벤트 얻기

툴바는 메뉴와 연결된형태로 존재하며 또한 툴바에만 ID를 설정하였다하여도 클래스 위저드를 이용하여 선택된 항목을 실행하는 함수를 만들수 있습니다. 그러나 다이얼로그바는 그성격이 다릅니다. 다이얼로그바에는 여러 자원들이 있으며 그자원들에 해당하는 다양한 이벤트가 있습니다. 예를 들어서 MExMenu에 설정된 다이얼로그바에는 콤보박스가 있습니다. 이콤보박스에서 선택될수 있는 이벤트는 마우스의 이벤트 포커스의 이동이벤트 데이터의 선택이벤트등 여러개입니다. 이런 이벤트를 가로채서 실행하는 함수를 만들어야 하는데 안타 깝게도 이함수는 클래스위저드를 이용하여 만들수가 없습니다. 그이유는 클래스위저드에 등록되어 있는 클래스가 없기 때문입니다. 다이얼로그바는 클래스 위저드로 등록하여 만든것이 아니고 대화상자를 만든다음 이대화상자를 CDialog맴버의 변수로 연결한것이기 때문입니다. 그렇다고 이벤트를 만들지 못하는 것이 아닙니다. MFC의 매크로에는 이런 문제를 해결하기 위해서 ON_CBN ,ON_LBN,ON_EN,ON_BN 계열의 메시지 맵핑 매크로를 만들어 두었습니다. ON_CBN 은 콤보박스에서 이벤트가 발생하였을때 의 매세지 매크로이며 ON_LBN은 리스트 박스에서 ,ON_EN은 에디터 박스에서 ON_BN은 버튼에서 입니다.

MExMenu에서 콤보박스에서 선택된 항목이 바뀌었을때의 메시지 함수를 만들어 보겠습니다. CMainFrame의 소스 즉 MainFrm.cpp에는 다음과 같은 항목이 있을것입니다.


BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)

       //{{AFX_MSG_MAP(CMainFrame)

       ON_WM_CREATE()

       ON_COMMAND(ID_EDIT_CUT, OnEditCut)


:

       ON_UPDATE_COMMAND_UI(IDD_DIALOGBAR, OnUpdateDialogbar)

       ON_CBN_SELCHANGE(IDC_COMBO,OnComboChange)//<--추가

       //}}AFX_MSG_MAP

END_MESSAGE_MAP()


위의 것은 바로 메시지 맵핑 메크로를 설정한 부분입니다. ON_CBN계열의 메시지에서 새로운 항목이 선택되었을때 발생되는 메시지 매크로는 ON_CBN_SELCHANGE입니다. 이매크로 함수를 설정할때 첫번째 인자는 윈도우 ID입니다. 자원에설정한 콤보박스 ID를 이곳에 기록하는 것입니다. 여러개의 콤보박스에서 같은 ON_CBN_SELCHANGE 가 발생됩니다. 따라서 어떤 윈도우에서 발생한 ON_CBN_SELCHANGE 설정하기 위함입니다. 다음 이때 수행할 함수를 기록합니다. 이함수는 여러분의 의미에 맞게 설정해 주면 됩니다. 규칙이 없기 때문입니다. 본예제에서는 OnComboChange라고 기록하였습니다.

OnComboChange라고 기록하였다면 헤더에 또한 이함수를 설정해 주어야 합니다. 다음은 헤더에 이함수를 설정한 형태입니다.


// Generated message map functions

protected:

       //{{AFX_MSG(CMainFrame)

       afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

       afx_msg void OnEditCut();

               :

       afx_msg void OnUpdateDialogbar(CCmdUI* pCmdUI);

       afx_msg void OnComboChange();//<--삽입한 부분

       //}}AFX_MSG


메시지 이벤트 함수는 //{{AFX_MSG(CMainFrame) 과 //}}AFX_MSG 사이에 afx_msg라는 형을 설정한후에 함수를 만들어 줍니다.

메시지 메크로에서 OnComboChange라고 설정하였다면 헤더에 또한 위와 같이 설정해야 합니다. 이렇게 설정한후에 이제 실제적으로 구동하는 함수를 제작합니다.CMainFrame의 소스 부분 즉 MainFrm.cpp에 다음과 같은 소스를 만듭니다.




void CMainFrame::OnComboChange()

{

}

위와 같이 하면 콤보박스에서 새로운 항목을 선택하였을때 OnComboChange함수가 실행되는 것입니다. 자원에서 콤보박스를 선택하고 세로운 데이터를 기록합니다. 그림 16은 콤보박스에 one - four까지 기록한 화면입니다.

       (그림 16) 콤보박스에 데이터 설정화면


그림 16처첨 콤보박스에 데이터를 설정하면 프로그램이 실행될때 데이터가 콤보박스에 기록됩니다. 이제 OnComboChange함수에서 콤보박스에서 세로운 데이터를 선택했을때 선택된 항목이 메시지로 출력되는 내용을 만들어 보겠습니다. 내용은 다음과 같습니다.


void CMainFrame::OnComboChange()

{

       CComboBox *pWnd

     pWnd=(CComboBox*)m_wndDialogBar.GetDlgItem(IDC_COMBO);

       int num=pWnd->GetCurSel();

       CString message;

       pWnd->GetLBText(num,message);

       AfxMessageBox(message);

}


GetDlgItem은 자원에 있는 ID의 CWnd를 받는 함수입니다. (전에 설명한 함수입니다) 콤보박스는 m_wndDilaogBar안에 있으므로 m_wndDialogBar의 맴버함수 GetDlgItem을 실행시킵니다. 이렇게 되면 CWnd가 넘어옵니다. 이것을 CComboBox로 전환합니다. 이렇게 전환해야 하는 이유는 우리가 원하는 형은 CWnd가 아니라 CWnd를 상속받은 CComboBox이기 때문입니다. 이렇게 얻은 콤보박스 클래스의 포인터를 이용하여 현재선택된 번호를 얻고 그리고 그 번호에 해당하는 데이터를 얻어서 화면에 출력하는 것입니다. OnComboChange함수안에 있는 내용은 전장에서 이미 다설명한 내용입니다. 위의 내용을 이해하지 못한다면 전장을 한번 다시 보시기 바랍니다.

위와 같이 한후에 컴파일하고 실행한후 콤보박스에서 데이터를 선택하면 그림 17처럼 선택한 내용이 메시지 박스로 출력됩니다.

       (그림 17) 콤보박스에서 새로운 데이터를 선택했을때의 화면

본예에서는 ON_CBN계열의 한개의 메시지만 컨트롤하는 함수를 만들었습니다. 여러분은 본예를 가지고 에디터박스에서 데이터를 입력하고 포커스가 사라졌을때 또는 라디오 버튼을 클릭했을때의 메시지를 만들어 보시기 바랍니다. 함수를 만드는 방법은 ON_CBN 계열과 비슷합니다. 어떤 메시지들이 있는가를 확인하고자 한다면 당연히 도움말을 참조하시면 됩니다. (꼭 만들어 보시기 바랍니다)


4.상태바

상태바는 현재의 상태를 출력하는 단순한 윈도우 형태입니다. 그림 17에서 보듯이 프로젝트를 새로만들면 상태바에는 Caps Lock 키와 NumLock키 그리고 Scroll Lock가 설정되어 있습니다. 이 3개의 키중 한개가 눌려져 있다면 눌려져 잇는 키의 문자가 상태바에 설정됩니다. 그림 17체서는 Num Lock가 눌려져 있는 상태입니다.상태바를 컨트롤하는 클래스는 CStatusBar입니다. 이클래스 또한 CControlBar를 상속받았기 때문에 툴바와 기능이 같습니다. 다만 상태바는 현재 어떤 상태이가 상태를 문자열로 출력하는 기능을 많이합니다.MainFrm.h즉 CMainFrame의 헤더에 보면 다음과 같이 상태바를 설정한것이 보일것입니다.

       

CStatusBar  m_wndStatusBar;



상태바에 Insert 키 상태 넣기


보통 워드 프로세서에서는 상태바에 Insert키가 눌렸을때 토글 형식으로 “삽입”,“수정”이 나타납니다. Insert의 토글 키를 넣고자 한다면 MainFrm.cpp에 설정되어 있는 indicators 를 수정합니다. 다음은 MainFrm.cpp 에 설정되어 있는 indicatiors를 수정한 내용입니다.


static UINT indicators[] =

{

       ID_SEPARATOR,           // status line indicator

       ID_INDICATOR_CAPS,

       ID_INDICATOR_NUM,

       ID_INDICATOR_SCRL,

       ID_INDICATOR_OVR

};


위의 indicators에 ID_INDICATOR_OVR를 설정하면 상태바에 Insert키에 대응하는 값이 출력됩니다. 위의 배열을 호출하는 함수는 CMainFrame의 OnCreate에 있습니다. 이 내용은 다음과 같습니다.

m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT))


SetIndicators는 상태바에 지시자 윈도우를 설정하는 함수입니다. 이때 설정하는 지시자의 내용은 indicators에 있으므로 이값을 설정하는 것이고 지시자의 크기가 sizeof함수로 설정되어 있습니다. 즉 지시자의 배열수가 두번째 인자로 설정되는 것입니다. 위와 같이 설정한후에 컴파일하면 상태바에 Insert항목에 대응하는 영역이 출력될것입니다.


상태바에 메시지 출력

상태바에 메시지를 출력하는 방법은 매우 간단합니다. 상태바 또한 CWnd를 상속받았기 때문에 SetWindowText함수를 이용하면 됩니다. 예를 들어서  상태바에 “안녕하세요” 라는 메시지를 출력하고자 한다면 다음과 같이 하면 됩니다.


m_wndStatusBar.SetWindowText("안녕하세요“);


메뉴나 툴바를 선택하지 않았을때도 현재의 상태를 알고자 한다면 바로 위의 함수를 이용하시면 쉽게 현재의 상태를 출력할수 있는 것입니다.



6.MExMenu의 CMainFrame의 소스

본장에서 설명한 내용은 CMainFrame에서만 코딩을 하였습니다. 툴바 다이얼로그바 상태바 등을 핸들링하는 메인 프레임에 한정되어 있기 때문입니다. 책이 두꺼어 지지 않도록 소스를 기재 하지 않으려고 했으나 본소스는 필요할것 같아서 기록합니다.

(프로그램 소스)

// MainFrm.h : interface of the CMainFrame class

//

/////////////////////////////////////////////////////////////////////////////


#if !defined(AFX_MAINFRM_H__9C6B0C2A_C4DE_11D1_AC4E_006097AEB8A7__INCLUDED_)

#define AFX_MAINFRM_H__9C6B0C2A_C4DE_11D1_AC4E_006097AEB8A7__INCLUDED_


#if _MSC_VER >= 1000

#pragma once

#endif // _MSC_VER >= 1000


class CMainFrame : public CFrameWnd

{

protected: // create from serialization only

        CMainFrame();

        DECLARE_DYNCREATE(CMainFrame)


// Attributes

public:

        BOOL m_bCopy;

        int m_nWindowNum;

// Operations

public:


// Overrides

        // ClassWizard generated virtual function overrides

        //{{AFX_VIRTUAL(CMainFrame)

        virtual BOOL PreCreateWindow(CREATESTRUCT& cs);

        //}}AFX_VIRTUAL


// Implementation

public:

        virtual ~CMainFrame();

#ifdef _DEBUG

        virtual void AssertValid() const;

        virtual void Dump(CDumpContext& dc) const;

#endif


protected:  // control bar embedded members

        CStatusBar  m_wndStatusBar;//상태바

        CToolBar    m_wndToolBar;//메인 툴바

        CToolBar       m_wndColorBar;//칼라 툴바

        CDialogBar m_wndDialogBar;//다이얼로그바

// Generated message map functions

protected:

        //{{AFX_MSG(CMainFrame)

        afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

        afx_msg void OnEditCut();

        afx_msg void OnEditCopy();

        afx_msg void OnUpdateEditPaste(CCmdUI* pCmdUI);

        afx_msg void OnWindow1();

        afx_msg void OnWindow2();

        afx_msg void OnWindow3();

        afx_msg void OnUpdateWindow1(CCmdUI* pCmdUI);

        afx_msg void OnUpdateWindow2(CCmdUI* pCmdUI);

        afx_msg void OnUpdateWindow3(CCmdUI* pCmdUI);

        afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);

        afx_msg void OnColorbar();

        afx_msg void OnUpdateColorbar(CCmdUI* pCmdUI);

        afx_msg void OnColorgreen();

        afx_msg void OnColoryellow();

        afx_msg void OnColorblue();

        afx_msg void OnDialogbar();

        afx_msg void OnUpdateDialogbar(CCmdUI* pCmdUI);

        afx_msg void OnComboChange();//다이얼로그바에서 콤보박스 이벤트

        //}}AFX_MSG

        DECLARE_MESSAGE_MAP()

};


/////////////////////////////////////////////////////////////////////////////


//{{AFX_INSERT_LOCATION}}

// Microsoft Developer Studio will insert additional declarations immediately before the previous line.


#endif // !defined(AFX_MAINFRM_H__9C6B0C2A_C4DE_11D1_AC4E_006097AEB8A7__INCLUDED_)

// MainFrm.cpp : implementation of the CMainFrame class

//


#include "stdafx.h"

#include "MExMenu.h"


#include "MainFrm.h"


#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif


/////////////////////////////////////////////////////////////////////////////

// CMainFrame


IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)


BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)

        //{{AFX_MSG_MAP(CMainFrame)

        ON_WM_CREATE()

        ON_COMMAND(ID_EDIT_CUT, OnEditCut)

        ON_COMMAND(ID_EDIT_COPY, OnEditCopy)

        ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste)

        ON_COMMAND(ID_WINDOW1, OnWindow1)

        ON_COMMAND(ID_WINDOW2, OnWindow2)

        ON_COMMAND(ID_WINDOW3, OnWindow3)

        ON_UPDATE_COMMAND_UI(ID_WINDOW1, OnUpdateWindow1)

        ON_UPDATE_COMMAND_UI(ID_WINDOW2, OnUpdateWindow2)

        ON_UPDATE_COMMAND_UI(ID_WINDOW3, OnUpdateWindow3)

        ON_WM_CONTEXTMENU()

        ON_COMMAND(ID_COLORBAR, OnColorbar)

        ON_UPDATE_COMMAND_UI(ID_COLORBAR, OnUpdateColorbar)

        ON_COMMAND(ID_COLORGREEN, OnColorgreen)

        ON_COMMAND(ID_COLORYELLOW, OnColoryellow)

        ON_COMMAND(ID_COLORBLUE, OnColorblue)

        ON_COMMAND(IDD_DIALOGBAR, OnDialogbar)

        ON_UPDATE_COMMAND_UI(IDD_DIALOGBAR, OnUpdateDialogbar)

        ON_CBN_SELCHANGE(IDC_COMBO,OnComboChange)

        //}}AFX_MSG_MAP

END_MESSAGE_MAP()


static UINT indicators[] =

{

        ID_SEPARATOR,           // status line indicator

        ID_INDICATOR_CAPS,

        ID_INDICATOR_NUM,

        ID_INDICATOR_SCRL,

        ID_INDICATOR_OVR

};


/////////////////////////////////////////////////////////////////////////////

// CMainFrame construction/destruction


CMainFrame::CMainFrame()

{

        // TODO: add member initialization code here

        m_bCopy=FALSE;

        m_nWindowNum=0;

}


CMainFrame::~CMainFrame()

{

}


int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

        if (CFrameWnd::OnCreate(lpCreateStruct) == -1)

                return -1;

       

        if (!m_wndToolBar.Create(this) ||

                !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))

        {

                TRACE0("Failed to create toolbar\n");

                return -1;      // fail to create

        }

        m_wndColorBar.Create(this);//툴바윈도우를 만들고

        m_wndColorBar.LoadToolBar(IDR_TOOLBAR);//툴바를 로드한다.

        //다이얼로그바 만들기

        m_wndDialogBar.Create(this,IDD_DIALOG1,CBRS_LEFT,555);


        if (!m_wndStatusBar.Create(this) ||

                !m_wndStatusBar.SetIndicators(indicators,

                  sizeof(indicators)/sizeof(UINT)))

        {

                TRACE0("Failed to create status bar\n");

                return -1;      // fail to create

        }


        // TODO: Remove this if you don't want tool tips or a resizeable toolbar

        m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |

                CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);

        //칼라바를 풍선 도움말의 기능이 되도록 스타일 변경

        m_wndColorBar.SetBarStyle(m_wndColorBar.GetBarStyle() |

                CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);

        // TODO: Delete these three lines if you don't want the toolbar to

        //  be dockable

        m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);

        m_wndColorBar.EnableDocking(CBRS_ALIGN_ANY);//<--칼라바 활성

        //다이얼로그바 도킹 설정설정

        m_wndDialogBar.EnableDocking(CBRS_ALIGN_ANY);

        EnableDocking(CBRS_ALIGN_ANY);

        DockControlBar(&m_wndToolBar);

        DockControlBar(&m_wndColorBar);//<--칼라바 도킹

        //다이얼로그바 를 메인프레임에 붙임

        DockControlBar(&m_wndDialogBar);

        return 0;

}


BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

{

        // TODO: Modify the Window class or styles here by modifying

        //  the CREATESTRUCT cs


        return CFrameWnd::PreCreateWindow(cs);

}


/////////////////////////////////////////////////////////////////////////////

// CMainFrame diagnostics


#ifdef _DEBUG

void CMainFrame::AssertValid() const

{

        CFrameWnd::AssertValid();

}


void CMainFrame::Dump(CDumpContext& dc) const

{

        CFrameWnd::Dump(dc);

}


#endif //_DEBUG


/////////////////////////////////////////////////////////////////////////////

// CMainFrame message handlers

//Edit 메뉴에서 항목 선택

void CMainFrame::OnEditCut()

{

        // TODO: Add your command handler code here

        m_bCopy=TRUE;       

}


void CMainFrame::OnEditCopy()

{

        // TODO: Add your command handler code here

        m_bCopy=TRUE;              

}


void CMainFrame::OnUpdateEditPaste(CCmdUI* pCmdUI)

{

        // TODO: Add your command update UI handler code here

        pCmdUI->Enable(m_bCopy);

}


void CMainFrame::OnWindow1()

{

        // TODO: Add your command handler code here

        m_nWindowNum=1;     

}


void CMainFrame::OnWindow2()

{

        // TODO: Add your command handler code here

        m_nWindowNum=2;     

}


void CMainFrame::OnWindow3()

{

        // TODO: Add your command handler code here

        m_nWindowNum=3;     

}


void CMainFrame::OnUpdateWindow1(CCmdUI* pCmdUI)

{

        // TODO: Add your command update UI handler code here

        if(m_nWindowNum==1)

                pCmdUI->SetCheck(TRUE);

        else

                pCmdUI->SetCheck(FALSE);

}


void CMainFrame::OnUpdateWindow2(CCmdUI* pCmdUI)

{

        // TODO: Add your command update UI handler code here

        if(m_nWindowNum==2)

                pCmdUI->SetCheck(TRUE);

        else

                pCmdUI->SetCheck(FALSE);   

}


void CMainFrame::OnUpdateWindow3(CCmdUI* pCmdUI)

{

        // TODO: Add your command update UI handler code here

        if(m_nWindowNum==3)

                pCmdUI->SetCheck(TRUE);

        else

                pCmdUI->SetCheck(FALSE);   

}


void CMainFrame::OnContextMenu(CWnd* pWnd, CPoint point)

{

        CMenu contmenu;

        CMenu *pMenu;

        contmenu.LoadMenu(IDR_MAINFRAME);

        pMenu=contmenu.GetSubMenu(0);

        pMenu->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON,point.x,point.y,this);       

}



void CMainFrame::OnColorbar()

{

        // TODO: Add your command handler code here

        if(m_wndColorBar.IsWindowVisible())

                ShowControlBar(&m_wndColorBar,FALSE,FALSE);

        else

                ShowControlBar(&m_wndColorBar,TRUE,FALSE); 

}


void CMainFrame::OnUpdateColorbar(CCmdUI* pCmdUI)

{

        // TODO: Add your command update UI handler code here

        if(m_wndColorBar.IsWindowVisible())

                pCmdUI->SetCheck(TRUE);

        else

                pCmdUI->SetCheck(FALSE);

       

}


void CMainFrame::OnColorgreen()

{

        // TODO: Add your command handler code here

        AfxMessageBox("green"); 

}


void CMainFrame::OnColoryellow()

{

        // TODO: Add your command handler code here

        AfxMessageBox("yellow");              

}


void CMainFrame::OnColorblue()

{

        // TODO: Add your command handler code here

        AfxMessageBox("blue");        

}

//메뉴에서 Dialog Bar 선택화면

void CMainFrame::OnDialogbar()

{

        if(m_wndDialogBar.IsWindowVisible())

                ShowControlBar(&m_wndDialogBar,FALSE,FALSE);

        else

                ShowControlBar(&m_wndDialogBar,TRUE,FALSE);       

       

}

//메뉴의 체크

void CMainFrame::OnUpdateDialogbar(CCmdUI* pCmdUI)

{

        // TODO: Add your command update UI handler code here

        if(m_wndDialogBar.IsWindowVisible())

                pCmdUI->SetCheck(TRUE);

        else

                pCmdUI->SetCheck(FALSE);   

}


void CMainFrame::OnComboChange()

{

        CComboBox *pWnd=(CComboBox*)m_wndDialogBar.GetDlgItem(IDC_COMBO);

        int num=pWnd->GetCurSel();

        CString message;

        pWnd->GetLBText(num,message);

        AfxMessageBox(message);

}

반응형

'WindowsPrograming' 카테고리의 다른 글

[퍼옴]MFC04  (0) 2007.03.11
[퍼옴]MFC06  (0) 2007.03.11
RichEditBox에서 글자색 관련 질문입니다..  (0) 2007.03.11
Posted by Real_G