Introduction
This is the first of two articles presenting various frame related classes and message map macros for Windows Mobile and Desktop WTL applications.
The second part will focus on multiple views implementation in frame and pane control classes.
This first part presents various message map macros, MDI and SDI split frame classes, a full screen mode implementation class, and the removing of the WTL UPDATE_UI_MAP
through automatic mapping of UI elements.
The attached SDIFrameX and MDISplitFrame samples in FrameX1.zip show how simple it is include this code in existing or new applications.
The reusable code for both article is in atlframx.zip.
Message Map Macros
These macros add message answering and forwarding, conditional message map chaining, and message map definition in an implementation file.
MESSAGE_ANSWER(msg, res)
returns res
and handles the message. It saves a function call in the cases where the returned LRESULT
value is context independent, typically:
MESSAGE_ANSWER(WM_ERASEBKGND, TRUE)
FORWARD_MESSAGE_WINDOW(msg, hWnd)
sends the msg
message to the provided hWnd
and handles the message. Useful when a command should be executed by an unsubclassed child control.
FORWARD_MESSAGE(msg)
is a single message complement to the ATL FORWARD_NOTIFICATIONS()
macro. It sends the msg
message to the parent window and handles the message.
CHAIN_MSG_MAP_CONDITION(bCondition, theChainClass)
and CHAIN_MSG_MAP_ALT_CONDITION(bCondition, theChainClass, msgMapID)
perform a CHAIN_MSG_MAP()
if bCondition
evaluates to true
. Useful in situations where chained class handling depends on the context.
CHAIN_MSG_MAP_CONDITION_MEMBER(bCondition, theChainMember)
and CHAIN_MSG_MAP_ALT_CONDITION_MEMBER(bCondition, theChainMember, msgMapID)
perform similarly with CHAIN_MSG_MAP_MEMBER()
if bCondition
evaluates to true
.
Declaring the message map in a .h file and implementing it in a .cpp file may help minimize rebuild dependencies. Use DECLARE_MSG_MAP(theClass)
alone in MyClass.h, and replace BEGIN_MSG_MAP()
by IMPLEMENT_MSG_MAP(theClass)
at the beginning of your message map declaration in MyClass.cpp.
Using these classes removes the usual intermediate CSplitterWindow
and associated message traffic from split frame layouts.
CSplitFrameImplBase
CSplitFrameImplBase
is a direct derivation of some TFrameImpl
(itself derived from WTL::CFrameWindowImplBase
) and WTL::CSplitterImpl
. With adequate TFrameImpl
template parameters, it specializes in:
CSplitFrameWindowImpl
, a ready to use split frame base class.
CMDISplitFrameWindowImpl
, a ready to use MDI split frame base class.
Definition
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
performs a simple splitter initialization in its constructor and does not use the WM_CREATE
message.
// 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
overrides 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
is a CSplitFrameImplBase
using CFrameWindowImpl<T, ATL::CWindow>
as the TFrameImpl
template parameter.
Definition
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;
};
Usage
See the SDIFrameX sample in Step 1.
CMDISplitFrameWindowImpl
is a ready to use MDI split frame; it is a CSplitFrameImplBase
using CMDIFrameWindowImpl<T, WTL::CMDIWindow>
as the TFrameImpl
template parameter. A bool t_bRightView
template parameter sets the MDI pane to right (or bottom) if true
(default).
Definition
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
overrides CMDIFrameWindowImpl::CreateMDIClient()
and sets the splitter MDI pane according to t_bRightView
.
Usage
See the MDISplitFrame sample.
CFullScreenImpl
manages a full screen display mode for any popup (non-child) window. First intended for frame windows, it may as well be applied to dialogs or splash windows.
CFullScreenImpl
does not apply to Windows CE which already has a CFullScreenFrame
class in atlwince.h.
Definition
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;
One of the design problem of a desktop full screen mode is to give the user a way to get back to normal windowing, as full screen mode has no more menu or toolbars. CFullScreenImpl
uses an optional t_uIdExitAccel
accelerator resource template parameter and a PreTranslateMessage
member to help that. The third template parameter, t_bIsFrame
, is set to true
when T
derives from CFrameWindowImplBase
and then manages visibility of the toolbar and statusbar.
Construction
The default constructor initializes the WINDOWPLACEMENT m_wp
member and the CAccelerator m_ExitAccel
member from a t_uIdExitAccel
resource if t_uIdExitAccel
is provided.
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()
returns the full screen state.
void SetExitAccelerator(BYTE fVirt, WORD key, WORD cmd)
sets the CAccelerator m_ExitAccel
member to a single keystroke according to the parameters.
void SetExitAccelerator(UINT uIdExitAccel)
loads the CAccelerator m_ExitAccel
member from a uIdExitAccel
accelerator resource.
bool SetFullScreen(bool bFullScreen)
sets the full screen state according to bFullScreen
if it is not already set and if the derived class OnFullScreen(bFullScreen)
returns true
. SetFullScreen()
returns true
if the full screen state has changed, false
otherwise.
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)
returns FALSE
if not in full screen mode or if m_ExitAccel
is not initialized; the result of m_ExitAccel.TranslateAccelerator()
otherwise.
BOOL PreTranslateMessage(MSG* pMsg)
{
return !IsFullScreen() || m_ExitAccel.IsNull() ?
FALSE : m_ExitAccel.TranslateAccelerator(static_cast<T*>(this)->m_hWnd, pMsg);
}
Overrideable
bool OnFullScreen(bool bFullScreen)
is called by SetFullScreen()
. The default CFullScreenImpl::OnFullScreen()
returns true
to allow full screen mode change. Override in your derived class if you want to prevent changes or do some layout or UI changes.
Usage
See the SDIFrameX sample in Step 2.
CAutoUpdateUI
is a replacement class for WTL::CUpdateUI
not requiring a derived class UPDATE_UI_MAP
. It is handy in development stages where UI layout and IDs are not stabilized, and later eases UI maintenance: adding, removing, or renaming a command, or changing its host toolbar, menu, or dialog.
If the derived class has no UPDATE_UI_MAP
, CAutoUpdateUI
embeds an empty UPDATE_UI_MAP
. The derived or embedded UPDATE_UI_MAP
is populated by calls to the UIAddxxx
members.
Definition
template <class T>
class CAutoUpdateUI : public WTL::CDynamicUpdateUI<T>
{
API
bool UIAddMenu(HMENU hm, bool bSetText = false)
adds the menu with the hm
handle and its submenus to the UPDATE_UI_MAP
.
bool UIAddMenu(UINT uID, bool bSetText = false)
adds the menu resource with the uID
ID and its submenus to the UPDATE_UI_MAP
.
If bSetText
is true
, both call UISetText()
with the menu item text.
Overrides
bool UIAddToolBar(HWND hWndToolBar)
adds the toolbar control with hWndToolBar
HWND
to the UPDATE_UI_MAP
. If the toolbar has embedded controls, they are added to the UPDATE_UI_MAP
by a call to UIAddChildWindowContainer()
.
In Windows CE projects, UIAddToolBar()
enters an infinite loop if called on a MenuBar, so it is disabled. Enable it with #define _AUTOUI_CE_TOOLBAR
to call it on a genuine ToolBarCtrl.
bool UIAddChildWindowContainer(HWND hWnd)
adds the direct children of the hWnd
window to the UPDATE_UI_MAP
. Grandchildren are not added.
Usage
See the SDIFrameX sample in Step 3.
This sample details all the steps to implement a CSplitFrameWindowImpl
derived, CFullScreenImpl
derived, and CAutoUpdateUI
derived frame from the code issued by the WTL AppWizard for an Explorer (split layout) application.
Step 0:
#include "atlframx.h"
in SDIFrameX.cpp.
// SDIFrameX.cpp : main source file for SDIFrameX.exe
// ...
#include "..\atlframx.h" // 0
- Derive
CMainFrame
from CSplitFrameWindowImpl
.
- Use
DECLARE_FRAME_WND_CLASS_EX
with CS_DBLCLKS
to enable the double click on splitter bar equalizes panes feature.
- Remove the
m_splitter
member declaration.
// 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
// ...
In OnCreate()
:
- Remove the
m_splitter.Create()
call.
- Change the parent of
m_pane
and m_view
to m_hWnd
.
- Remove the m_splitter. prefix from the calls to
CSplitterImpl
members.
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
In OnViewTreePane()
and OnTreePaneClose()
, remove the m_splitter. prefix from the calls to CSplitterImpl
members.
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;
}
Compile, run, and check the splitter functions.
- Declare a
ID_VIEW_FULLSCREEN
identifier in resource.h.
// resource.h
// ...
#define ID_VIEW_FULLSCREEN 0xE802 // 2
Add a Full Screen View menu entry and a ID_VIEW_FULLSCREEN
accelerator resource.
// 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
Derive CMainFrame
from CFullScreenImpl
.
Add a CMainFrame::OnFullScreen
member to hide the splitter left pane in full screen mode.
Call FullScreen::PreTranslateMessage
from CMainFrame::PreTranslateMessage
to activate the ID_VIEW_FULLSCREEN
accelerator in full screen mode.
// 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
// ...
Add a command handler for 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
Compile, run, and check the full screen implementation.
- Derive
CMainFrame
from CAutoUpdateUI
.
- Remove the
UPDATE_UI_MAP
macros and chain to CAutoUpdateUI
in the message map.
- Call
UIAddMenu()
in CMainFrame::OnCreate()
.
// 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
// ...
Compile, run, and check the UpdateUI implementation.
This sample implements a basic MDI split frame, merging code issued by the WTL AppWizard for the MDI and Explorer (split layout) applications.
CMainFrame
derives from CMDISplitFrameWindowImpl<CMainFrame>
; the left pane members, command handlers are added, ID_VIEW_TREEPANE
is added to the menu resource.
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()
The OnCreate()
member creates the left pane, and calls the overridden CMDISplitFrameWindowImpl::CreateMDIClient()
which sets the right pane to 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;
}
First part conclusion
This first part has presented some simple enhancements to the current WTL 8.0 frame management and message routing.
The second part will introduce a multiple views implementation and an application to frame and pane container classes.
Hope to see you there soon, cheers!
History
- July 29 2009: First release.