ToolBar에 Scroll Bar와 Static control 올리기

 

1. 우선 새로운 프로젝트를 하나 만듭니다. SDI에 옵션은 그냥 있는대로 놔둡니다. 프로젝트 제목은 Tbar 로 정하죠.

2. 툴바에 무언가 다른 걸 올릴 거니까 새로운 툴바 클래스를 하나 만들죠. 우선 클래스 위저드를 실행해서 Add Class를 선택합니다.  
 클래스 이름은 CMyToolbar 로 하고 Base Class는 마땅히 CToolBar 로 해야겠지만 눈을 씻고 찾아봐도 CToolBar 는 없고, 비슷한 CToolBarCtrl 만 있네요.  할 수 없이 그걸루 선택하고 나중에 고쳐야 되겠군요.
 OK 버튼을 눌러 작업을 끝내고, WorkSpace의 ClassView를 보면 새로 만든 CMyToolBar 클래스가 보이는군요.
 고칠 파일은 MyToolBar.h / cpp 이고, 위치는 다음과 같습니다.

--------------------------------------------------------------

#if !defined(AFX_MYTOOLBAR_H__F19B9739_9AAA_11D3_998C_8A0FF977CCE4__INCLUDED_)
#define AFX_MYTOOLBAR_H__F19B9739_9AAA_11D3_998C_8A0FF977CCE4__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// MyToolBar.h : header file
//

/////////////////////////////////////////////////////////////////////////////
// CMyToolBar window

class CMyToolBar : public CToolBar    // <----  여기 고쳤습니다.
{                                                      //        (CToolBarCtrl -> CToolBar)
// Construction
public:
        CMyToolBar();

// Attributes
public:

// Operations
public:

..................................

- x - x - x --------------------------------------

// MyToolBar.cpp : implementation file
//

#include "stdafx.h"
#include "Tbar.h"
#include "MyToolBar.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CMyToolBar

CMyToolBar::CMyToolBar()
{
}

CMyToolBar::~CMyToolBar()
{
}


BEGIN_MESSAGE_MAP(CMyToolBar, CToolBar)    // <- 여기두 고쳤어요..
        //{{AFX_MSG_MAP(CMyToolBar)
                // NOTE - the ClassWizard will add and remove mapping macros here.
        //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMyToolBar message handlers

 

3. 다음으로 MainFrm.h 도 한 줄 고쳐야 합니다. 중간 정도에 다음과 같은 코드가 나옵니다. 그리고 이 파일 위에
   #include "MyToolBar.h" 처럼 헤더파일 빼먹으면 안돼죠..

................................

protected:  // control bar embedded members
        CStatusBar  m_wndStatusBar;
        CMyToolBar    m_wndToolBar;       // CToolBar -> CMyToolBar 로 고쳤습니다.

..................................

 

4. 이제 할 일은 툴바의 버튼 위에 스크롤바가 자리잡을 곳을 마련하는 일입죠. 이건 툴바의 뒤에 ID_SEPARATOR를 붙여야 하는데 이렇게 하려면 다음을 따라하세요..

5. 다음엔 CMyToolBar 클래스 안에 Scroll bar와 Static control 타입의 멤버를 추가합니다.
 방법은 다음을 따라하세요.

6. 새로운 멤버를 추가했으니 그 멤버를 가리키는 ID를 만들어야겠죠. 그 ID는 각각 ID_ZOOMSCROLLID_ZOOMSTATIC 으로 하겠습니다.

 

 7. 다음으로 MainFrm.cpp를 열어서 OnCreate() 함수를 고칩니다. 아래의 굵은 글씨 부분이 추가한 부분임다.

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
        if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
                return -1;
        
        if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | 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;      // fail to create
        }

        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: Delete these three lines if you don't want the toolbar to
        //  be dockable
        m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
        EnableDocking(CBRS_ALIGN_ANY);
        DockControlBar(&m_wndToolBar);

        // add scroll bar & static control to end of toolbar
        CRect rect;

        m_wndToolBar.SetButtonInfo(12, ID_ZOOMSCROLL, TBBS_SEPARATOR, 80);
        m_wndToolBar.GetItemRect(12, &rect);
        rect.top = 3;
        if(!m_wndToolBar.m_zoomScroll.Create(WS_VISIBLE|SBS_HORZ|WS_TABSTOP,
                rect, &m_wndToolBar, ID_ZOOMSCROLL)) {
                TRACE0("Failed to create scroll bar\n");
                return -1;
        }

        m_wndToolBar.SetButtonInfo(14, ID_ZOOMSTATIC, TBBS_SEPARATOR, 60);
        m_wndToolBar.GetItemRect(14, &rect);
        rect.top = 6;
        if(!m_wndToolBar.m_zoomStatic.Create("배율", WS_VISIBLE|SS_LEFT|
                WS_TABSTOP, rect, &m_wndToolBar, ID_ZOOMSTATIC)) {
                TRACE0("Failed to create Static control\n");
                return -1;
        }

        return 0;
}

8. 위에서 보면 먼저 스크롤바를 붙이고 SetButtonInfo() 라는 함수를 호출하여 툴바버튼 중 12번째 것 (SEPARATOR 포함) 의 메뉴 ID를 ID_SEPARATOR에서 ID_ZOOMSCROLL로 바꾸면서 폭을 80 픽셀로 변경했다.

m_wndToolBar.SetButtonInfo(12, ID_ZOOMSCROLL, TBBS_SEPARATOR, 80);

그리고 나서 GetItemRect()를 호출해 변경된 그 부분의 위치를 얻어 시작 Y 좌표를 약간 밑으로 내린 다음 툴바 위의 그 위치에 스크롤 바를 생성하였다. (m_wndToolBar.m_zoomScroll.Create 호출부분)

if(!m_wndToolBar.m_zoomScroll.Create(WS_VISIBLE|SBS_HORZ|WS_TABSTOP,
                rect, &m_wndToolBar, ID_ZOOMSCROLL))

 위의 Create() 함수를 보면 두 번째 인자로 스크롤 바의 위치를 주었다. 그리고 세 번째 인자로 부모 윈도우 오브젝트에 대한 포인터로 툴바에 대한 포인터를 주었다. 툴바가 스크롤 바의 부모윈도우이기 때문이다.
 다음으로 static control을 만들기 위해 14번째 툴바 버튼에 대해 반복하였다.

(한가지 더)
     =>
만약 위의 경우와 같이 만들었는데 컴파일해서 실행중 에러가 난다면 아마 컨트롤이 출력되는 위치가 바른지 확인을 해보아야 할 것이다. 예를 들어 고친 툴바에 SEPARATOR를 포함해 14개의 컨트롤이 있는데, 15번째로 출력을 하도록 되어있다면 당연히 실행중 엑세스 에러가 날 것이다.