WTL for MFC Programmers 学习笔记(三) Part III Toolbars and Status Bars

Toolbars and Status Bars in a Frame

       CFrameWindowImpl有个三个HWND对象成员:

1.       m_hWndClient 子窗体HWND

2.       m_hWndToolBar 工具栏或rebar HWND

3.       m_hWndStatusBar 状态栏HWND

CFrameWindowImpl只支持一个工具栏。如果需要使用多个工具栏的话需要用rebar

CFrameWindowImpl::OnSize()中调用UpdateLayout()时做了两件事:设置bar的位置、调整视图窗口大小以符合当前客户区域。

 

AppWizard Code for Toolbars and Stauts Bars

       创建SDI工程的时候选择特征: ToolbarStatus Bar,这样主窗体上就加上了这两个bar

 

How CMainWindow creates the bars

       LRESULT CMainFrame::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/,

                             LPARAM /*lParam*/, BOOL& /*bHandled*/)

{

    CreateSimpleToolBar();

    CreateSimpleStatusBar();

 

    m_hWndClient = m_view.Create(...);

 

// ...

 

    // register object for message filtering and idle updates

    CMessageLoop* pLoop = _Module.GetMessageLoop();

    ATLASSERT(pLoop != NULL);

    pLoop->AddMessageFilter(this);

    pLoop->AddIdleHandler(this);

 

    return 0;

}

      

BOOL CFrameWindowImpl::CreateSimpleToolBar(

    UINT nResourceID = 0,                 // 0表示使用DECLARE_FRAME_WND_CLASS宏中指定的ID

    DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE,  // TBSTYLE_TOOLTIPS | usual child | visible styles

    UINT nID = ATL_IDW_TOOLBAR)  // 工具栏的Window ID,一般使用默认值

{

    ATLASSERT(!::IsWindow(m_hWndToolBar));

 

    if(nResourceID == 0)

        nResourceID = T::GetWndClassInfo().m_uCommonResourceID;

 

    m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd,

                     nResourceID, TRUE, dwStyle, nID);

    return (m_hWndToolBar != NULL);

}

 

BOOL CFrameWindowImpl::CreateSimpleStatusBar(

    UINT nTextID = ATL_IDS_IDLEMESSAGE,  // “Ready” 字符串

    DWORD dwStyle = ... SBARS_SIZEGRIP, // 状态栏样式,在右侧显示拖动区域

    UINT nID = ATL_IDW_STATUS_BAR) // 状态栏Window ID

{

    TCHAR szText[128];    // max text lentgth is 127 for status bars

    szText[0] = 0;

    ::LoadString(_Module.GetResourceInstance(), nTextID, szText, 128); // 从字符串表取字符串显示在状态栏

    return CreateSimpleStatusBar(szText, dwStyle, nID);

}

         调用重载方法:

BOOL CFrameWindowImpl::CreateSimpleStatusBar(

    LPCTSTR lpstrText,

    DWORD dwStyle = ... SBARS_SIZEGRIP,

    UINT nID = ATL_IDW_STATUS_BAR)

{

    ATLASSERT(!::IsWindow(m_hWndStatusBar));  // 判断状态栏是否已经创建

    m_hWndStatusBar = ::CreateStatusWindow(dwStyle, lpstrText, m_hWnd, nID);

    return (m_hWndStatusBar != NULL);

}

 

Showing and hiding the bars

       View菜单中有两个菜单控制toolbarstatusbarshow/hide。有相应的处理函数,OnViewToolBar如下:

LRESULT CMainFrame::OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/,

                                  HWND /*hWndCtl*/, BOOL& /*bHandled*/)

{

    BOOL bVisible = !::IsWindowVisible(m_hWndToolBar);

    ::ShowWindow(m_hWndToolBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE);

    UISetCheck(ID_VIEW_TOOLBAR, bVisible);

    UpdateLayout();

    return 0;

}

 

Built-in features of the bars

       CFrameWindowImple中实现了MFC中相同的工具栏和状态栏特征,如:工具提示(tooltips for toolbar buttons)、菜单功能提示(flyby help for menu items)

       CFrameWindowImplBase中由两个消息处理来实现这两个特征:OnMenuSelect()OnToolTipTextA()/OnToolTipTextW()。它们从字符串表中依据相同ID获取相同菜单/工具的提示串,OnMenuSelect获取/n前的字符串作为菜单提示,/n后的字符串作为工具提示。

 

Create a toolbar with a different style

       如果希望创建不同样式的工具栏,只要在CMainwindow::OnCreate调用CreateSimpleToolBar时传递样式参数。例如,创建3D按钮的工具:

CreateSimpleToolBar(0, ATL_SIMPLE_TOOLBAR_STYLE | TBSTYLE_FLAT | TBSTYLE_LIST);

       添加工具,通过COMMAND_ID_HANDLER_EX映射消息。

 

