适用于 Windows Mobile 和桌面 WTL 应用程序的框架相关类和消息映射宏(第一部分)






4.80/5 (6投票s)
消息映射宏、拆分框架、全屏实现以及 UI 元素的自动映射。
- 下载 FrameX1 示例项目 - 30.5 KB
- 下载 atlframx.h 类和宏 - 6.44 KB
- 下载 MDISplitFrame 示例 - 57.8 KB
- 下载 SDIFrameX 示例 - 64.7 KB
引言
这是两篇关于用于 Windows Mobile 和桌面 WTL 应用程序的各种框架相关类和消息映射宏的文章中的第一篇。
第二部分将侧重于框架和窗格控件类中的多视图实现。
第一部分介绍了各种消息映射宏、MDI 和 SDI 拆分框架类、一个全屏模式实现类,以及通过UI 元素的自动映射移除 WTL 的 UPDATE_UI_MAP
。
随附的 FrameX1.zip 中的 SDIFrameX 和 MDISplitFrame 示例展示了将此代码包含到现有或新应用程序中的简单性。
两篇文章的可重用代码在 atlframx.zip 中。
消息映射宏
这些宏实现了消息应答和转发、条件消息映射链式调用以及在实现文件中定义消息映射。
MESSAGE_ANSWER(msg, res)
返回res
并处理消息。在返回值LRESULT
与上下文无关的情况下,它节省了一个函数调用,通常
MESSAGE_ANSWER(WM_ERASEBKGND, TRUE)
FORWARD_MESSAGE_WINDOW(msg, hWnd)
将 msg
消息发送到提供的 hWnd
并处理消息。当命令应由未重绘的子控件执行时很有用。FORWARD_MESSAGE(msg)
是 ATL FORWARD_NOTIFICATIONS()
宏的单一消息补充。它将 msg
消息发送到父窗口并处理该消息。CHAIN_MSG_MAP_CONDITION(bCondition, theChainClass)
和 CHAIN_MSG_MAP_ALT_CONDITION(bCondition, theChainClass, msgMapID)
如果 bCondition
求值为 true
,则执行 CHAIN_MSG_MAP()
。当链式类处理取决于上下文时很有用。CHAIN_MSG_MAP_CONDITION_MEMBER(bCondition, theChainMember)
和 CHAIN_MSG_MAP_ALT_CONDITION_MEMBER(bCondition, theChainMember, msgMapID)
如果 bCondition
求值为 true
,则与 CHAIN_MSG_MAP_MEMBER()
执行类似的操作。DECLARE_MSG_MAP(theClass)
,并在 MyClass.cpp 中你的消息映射声明的开头将 BEGIN_MSG_MAP()
替换为 IMPLEMENT_MSG_MAP(theClass)
。拆分框架类
使用这些类消除了拆分框架布局中通常存在的中间 CSplitterWindow
和相关的消息流量。
CSplitFrameImplBase
CSplitFrameImplBase
直接派生自 TFrameImpl
(本身派生自 WTL::CFrameWindowImplBase
)和 WTL::CSplitterImpl
。通过充分的 TFrameImpl
模板参数,它专门化为
CSplitFrameWindowImpl
,一个即用型拆分框架基类。CMDISplitFrameWindowImpl
,一个即用型 MDI 拆分框架基类。
定义
template <class T, class TFrameImpl, bool t_bVertical = true> class ATL_NO_VTABLE CSplitFrameImplBase : public TFrameImpl, public CSplitterImpl<T, t_bVertical> { typedef CSplitFrameImplBase<T, TFrameImpl, t_bVertical> thisClass; public: typedef thisClass SplitFrame; typedef TFrameImpl Frame; typedef CSplitterImpl<T, t_bVertical> Splitter;
Overrides
CSplitFrameImplBase
在其构造函数中执行简单的拆分器初始化,并且不使用 WM_CREATE
消息。
// Splitter initialization in constructor CSplitFrameImplBase() { #ifndef _WIN32_WCE m_cxySplitBar = ::GetSystemMetrics(t_bVertical ? SM_CXSIZEFRAME : SM_CYSIZEFRAME); m_cxyMin = 2 * ::GetSystemMetrics(t_bVertical ? SM_CXEDGE : SM_CYEDGE); ::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &m_bFullDrag, 0); #else // CE specific m_cxyMin = m_cxySplitBar = 2 * ::GetSystemMetrics(t_bVertical ? SM_CXEDGE : SM_CYEDGE); #endif // _WIN32_WCE }
CSplitFrameImplBase
重写了 TFrameImpl::UpdateLayout()
void UpdateLayout(BOOL bResizeBars = TRUE) { RECT rect; GetClientRect(&rect); // position bars and offset their dimensions UpdateBarsPosition(rect, bResizeBars); // resize splitter and children SetSplitterRect(&rect); }
CSplitFrameWindowImpl
CSplitFrameWindowImpl
是一个 CSplitFrameImplBase
,它使用 CFrameWindowImpl<T, ATL::CWindow>
作为 TFrameImpl
模板参数。
定义
template <class T, bool t_bVertical = true, class TBase = ATL::CWindow, class TWinTraits = ATL::CFrameWinTraits> class ATL_NO_VTABLE CSplitFrameWindowImpl : public CSplitFrameImplBase<T, CFrameWindowImpl<T, TBase, TWinTraits>, t_bVertical> { typedef CSplitFrameWindowImpl<T, t_bVertical, TBase, TWinTraits> thisClass; };
用法
CMDISplitFrameWindowImpl
CMDISplitFrameWindowImpl
是一个即用型 MDI 拆分框架;它是 CSplitFrameImplBase
,使用 CMDIFrameWindowImpl<T, WTL::CMDIWindow>
作为 TFrameImpl
模板参数。一个 bool t_bRightView
模板参数如果为 true
(默认),则将 MDI 窗格设置为右侧(或底部)。
定义
template <class T, bool t_bRightView = true, bool t_bVertical = true, class TBase = WTL::CMDIWindow, class TWinTraits = ATL::CFrameWinTraits> class ATL_NO_VTABLE CMDISplitFrameWindowImpl : public CSplitFrameImplBase<T, CMDIFrameWindowImpl<T, TBase, TWinTraits>, t_bVertical> { typedef CMDISplitFrameWindowImpl<T, t_bRightView, t_bVertical, TBase, TWinTraits> thisClass; public: HWND CreateMDIClient(HMENU hWindowMenu = NULL, UINT nID = ATL_IDW_CLIENT, UINT nFirstChildID = ATL_IDM_FIRST_MDICHILD) { HWND hWndMDIClient = Frame::CreateMDIClient(hWindowMenu, nID, nFirstChildID); SetSplitterPane(t_bRightView, hWndMDIClient); return hWndMDIClient; } BEGIN_MSG_MAP(thisClass) MESSAGE_HANDLER(WM_MDISETMENU, OnMDISetMenu) CHAIN_MSG_MAP(SplitFrame) END_MSG_MAP() };
Overrides
CMDISplitFrameWindowImpl
重写了 CMDIFrameWindowImpl::CreateMDIClient()
并根据 t_bRightView
设置拆分器的 MDI 窗格。
用法
请参阅 MDISplitFrame 示例。
CFullScreenImpl
CFullScreenImpl
管理任何弹出窗口(非子窗口)的全屏显示模式。最初用于框架窗口,它也可以应用于对话框或闪屏窗口。
CFullScreenImpl
不适用于 Windows CE,因为它已经在 atlwince.h 中包含了一个 CFullScreenFrame
类。
定义
template <class T, UINT t_uIdExitAccel = 0, bool t_bIsFrame = true> class CFullScreenImpl { typedef CFullScreenImpl<T, t_uIdExitAccel, t_bIsFrame> thisClass; public: typedef thisClass FullScreen;
桌面全屏模式的一个设计问题是如何让用户有机会返回到正常窗口模式,因为全屏模式不再有菜单或工具栏。CFullScreenImpl
使用可选的 t_uIdExitAccel
加速器资源模板参数和一个 PreTranslateMessage
成员来帮助解决这个问题。第三个模板参数 t_bIsFrame
,当 T
派生自 CFrameWindowImplBase
时设置为 true
,然后管理工具栏和状态栏的可见性。
然后,当你开始迭代 2(这是构建迭代的开始)时,你可能想要复制测试用例并将它们重新分类到迭代 2。这还允许对测试用例进行粒度跟踪,并允许你说某个测试用例在一个迭代中是准备好的,但在另一个迭代中不是。同样,如何做到这一点取决于你以及你希望如何报告。 “场景”部分提供了更多细节。
默认构造函数从 t_uIdExitAccel
资源(如果提供了 t_uIdExitAccel
)初始化 WINDOWPLACEMENT m_wp
成员和 CAccelerator m_ExitAccel
成员。
CFullScreenImpl() : m_bFullScreen(false), m_bTopVisible(false), m_bBottomVisible(false) { m_wp.length = sizeof WINDOWPLACEMENT; if (t_uIdExitAccel) m_ExitAccel.LoadAccelerators(t_uIdExitAccel); }
API
bool IsFullScreen()
返回全屏状态。void SetExitAccelerator(BYTE fVirt, WORD key, WORD cmd)
根据参数将CAccelerator m_ExitAccel
成员设置为单个按键。void SetExitAccelerator(UINT uIdExitAccel)
从uIdExitAccel
加速器资源加载CAccelerator m_ExitAccel
成员。bool SetFullScreen(bool bFullScreen)
在全屏状态尚未设置且派生类OnFullScreen(bFullScreen)
返回true
时,根据bFullScreen
设置全屏状态。如果全屏状态已更改,SetFullScreen()
返回true
,否则返回false
。
bool SetFullScreen(bool bFullScreen) { if (bFullScreen == m_bFullScreen) return false; T* pT = static_cast<T*>(this); ATLASSERT(pT->IsWindow()); if (!pT->OnFullScreen(bFullScreen)) return false; if (bFullScreen) { // save current position pT->GetWindowPlacement(&m_wp); // remove framish styles pT->ModifyStyle(WS_CAPTION | WS_BORDER | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, 0, SWP_FRAMECHANGED); // hide bars if necessary if (t_bIsFrame) { m_bTopVisible = ::IsWindow(pT->m_hWndToolBar) && ::IsWindowVisible(pT->m_hWndToolBar); if (m_bTopVisible) ::ShowWindow(pT->m_hWndToolBar, SW_HIDE); m_bBottomVisible = ::IsWindow(pT->m_hWndStatusBar) && ::IsWindowVisible(pT->m_hWndStatusBar); if (m_bBottomVisible) ::ShowWindow(pT->m_hWndStatusBar, SW_HIDE); } // move to full screen CWindowDC dc(NULL); pT->SetWindowPos(NULL, 0, 0, dc.GetDeviceCaps(HORZRES), dc.GetDeviceCaps(VERTRES), SWP_FRAMECHANGED); } else { // restore original styles pT->ModifyStyle(0, T::GetWndStyle(0), SWP_FRAMECHANGED); // restore bars if (t_bIsFrame) { if (m_bTopVisible) ::ShowWindow(pT->m_hWndToolBar, SW_SHOW); if (m_bBottomVisible) ::ShowWindow(pT->m_hWndStatusBar, SW_SHOW); } // move to saved position pT->SetWindowPlacement(&m_wp); } m_bFullScreen = bFullScreen; return true; }
BOOL PreTranslateMessage(MSG* pMsg)
在未处于全屏模式或 m_ExitAccel
未初始化时返回 FALSE
;否则返回 m_ExitAccel.TranslateAccelerator()
的结果。BOOL PreTranslateMessage(MSG* pMsg) { return !IsFullScreen() || m_ExitAccel.IsNull() ? FALSE : m_ExitAccel.TranslateAccelerator(static_cast<T*>(this)->m_hWnd, pMsg); }
可重写
bool OnFullScreen(bool bFullScreen)
由SetFullScreen()
调用。默认的CFullScreenImpl::OnFullScreen()
返回true
以允许全屏模式更改。如果想防止更改或进行一些布局或 UI 更改,请在派生类中重写它。
用法
CAutoUpdateUI
CAutoUpdateUI
是 WTL::CUpdateUI
的替代类,不需要派生的 UPDATE_UI_MAP
。它在 UI 布局和 ID 尚未稳定的开发阶段很有用,并且以后可以方便地进行 UI 维护:添加、删除或重命名命令,或更改其托管工具栏、菜单或对话框。
如果派生类没有 UPDATE_UI_MAP
,CAutoUpdateUI
会嵌入一个空的 UPDATE_UI_MAP
。派生或嵌入的 UPDATE_UI_MAP
通过调用 UIAddxxx
成员来填充。
定义
template <class T> class CAutoUpdateUI : public WTL::CDynamicUpdateUI<T> {
API
bool UIAddMenu(HMENU hm, bool bSetText = false)
将具有hm
句柄的菜单及其子菜单添加到UPDATE_UI_MAP
。bool UIAddMenu(UINT uID, bool bSetText = false)
将具有uID
ID 的菜单资源及其子菜单添加到UPDATE_UI_MAP
。
如果 bSetText
为 true
,两者都会调用 UISetText()
来设置菜单项文本。
Overrides
bool UIAddToolBar(HWND hWndToolBar)
将具有hWndToolBar
HWND
的工具栏控件添加到UPDATE_UI_MAP
。如果工具栏包含嵌入式控件,则通过调用UIAddChildWindowContainer()
将它们添加到UPDATE_UI_MAP
。bool UIAddChildWindowContainer(HWND hWnd)
将hWnd
窗口的直接子窗口添加到UPDATE_UI_MAP
。不会添加孙子窗口。
在 Windows CE 项目中,如果对菜单栏调用 UIAddToolBar()
,它会进入无限循环,因此它被禁用。使用 #define _AUTOUI_CE_TOOLBAR
启用它,以便可以对其真正的工具栏控件调用。
用法
SDIFrameX 示例
此示例详细介绍了从 WTL AppWizard 为 Explorer(拆分布局)应用程序生成的代码,实现一个派生自 CSplitFrameWindowImpl
、CFullScreenImpl
和 CAutoUpdateUI
的框架的所有步骤。
步骤 0
- 在 SDIFrameX.cpp 中包含
#include "atlframx.h"
。
// SDIFrameX.cpp : main source file for SDIFrameX.exe // ... #include "..\atlframx.h" // 0
步骤 1:从 CSplitFrameWindowImpl 派生 CMainFrame 并移除中间的 CSplitterWindow
- 从
CSplitFrameWindowImpl
派生CMainFrame
。 - 使用
DECLARE_FRAME_WND_CLASS_EX
和CS_DBLCLKS
来启用双击拆分器条以均分窗格功能。 - 移除
m_splitter
成员声明。
// MainFrm.h : interface of the CMainFrame class // ... class CMainFrame : public CSplitFrameWindowImpl<CMainFrame>, // 1 // ... { public: DECLARE_FRAME_WND_CLASS_EX(NULL, IDR_MAINFRAME, CS_DBLCLKS, COLOR_WINDOW) // 1 //CSplitterWindow m_splitter; // 1 // ...
OnCreate()
中- 移除
m_splitter.Create()
调用。 - 将
m_pane
和m_view
的父窗口更改为m_hWnd
。 - 移除对
CSplitterImpl
成员调用的 m_splitter. 前缀。
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { // ... //m_hWndClient = m_splitter.Create(m_hWnd, rcDefault, NULL, //WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN); // 1 // ... m_pane.Create(/*m_splitter*/m_hWnd, _T("Tree"), WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN); // 1 // ... m_view.Create(/*m_splitter*/m_hWnd, rcDefault, _T("http://www.microsoft.com"), WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_HSCROLL | WS_VSCROLL, WS_EX_CLIENTEDGE); // 1 /*m_splitter.*/SetSplitterPanes(m_pane, m_view); // 1 UpdateLayout(); /*m_splitter.*/SetSplitterPosPct(25); // 1
OnViewTreePane()
和 OnTreePaneClose()
中,移除对 CSplitterImpl
成员调用的 m_splitter. 前缀。LRESULT OnViewTreePane(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { bool bShow = (/*m_splitter.*/GetSinglePaneMode() != SPLIT_PANE_NONE); // 1 /*m_splitter.*/SetSinglePaneMode(bShow ? SPLIT_PANE_NONE : SPLIT_PANE_RIGHT); // 1 UISetCheck(ID_VIEW_TREEPANE, bShow); return 0; } LRESULT OnTreePaneClose(WORD /*wNotifyCode*/, WORD /*wID*/, HWND hWndCtl, BOOL& /*bHandled*/) { if(hWndCtl == m_pane.m_hWnd) { /*m_splitter.*/SetSinglePaneMode(SPLIT_PANE_RIGHT); // 1 UISetCheck(ID_VIEW_TREEPANE, 0); } return 0; }
步骤 2:实现一个由 Escape 键退出的全屏模式
- 在 resource.h 中声明一个
ID_VIEW_FULLSCREEN
标识符。
// resource.h // ... #define ID_VIEW_FULLSCREEN 0xE802 // 2
ID_VIEW_FULLSCREEN
加速器资源。// Microsoft Visual C++ generated resource script. // SDIFrameX.rc // ... IDR_MAINFRAME MENU BEGIN // ... POPUP "&View" BEGIN MENUITEM "&Toolbar", ID_VIEW_TOOLBAR MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR MENUITEM "Tree &Pane", ID_VIEW_TREEPANE MENUITEM "&Full Screen", ID_VIEW_FULLSCREEN // 2 END // ... // Accelerator // ... ID_VIEW_FULLSCREEN ACCELERATORS // 2 BEGIN // 2 VK_ESCAPE, ID_VIEW_FULLSCREEN, VIRTKEY, NOINVERT // 2 END // 2
CFullScreenImpl
派生 CMainFrame
。CMainFrame::OnFullScreen
成员以在全屏模式下隐藏左侧拆分窗格。CMainFrame::PreTranslateMessage
调用 FullScreen::PreTranslateMessage
以在全屏模式下激活 ID_VIEW_FULLSCREEN
加速器。// MainFrm.h : interface of the CMainFrame class // ... class CMainFrame : // ... public CFullScreenImpl<CMainFrame, ID_VIEW_FULLSCREEN>, // 2 // … { // ... bool OnFullScreen(bool bFullScreen) // 2 { if (bFullScreen) // 2 SetSinglePaneMode(SPLIT_PANE_RIGHT); // 2 else if (UIGetState(ID_VIEW_TREEPANE) & UPDUI_CHECKED) // 2 SetSinglePaneMode(SPLIT_PANE_NONE); // 2 return true; // allow change // 2 } virtual BOOL PreTranslateMessage(MSG* pMsg) { if (FullScreen::PreTranslateMessage(pMsg)) // 2 return TRUE; // 2 // ...
ID_VIEW_FULLSCREEN
的命令处理程序。// ... BEGIN_MSG_MAP(CMainFrame) // ... COMMAND_ID_HANDLER(ID_VIEW_FULLSCREEN, OnViewFullScreen) // 2 // ... LRESULT OnViewFullScreen(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) // 2 { SetFullScreen(!IsFullScreen()); // 2 return 0; // 2 } // 2
步骤 3:从 CAutoUpdateUI 派生 CMainFrame 并移除 UPDATE_UI_MAP 宏
- 从
CAutoUpdateUI
派生CMainFrame
。 - 移除
UPDATE_UI_MAP
宏并在消息映射中链式调用CAutoUpdateUI
。 - 在
CMainFrame::OnCreate()
中调用UIAddMenu()
。
// MainFrm.h : interface of the CMainFrame class // ... class CMainFrame : // ... public CAutoUpdateUI<CMainFrame>, // 3 // ... { // ... /* BEGIN_UPDATE_UI_MAP(CMainFrame) // 3 UPDATE_ELEMENT(ID_VIEW_TOOLBAR, UPDUI_MENUPOPUP) UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP) UPDATE_ELEMENT(ID_VIEW_TREEPANE, UPDUI_MENUPOPUP) END_UPDATE_UI_MAP()*/ // 3 // … BEGIN_MSG_MAP(CMainFrame) // ... CHAIN_MSG_MAP(CAutoUpdateUI<CMainFrame>) // 3 // ... LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { UIAddMenu(IDR_MAINFRAME); // 3 // ...
MDISplitFrame 示例
此示例实现了一个基本的 MDI 拆分框架,合并了 WTL AppWizard 为 MDI 和 Explorer(拆分布局)应用程序生成的代码。
CMainFrame
派生自 CMDISplitFrameWindowImpl<CMainFrame>
;添加了左侧窗格成员、命令处理程序,并将 ID_VIEW_TREEPANE
添加到菜单资源。
class CMainFrame : public CMDISplitFrameWindowImpl, public CUpdateUI , public CMessageFilter, public CIdleHandler { public: DECLARE_FRAME_WND_CLASS_EX(_T("WTL_MDISplitFrame"), IDR_MAINFRAME, CS_DBLCLKS, COLOR_WINDOW) CPaneContainer m_pane; CTreeViewCtrl m_treeview; CMDICommandBarCtrl m_CmdBar; virtual BOOL PreTranslateMessage(MSG* pMsg) { if(Frame::PreTranslateMessage(pMsg)) return TRUE; HWND hWnd = MDIGetActive(); if(hWnd != NULL) return (BOOL)::SendMessage(hWnd, WM_FORWARDMSG, 0, (LPARAM)pMsg); return FALSE; } // ... BEGIN_UPDATE_UI_MAP(CMainFrame) UPDATE_ELEMENT(ID_VIEW_TOOLBAR, UPDUI_MENUPOPUP) UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP) UPDATE_ELEMENT(ID_VIEW_TREEPANE, UPDUI_MENUPOPUP) END_UPDATE_UI_MAP() BEGIN_MSG_MAP(CMainFrame) MESSAGE_HANDLER(WM_CREATE, OnCreate) MESSAGE_HANDLER(WM_DESTROY, OnDestroy) COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit) COMMAND_ID_HANDLER(ID_FILE_NEW, OnFileNew) COMMAND_ID_HANDLER(ID_VIEW_TOOLBAR, OnViewToolBar) COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR, OnViewStatusBar) COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout) COMMAND_ID_HANDLER(ID_VIEW_TREEPANE, OnViewTreePane) COMMAND_ID_HANDLER(ID_PANE_CLOSE, OnViewTreePane) COMMAND_ID_HANDLER(ID_WINDOW_CASCADE, OnWindowCascade) COMMAND_ID_HANDLER(ID_WINDOW_TILE_HORZ, OnWindowTile) COMMAND_ID_HANDLER(ID_WINDOW_ARRANGE, OnWindowArrangeIcons) CHAIN_MDI_CHILD_COMMANDS() CHAIN_MSG_MAP(CUpdateUI ) CHAIN_MSG_MAP(CMDISplitFrameWindowImpl ) END_MSG_MAP()
OnCreate()
成员创建左侧窗格,并调用重写的 CMDISplitFrameWindowImpl::CreateMDIClient()
,该函数将右侧窗格设置为 CMDIWindow::m_hWndMDIClient
。
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { // create command bar window HWND hWndCmdBar = m_CmdBar.Create(m_hWnd, rcDefault, NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE); // attach menu m_CmdBar.AttachMenu(GetMenu()); // load command bar images m_CmdBar.LoadImages(IDR_MAINFRAME); // remove old menu SetMenu(NULL); HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd, IDR_MAINFRAME, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE); CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE); AddSimpleReBarBand(hWndCmdBar); AddSimpleReBarBand(hWndToolBar, NULL, TRUE); CreateSimpleStatusBar(); // Create left pane content m_pane.SetPaneContainerExtendedStyle(PANECNT_NOBORDER); m_pane.Create(m_hWnd, _T("Tree"), WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN); m_treeview.Create(m_pane, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS | TVS_SHOWSELALWAYS, WS_EX_CLIENTEDGE); m_treeview.SetFont(AtlGetDefaultGuiFont()); m_pane.SetClient(m_treeview); // Set left pane SetSplitterPane(SPLIT_PANE_LEFT, m_pane); UpdateLayout(); SetSplitterPosPct(25); CreateMDIClient(); m_CmdBar.SetMDIClient(m_hWndMDIClient); UIAddToolBar(hWndToolBar); UISetCheck(ID_VIEW_TOOLBAR, 1); UISetCheck(ID_VIEW_STATUS_BAR, 1); UISetCheck(ID_VIEW_TREEPANE, 1); // register object for message filtering and idle updates CMessageLoop* pLoop = _Module.GetMessageLoop(); ATLASSERT(pLoop != NULL); pLoop->AddMessageFilter(this); pLoop->AddIdleHandler(this); return 0; }
第一部分结论
第一部分介绍了对当前 WTL 8.0 框架管理和消息路由的一些简单增强。
第二部分将介绍多视图实现以及框架和窗格容器类的应用程序。
希望很快能见到你,祝好!
历史
- 2009 年 7 月 29 日:首次发布。