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)
希望它对您有所帮助!