在DELPHI和.NET的可视化设计中,利用Splitter和Panel可以实现控件的分组和布局控制,在WTL中提供了SplitterWindow对于对话框程序非常方便,而提供的CPaneContainer只能容纳一个控件,不能达到完全可视化的目的.WINXGUI提供了嵌入对话框设计的方式,本文的PANE控制就是基于WINXGUI实现的.实际上在WTL中也可以实现类似控制,但是用WINXGUI实现起来尤其方便,并且WINXGUI本身支持可视化设计. 参见http://winxgui.com
利用WINGUI的子类化技术,可以实现PANE控制,利用类似WINGUI设计的宏可以简化设计,利用WTL的SplitterWindow可以实现窗口分割控制.这样通过Spliter和Pane可以在VS6.0的对话框上直接进行设计,其中Splitter控制可以使用StaticText控件占位生成或直接动态生成,而Pane可以直接子类化StaticText控件.
一个应用例子: 需要使用WINXGUI.
代码下载请见http://www.winxgui.com/forum/viewthread.php?tid=4&extra=page=1
WTL::CHorSplitterWindowEx m_left; int OnInitDialog(HWND hWnd, HWND wParam) ... { CenterWindow(); m_left.CreateFromID(m_hWnd,IDC_LEFT); m_left.SetSplitterPos(100); WINX_PANE_BEGIN(IDC_PANE2) WINX_PANEITEM(IDC_MY_EDIT,PANE_SIZE_X|PANE_SIZE_Y) WINX_PANE_END(); WINX_PANE_BEGIN(IDC_PANE1) WINX_PANEACCEL(IDR_ACCELERATOR) WINX_PANEITEM(IDC_HELP_BTN,PANE_MOVE_X) WINX_PANEITEM(IDC_HIDE_BTN,PANE_MOVE_X) WINX_PANE_END(); WINX_PANE_BEGIN(IDC_PANE3) WINX_PANEACCEL(IDR_ACCELERATOR) WINX_PANEITEM(IDOK,0) WINX_PANEITEM(IDCANCEL,0) WINX_PANEITEM(IDC_ABOUT,PANE_MOVE_Y) WINX_PANE_END(); CWindow pane1 = GetDlgItem(IDC_PANE1); pane1.SetParent(m_left); CWindow pane2 = GetDlgItem(IDC_PANE2); pane2.SetParent(m_left); m_left.SetSplitterPanes(pane1,pane2); return 0; }
PANE的源代码
// winx使用子类化(Subclass)技术实现Pane控制 // by QWL1996@GMAIL.COM /**/ /*用法:在对话框的初始化中使用,允许子类化GroupBox,Picture,StaticText三种控件 允许在对话框设计中直接作为Pane,容纳子控件,并进行布局控制. 如果使用Splitter控制Pane,则只能子类化StaticText控件例: WINX_DLGRESIZE_BEGIN(TRUE) // layout WINX_DLGRESIZE(IDC_STATIC1, ResizeAll) WINX_DLGRESIZE_END(); int OnInitDialog(HWND hWnd, HWND wParam) { CenterWindow(); WINX_PANE_BEGIN(IDC_STATIC1) WINX_PANEACCEL(IDR_ACCELERATOR) WINX_PANEITEM(IDC_BTN1,PANE_SIZE_X|PANE_MOVE_Y) WINX_PANEITEM(IDC_BTN2,0) //no move and no size WINX_PANE_END(); return 0; }*/ #ifndef _WINX_STATIC_PANE_H_ #define _WINX_STATIC_PANE_H_ #pragma once #define PANE_SIZE_NONE 0x00000000 #define PANE_MOVE_NONE 0x00000000 #define PANE_SIZE_X 0x00000001 #define PANE_SIZE_Y 0x00000002 #define PANE_MOVE_X 0x00000004 #define PANE_MOVE_Y 0x00000008 namespace winx ... {#ifndef WINX_DLGRESIZE_BEGIN_NOGRIPPER#define WINX_DLGRESIZE_BEGIN_NOGRIPPER(fMinSizeLimit) WINX_DLGRESIZE_BEGIN_EX(fMinSizeLimit) WINX_DLGRESIZE_ADDGRIPPER(FALSE) WINX_DLGRESIZE_MAP_BEGIN()#endif#define WINX_PANE_ACCEL() private: WINX_ACCEL_EX(_winx_hAccel); HACCEL _winx_hAccel; public: VOID winx_msg OnAccelInit(HWND hWnd) ...{ _winx_hAccel = NULL; } VOID winx_msg OnAccelLoad(int idAccel) ...{ _winx_hAccel = winx::LoadAccelerators(m_hWnd, idAccel); } VOID winx_msg OnAccelTerm(HWND hWnd) ...{ if (_winx_hAccel != NULL) ::DestroyAcceleratorTable(_winx_hAccel); _winx_hAccel = NULL; }class CStaticPane: public winx::Static<CStaticPane>...{public: WINX_DLG_ACCEL(); // enable accelerator WINX_PANE_ACCEL(); WINX_CMDS_BEGIN_EX() // command dispatcher ::SendMessage(::GetParent(hWnd),WM_COMMAND, wParam, (LPARAM)hWnd); return TRUE; WINX_CMDS_END_EX(); WINX_NOTIFY_BEGIN() *pResult = ::SendMessage(::GetParent(hWnd),WM_NOTIFY,(WPARAM)idCtrl,(LPARAM)pnmh); return TRUE; WINX_NOTIFY_END() WINX_DLGRESIZE_BEGIN_NOGRIPPER(TRUE) WINX_DLGRESIZE_END(); void AddItem(HWND hDlg, int id) ...{ RECT rect; GetWindowRect(&rect); CWindow item = ::GetDlgItem(hDlg,id); RECT rc; item.GetWindowRect(&rc); item.SetParent(m_hWnd); rc.left -= rect.left; rc.top -= rect.top; rc.right -= rect.left; rc.bottom -= rect.top; item.MoveWindow(&rc); } void AddResize(int m_nCtlID, DWORD m_dwResizeFlags) ...{ ATL::CWindow ctl = GetDlgItem(m_nCtlID); ATLASSERT(ctl.IsWindow()); RECT rectCtl = ...{ 0, 0, 0, 0 }; ctl.GetWindowRect(&rectCtl); ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rectCtl, 2); //DWORD dwGroupFlag = (nGroupStart != -1 && m_arrData.GetSize() == nGroupStart) ? _DLSZ_BEGIN_GROUP : 0; WTL::CDialogResize<DialogResizeClass>::_AtlDlgResizeData data = ...{ m_nCtlID, m_dwResizeFlags, ...{ rectCtl.left, rectCtl.top, rectCtl.right, rectCtl.bottom } }; _winx_resizer.m_arrData.Add(data); }};} // namespace winx #define WINX_PANE_BEGIN(nPaneID) ... { winx::CStaticPane::DoSubclassDlgItem(m_hWnd, nPaneID); winx::CStaticPane * pPane = winx::CStaticPane::UnsafeGetInstance(::GetDlgItem(m_hWnd,nPaneID)); pPane->ModifyStyleEx(0,WS_EX_TRANSPARENT,0);#define WINX_PANEACCEL(iAccel) pPane->OnAccelLoad(iAccel);#define WINX_PANEITEM(id, flags)...{ pPane->AddItem(m_hWnd,id); pPane->AddResize(id,flags);}#define WINX_PANE_END()} #endif // WINX_STATICPANE_H_
