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

Sharp Layout

0.00/5 (No votes)
31 Jan 2005 1  
Sharp Layout manager for ATL/WTL.

Sharp Layout

Introduction

I will describe here what the article/code snippet does, why it's useful, the problem it solves etc. Splitter is good, but often I need more than just repositioning two panes - implementation of multiple panes, hide/show panes, frozen panes, resize manager, save/load layout. The idea is taken from the new VS.NET C# form editor. You can dock any window at any side or you can set anchor on any side of the window.

Using the code

So we have two kinds of windows - docking and anchored.

The following styles are applicable for docking windows.

  • SSP_DOCKTOP - docked at top.
  • SSP_DOCKBOTTOM - docked at bottom.
  • SSP_DOCKLEFT - docked at left.
  • SSP_DOCKRIGHT - docked at right.
  • SSP_PROPORTIONAL - pane size (width/height) will be relative to the layout size.
  • SSP_DOCKFILL - fill all empty space.

Any docking window can have a splitter - four pixels on opposite side, and splitter can be interactive.

  • SSP_SPLITTER - enable splitter (for docking windows only).
  • SSP_INTERACTIVE - enable interactive splitter.

And for anchored windows, we have.

  • SSP_ALIGNLEFT - left anchor.
  • SSP_ALIGNRIGHT - right anchor.
  • SSP_ALIGNTOP - top anchor.
  • AAP_ALIGNBOTTOM - bottom anchor.

Additionally, one more flag for both types of panes:

  • SSP_INGNORE - controls whether layout will be tried to reposition corresponding pane.

For using layout, you need to:

  • Derive your own class from CWindowImpl/CDialogImpl and CSharpLayout.
  • Chain message map to CSharpLayout.
  • Initialize panes.
class CSharpLayoutSampleView : public CDialogImpl<CSharpLayoutSampleView>,
    public CSharpLayoutImpl<CSharpLayoutSampleView>
{
public:
    enum { IDD = IDD_SHARPLAYOUTSAMPLE_FORM };

    BOOL PreTranslateMessage(MSG* pMsg)
    {
        return CWindow::IsDialogMessage(pMsg);
    }

    BEGIN_MSG_MAP(CSharpLayoutSampleView)
        MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
        MESSAGE_HANDLER(WM_CONTEXTMENU, OnContextMenu)
        MESSAGE_HANDLER(WM_INITMENUPOPUP, OnInitMenuPopup)
        MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
        COMMAND_ID_HANDLER(ID_1_SHOWTOPDOCKBAR, OnShowTop)
        COMMAND_ID_HANDLER(ID_1_SHOWLEFTDOCKBAR, OnShowLeft)
        CHAIN_MSG_MAP(CSharpLayoutImpl<CSharpLayoutSampleView>)
    END_MSG_MAP()

    LRESULT OnShowTop(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
    {
        //hide show top pane

        CWindow wnd = GetDlgItem(IDC_EDIT1);
        wnd.ShowWindow(wnd.IsWindowVisible() ? SW_HIDE : SW_SHOW);
        RecalcLayout();
        return 0;
    }
    LRESULT OnShowLeft(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
    {
        //hide show left pane

        CWindow wnd = GetDlgItem(IDC_LIST1);
        wnd.ShowWindow(wnd.IsWindowVisible() ? SW_HIDE : SW_SHOW);
        RecalcLayout();
        return 0;
    }

    LRESULT OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        CMenu menu;
        menu.LoadMenu(IDR_CONTEXTMENU);
        menu.GetSubMenu(0).TrackPopupMenu(
            0, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), m_hWnd);
        return 0;
    }
    LRESULT OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        //track pane state

        CMenuHandle menu((HMENU)wParam);
        menu.CheckMenuItem(ID_1_SHOWTOPDOCKBAR, 
            GetDlgItem(IDC_EDIT1).IsWindowVisible() ? MF_CHECKED : MF_UNCHECKED);
        menu.CheckMenuItem(ID_1_SHOWLEFTDOCKBAR, 
            GetDlgItem(IDC_LIST1).IsWindowVisible() ? MF_CHECKED : MF_UNCHECKED);
        return 0;
    }
    LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        //save layout to registry

        SaveLayout(HKEY_CURRENT_USER, _T("Software\\wtlsplit\\Layout"));
        return 0;
    }
    LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        //initialize panes

        SetPaneStyle(GetDlgItem(IDC_EDIT1), 
            SSP_DOCKTOP|SSP_SPLITTER, false);
        SetPaneStyle(GetDlgItem(IDC_LIST1), 
            SSP_DOCKLEFT|SSP_SPLITTER|SSP_INTERACTIVE|SSP_PROPORTIONAL, false);
        SetPaneStyle(GetDlgItem(IDC_BUTTON1), 
            SSP_ALIGNRIGHT|SSP_ALIGNTOP, false);
        SetPaneStyle(GetDlgItem(IDC_BUTTON2), 
            SSP_ALIGNRIGHT|SSP_ALIGNTOP, false);
        SetPaneStyle(GetDlgItem(IDC_BUTTON3), 
            SSP_ALIGNRIGHT|SSP_ALIGNBOTTOM, false);
        SetPaneStyle(GetDlgItem(IDC_EDIT2), 
            SSP_ALIGNRIGHT|SSP_ALIGNLEFT|SSP_ALIGNBOTTOM|SSP_ALIGNTOP, false);
        //load layout from registry

        LoadLayout(HKEY_CURRENT_USER, _T("Software\\wtlsplit\\Layout"), true);
        return 0;
    }
};

Function reference

There is nothing to comment, all functions are self documented.

  • bool SetPaneStyle(CWindow wnd, int style, bool update)
  • bool SetPaneWidth(CWindow wnd, int width, bool update)
  • bool SetPaneHeight(CWindow wnd, int height, bool update)
  • bool SetPaneDockSize(CWindow wnd, int size, bool update)
  • void RecalcLayout()
  • bool SaveLayout(HKEY hkey, LPCTSTR szkey)
  • bool LoadLayout(HKEY hkey, LPCTSTR szkey, bool update)

Hope it will be useful!

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