ATL GUI 4
WTL可以完成工具栏和状态栏
RESULT 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;
}
CFrameWindowImpl::CreateSimpleToolBar()函数使用资源 IDR_MAINFRAME创建工具条并将其句柄赋值给m_hWndToolBar,
下面是CreateSimpleToolBar()函数的代码:
BOOL CFrameWindowImpl::CreateSimpleToolBar(
UINT nResourceID = 0,
DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE,
UINT nID = ATL_IDW_TOOLBAR)
{
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);
}
这是新添加的代码的开始部分,
CFrameWindowImpl::CreateSimpleToolBar()函数使用资源 IDR_MAINFRAME创建工具条并将其句柄赋值给m_hWndToolBar,
下面是CreateSimpleToolBar()函数的代码:
BOOL CFrameWindowImpl::CreateSimpleToolBar(
UINT nResourceID = 0,
DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE,
UINT nID = ATL_IDW_TOOLBAR)
{
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);
}
显示和隐藏工具条和状态条
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;
}
这些代码翻转控制条的显示状态,相应的翻转View|Toolbar菜单上的检查标记,
然后调用UpdateLayout()重新定位控制条并改变视图窗口的大小。
工具条按钮的UI状态更新
向导生成的代码已经为CMainFrame添加了对View|Toolbar和View|Status Bar两个菜单项的Check和Uncheck的UI更新处理。
对CMainFrame类的两个命令使用UI更新的宏:
BEGIN_UPDATE_UI_MAP(CMainFrame)
UPDATE_ELEMENT(ID_VIEW_TOOLBAR, UPDUI_MENUPOPUP)
UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP)
END_UPDATE_UI_MAP()
我们的时钟程序的工具条按钮与对应的菜单项有相同的ID,所以第一步就是为每个宏添加UPDUI_TOOLBAR标志:
BEGIN_UPDATE_UI_MAP(CMainFrame)
UPDATE_ELEMENT(ID_VIEW_TOOLBAR, UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
END_UPDATE_UI_MAP()
使用Rebar代替简单的工具条
LRESULT CMainFrame::OnCreate(...)
{
HWND hWndToolBar = CreateSimpleToolBarCtrl ( m_hWnd,
IDR_MAINFRAME, FALSE,
ATL_SIMPLE_TOOLBAR_PANE_STYLE );
CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);
AddSimpleReBarBand(hWndToolBar);
// ...
}
代码从创建工具条开始,只是使用了不同的风格,也就是ATL_SIMPLE_TOOLBAR_PANE_STYLE,
它定义在 atlframe.h文件中,与ATL_SIMPLE_TOOLBAR_STYLE风格相似,只是附加了一些诸如CCS_NOPARENTALIGN之类的风格,
这是使工具条作为Rebar的子窗口能够正常工作所必需的风格。
CMainFrame::OnViewToolBar()函数也有些不同,它只隐藏Rebar上工具条所在的条位而不是隐藏m_hWndToolBar(如果隐藏m_hWndToolBar将隐藏整个Rebar而不仅仅是工具条)。
如果你使用多个工具条,只需像向导为我们生成的关于第一个工具条的代码那在OnCreate()创建它们并调用 AddSimpleReBarBand()添加到Rebar就行了。
CFrameWindowImpl使用标准的Rebar控件,不像MFC那样支持可停靠的工具条,你所能作得就是排列这些工具条在Rebar中的位置。
窗格的UI状态更新
为了更新窗格上的文本,我们需要将相应的窗格添加到UI更新表:
BEGIN_UPDATE_UI_MAP(CMainFrame)
//...
UPDATE_ELEMENT(1, UPDUI_STATUSBAR) // clock status
UPDATE_ELEMENT(2, UPDUI_STATUSBAR) // CAPS indicator
END_UPDATE_UI_MAP()
和前面一样,第一个参数是窗格的索引。UISetText()是状态条唯一支持的UI更新函数。
最后,在CMainFrame::OnIdle()中添加对UIUpdateStatusBar()函数的调用,使状态条的窗格能够在空闲时间被更新:
BOOL CMainFrame::OnIdle()
{
UIUpdateToolBar();
UIUpdateStatusBar();
return FALSE;
}
当你使用UIUpdateStatusBar()时CUpdateUI的一个问题就暴露出来了--菜单项的文本在调用UISetText()后没有改变!
如果你在看WTLClock3工程的代码,时钟的开始/停止菜单项被移到了Clock菜单,在菜单项命令的响应处理函数中设置菜单项的文本。
无论如何,如果当前调用的是UIUpdateStatusBar(),那么对UISetText()的调用就不会起作用。
我没有研究这个问题是否可以被修复,所以如果你打算改变菜单的文本,你需要留意这个地方。
文章转至http://www.imyaker.com/wtl/,加入了自己的理解。
ATL GUI (四)
最新推荐文章于 2025-08-07 21:29:52 发布