Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Frame Related Classes and Message Map Macros for Windows Mobile and Desktop WTL Applications (Part 1)

0.00/5 (No votes)
29 Jul 2009 1  
Message map macros, split frames, full screen implementation, and automatic mapping of UI elements.

FrameX1

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.

Split frame classes

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

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

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

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

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.


The SDIFrameX sample

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

Step 1: Derive CMainFrame from CSplitFrameWindowImpl and remove the intermediate CSplitterWindow

  • 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.

Step 2: Implement a Full Screen mode exited by the Escape key

  • 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.

Step 3: Derive CMainFrame from CAutoUpdateUI and remove the UPDATE_UI_MAP macros

  • 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.

The MDISplitFrame sample

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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here