在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%3D1

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_