UI Updating Toolbar Buttons

       相同菜单项和工具项(拥有相同的ID)采用相同的更新映射

BEGIN_UPDATE_UI_MAP(CMainWindow)

       UPDATE_ELEMENT(ID_VIEW_TOOLBAR, UPDUI_MENUPOPUP | UPDUI_TOOLBAR)

       UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP | UPDUI_TOOLBAR)

END_UPDATE_UI_MAP()

 

Enabling toolbar UI updating

LRESULT CMainFrame::OnCreate( ... )

{

// ...

    m_hWndClient = m_view.Create(...);

 

    UIAddToolBar(m_hWndToolBar); // 告诉CUpdateUI toolbarHWND,这样当需要更新按钮状态时向哪个窗体发送消息

    UISetCheck(ID_VIEW_TOOLBAR, 1);

    UISetCheck(ID_VIEW_STATUS_BAR, 1);

// ...

}

       除了OnCreate,另外需要注意的是OnIdle(该方法在消息空闲状态时被触发,CMessageLoop中调用)

BOOL CMainFrame::OnIdle()

{

    UIUpdateToolBar();

    return FALSE;

}

       注意:如果仅更新菜单的话(没有工具栏需要更新)的话不需要这两步,因为CUpdateUI处理了WM_INITMENUPOPUP消息,并且在更新消息来的时候更新菜单。

 

Using a Rebar Instead of a Plain Toolbar

LRESULT CMainFrame::OnCreate(...)

{

    HWND hWndToolBar = CreateSimpleToolBarCtrl ( m_hWnd,

                           IDR_MAINFRAME, FALSE,

                           ATL_SIMPLE_TOOLBAR_PANE_STYLE ); // 创建工具栏,采用不同的样式,相当于ATL_SIMPLE_TOOLBAR_STYLE | CSS_NOPARENTALIGN

 

    CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE); // 创建rebar

    AddSimpleReBarBand(hWndToolBar); // toolbar添加到rebar

// ...

}

       CMainFrame::OnViewToolBar()中隐藏工具栏,如果还是m_hWndToolBar的话就会隐藏整个rebar.

 

Multi-Pane Status Bars

       WTL还有另外一个多区域状态栏类CMultiPaneStatusBarCtrl,该类提供了优先的UI更新。

class CMainFrame : public ...

{

//...

protected:

    CMultiPaneStatusBarCtrl m_wndStatusBar;

};

       OnCreate

    m_hWndStatusBar = m_wndStatusBar.Create ( *this );

UIAddStatusBar ( m_hWndStatusBar );

设置状态栏区域,调用CMultiPaneStatusBarCtrl::SetPanes()

BOOL SetPanes(int* pPanes,  // 状态区域ID数组,其实是字符串资源ID,资源值宽度决定了区域宽度

int nPanes,         // 区域个数

bool bSetText = true); // 是否设置初始值

    // Create the status bar panes.

int anPanes[] = { ID_DEFAULT_PANE, IDPANE_STATUS,

                  IDPANE_CAPS_INDICATOR };

 

m_wndStatusBar.SetPanes ( anPanes, 3, false );

 

UI updating the panes

       填写消息映射

BEGIN_UPDATE_UI_MAP(CMainFrame)

       UPDATE_ELEMENT(1, UPDUI_STATUSBAR) // CLOCK STATUS

       UPDATE_ELEMENT(2, UPDUI_STATUSBAR) // CAPS indicator

END_UPDATE_UI_MAP()

注意:第一个参数不是ID,而是状态栏中区域的索引号(从0开始)。如果区域顺序改变,映射宏中序号也要同时改变。

因为在调用SetPanes()的时候第三个参数是false,状态栏区域初始为空,现在设置区域文本:

// Set the initial text for the clock status pane

UISetText(1, _T(“Running”));

为了在空闲时更新状态栏,需要在CMainFrame::OnIdle()中调用UIUpdateStatusBar()

BOOL CMainFrame::OnIdle()

{

    UIUpdateToolBar();

    UIUpdateStatusBar();

    return FALSE;

}

       存在BUG:当调用了UIUpdateStatusBar(),通过UISetText()修改菜单项文本就不起作用了。

       在状态栏显示CAPS LOCK的状态:

BOOL CMainFrame::OnIdle()

{

    // Check the current Caps Lock state, and if it is on, show the

    // CAPS indicator in pane 2 of the status bar.

    if ( GetKeyState(VK_CAPITAL) & 1 )

        UISetText ( 2, CString(LPCTSTR(IDPANE_CAPS_INDICATOR)) );

    else

        UISetText ( 2, _T("") );

 

    UIUpdateToolBar();

    UIUpdateStatusBar();

    return FALSE;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值