資料輸入對話框常包含「必填欄位」與「選填欄位」。透過分隔線 (Picture Control) 與「更多/收合」按鈕,讓使用者自行決定是否顯示選填區域,提升介面簡潔度。
Picture Control (ID: IDC_DIVIDER) 作為分隔線,按鈕 IDC_MORE 切換狀態。ExpandDialog() 調整視窗大小,EnableVisibleChildren() 控制子控件啟用/停用。
class CExpandDlgDlg : public CDialog
{
public:
void EnableVisibleChildren();
void ExpandDialog(int nResourceID, BOOL bExpand);
// ...
protected:
afx_msg void OnMore();
};
void CExpandDlgDlg::ExpandDialog(int nResourceID, BOOL bExpand)
{
static CRect rcLarge, rcSmall;
CString strBtn;
if (rcLarge.IsRectNull()) // 首次執行計算兩種尺寸
{
CRect rcLandmark;
CWnd* pLandmark = GetDlgItem(nResourceID);
GetWindowRect(rcLarge);
pLandmark->GetWindowRect(rcLandmark);
rcSmall = rcLarge;
rcSmall.bottom = rcLandmark.top; // 僅保留分隔線上方
}
if (bExpand)
{
SetWindowPos(NULL, 0, 0, rcLarge.Width(), rcLarge.Height(),
SWP_NOMOVE | SWP_NOZORDER);
strBtn = _T("<< &Less");
}
else
{
SetWindowPos(NULL, 0, 0, rcSmall.Width(), rcSmall.Height(),
SWP_NOMOVE | SWP_NOZORDER);
strBtn = _T("&More >>");
}
SetDlgItemText(IDC_MORE, strBtn);
EnableVisibleChildren(); // 同步更新子控件狀態
}
void CExpandDlgDlg::EnableVisibleChildren()
{
CRect rcDlg;
GetWindowRect(rcDlg); // 目前可見區域
CWnd* pChild = GetWindow(GW_CHILD);
while (pChild)
{
CRect rcChild;
pChild->GetWindowRect(rcChild);
CRect rcIntersect;
// 若子控件與目前視窗區域相交則啟用,否則停用
pChild->EnableWindow(rcIntersect.IntersectRect(rcDlg, rcChild));
pChild = pChild->GetWindow(GW_HWNDNEXT);
}
}
void CExpandDlgDlg::OnMore()
{
static BOOL bExpand = TRUE;
ExpandDialog(IDC_DIVIDER, bExpand);
bExpand = !bExpand;
}
rcLarge 與收合後矩形 rcSmall。SetWindowPos 配合 SWP_NOMOVE | SWP_NOZORDER 僅改變寬高,位置與 Z-order 不變。EnableWindow,避免隱藏區域控件仍可透過 Tab 鍵焦點或快速鍵觸發。AnimateWindow (AW_SLIDE | AW_VER_POSITIVE) 實現滑動展開。bExpand 寫入登錄或 INI,下次啟動還原狀態。