ATLVisual Studio .NET 2002Visual C++ 7.1Visual Studio 6Visual C++ 7.0Visual Studio .NET 2003Visual C++ 6.0中间开发Visual StudioWindowsC++
Sharp Layout






4.80/5 (10投票s)
2005 年 1 月 31 日
2分钟阅读

43899

1290
用于 ATL/WTL 的 Sharp Layout 管理器。

引言
在这里,我将描述这篇文章/代码片段的作用、为什么它有用、它解决了什么问题等等。分割器很好,但通常我需要的不仅仅是重新定位两个窗格 - 实现多个窗格、隐藏/显示窗格、冻结窗格、调整大小管理器、保存/加载布局。这个想法来自新的 VS.NET C# 表单编辑器。您可以在任何一侧停靠任何窗口,或者可以在窗口的任何一侧设置锚点。
使用代码
所以我们有两种窗口 - 停靠和锚定。
以下样式适用于停靠窗口。
- SSP_DOCKTOP- 停靠在顶部。
- SSP_DOCKBOTTOM- 停靠在底部。
- SSP_DOCKLEFT- 停靠在左侧。
- SSP_DOCKRIGHT- 停靠在右侧。
- SSP_PROPORTIONAL- 窗格大小(宽度/高度)将相对于布局大小。
- SSP_DOCKFILL- 填充所有空白空间。
任何停靠窗口都可以有一个分割器 - 在相对侧的四个像素,并且分割器可以是交互式的。
- SSP_SPLITTER- 启用分割器(仅适用于停靠窗口)。
- SSP_INTERACTIVE- 启用交互式分割器。
对于锚定窗口,我们有。
- SSP_ALIGNLEFT- 左侧锚点。
- SSP_ALIGNRIGHT- 右侧锚点。
- SSP_ALIGNTOP- 顶部锚点。
- AAP_ALIGNBOTTOM- 底部锚点。
此外,还有另一个用于两种类型窗格的标志
- SSP_INGNORE- 控制是否尝试重新定位相应的窗格。
要使用布局,您需要
- 从 CWindowImpl/CDialogImpl和CSharpLayout派生您自己的类。
- 将消息映射链接到 CSharpLayout。
- 初始化窗格。
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; } };
函数参考
没有什么可评论的,所有函数都有自文档。
- 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)
希望它对您有所帮助!
