VC++ 6.0 原生不支援對話方塊控制項隨視窗大小自動調整。`DynamicLayout` 是一個輕量級 MFC 佈局管理器,採用**面板巢狀**模型(參考 .NET `TableLayoutPanel`/`FlowLayoutPanel`),支援控制項錨定(上下左右)、分割條拖曳調整面板大小、最小/最大視窗限制、面板背景色。核心類別 `CDynamicLayout` 透明處理 `WM_SIZE`、`WM_MOUSEMOVE`、`WM_LBUTTONDOWN/UP` 等訊息,使用者僅需在 `OnInitDialog` 宣告式註冊佈局結構。
namespace DynamicLayout
{
class CDynamicLayout
{
public:
void InitLayout(CWnd* pDialog); // 必須最先呼叫
void SetDialogMinSize(int cx, int cy);
void SetDialogMaxSize(int cx, int cy);
void SetBkColor(LPCTSTR pszPanelName, COLORREF clr);
// 註冊面板:pszName=面板名稱, pszParent=父面板名稱(""=根對話框)
// bLeft,bTop,bRight,bBottom = 錨定規則
void AddPanel(LPCTSTR pszName, LPCTSTR pszParent,
BOOL bLeft, BOOL bTop, BOOL bRight, BOOL bBottom);
// 註冊控制項到面板
void AddControl(int nCtrlID, LPCTSTR pszPanel,
BOOL bLeft, BOOL bTop, BOOL bRight, BOOL bBottom);
// 顯示/隱藏面板
void ShowPanel(LPCTSTR pszName, BOOL bShow);
// 在面板之間插入分割條
void SetSplit(LPCTSTR pszPanelName); // pszPanelName="" 為根分割條
// 核心訊息過濾器:必須在對話框 WindowProc 中呼叫
void FilterDynamicLayoutMessage(UINT msg, WPARAM wp, LPARAM lp);
};
}
class CMyDialog : public CDialog
{
DynamicLayout::CDynamicLayout m_layout;
// ...
virtual LRESULT WindowProc(UINT msg, WPARAM wp, LPARAM lp);
};
BOOL CMyDialog::OnInitDialog()
{
CDialog::OnInitDialog();
m_layout.InitLayout(this);
m_layout.SetDialogMinSize(200, 100);
m_layout.SetDialogMaxSize(800, 600);
// 根面板分上下
m_layout.AddPanel(_T("上"), _T(""), 1,1,1,1); // 四邊錨定
m_layout.AddPanel(_T("下"), _T(""), 0,1,1,1); // 底部錨定
// 上面板分左右
m_layout.AddPanel(_T("上左"), _T("上"), 1,1,1,0);
m_layout.AddPanel(_T("上右"), _T("上"), 1,1,1,1);
// 上右再分上下
m_layout.AddPanel(_T("上右下"), _T("上右"), 0,1,1,0);
// 配置控制項
m_layout.AddControl(IDC_TREE1, _T("上左"), 1,1,1,1);
m_layout.AddControl(IDC_LIST_LIST, _T("上右"), 1,1,1,1);
m_layout.AddControl(IDC_BTN_MODAL, _T("上右下"), 1,1,1,0);
m_layout.AddControl(IDC_BTN_MODELESS, _T("上右下"), 1,1,1,0);
m_layout.AddControl(IDOK, _T("上右下"), 1,1,1,0);
m_layout.AddControl(IDC_LIST2, _T("下左"), 1,1,1,1);
m_layout.AddControl(IDC_EDIT1, _T("下右"), 1,1,1,1);
m_layout.AddControl(IDC_STATIC_CMD, _T("下右"), 1,0,1,0);
m_layout.AddControl(IDC_EDIT2, _T("下右"), 1,0,1,1);
// 面板背景色區分
m_layout.SetBkColor(_T("上"), RGB(160,160,255));
m_layout.SetBkColor(_T("上右"), RGB(128,128,255));
m_layout.SetBkColor(_T("上右下"), RGB(128,255,128));
// 分割條
m_layout.SetSplit(_T("")); // 根:上/下 分割條
m_layout.SetSplit(_T("上")); // 上面板:左/右 分割條
m_layout.SetSplit(_T("下")); // 下面板:左/右 分割條
m_layout.ShowPanel(_T(""), TRUE); // 顯示所有
return TRUE;
}
LRESULT CMyDialog::WindowProc(UINT msg, WPARAM wp, LPARAM lp)
{
m_layout.FilterDynamicLayoutMessage(msg, wp, lp);
return CDialog::WindowProc(msg, wp, lp);
}






`DynamicLayout` 以宣告式 API 解決 VC++ 6.0 對話方塊佈局痛點,核心代碼約 500 行,零外部依賴,編譯輕量。面板巢狀 + 錨定 + 分割條 模型直觀強大,足以應對多數商業應用的複雜介面需求。現代專案若升級至 VS2010+,可直接使用 MFC 內建 `CMFCDynamicLayout`(`EnableDynamicLayout`),API 設計理念幾乎相同,遷移成本極低。