首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

MFC 對話框動態展開/收合實作:分隔線控制與子控件啟用管理

     編輯:VC 教學

應用場景

資料輸入對話框常包含「必填欄位」與「選填欄位」。透過分隔線 (Picture Control) 與「更多/收合」按鈕,讓使用者自行決定是否顯示選填區域,提升介面簡潔度。

實作架構

  • 對話框資源:放置 Picture Control (ID: IDC_DIVIDER) 作為分隔線,按鈕 IDC_MORE 切換狀態。
  • 類別成員函數:ExpandDialog() 調整視窗大小,EnableVisibleChildren() 控制子控件啟用/停用。

完整程式碼

1. 標頭檔宣告


class CExpandDlgDlg : public CDialog
{
public:
    void EnableVisibleChildren();
    void ExpandDialog(int nResourceID, BOOL bExpand);
    // ...
protected:
    afx_msg void OnMore();
};

2. 核心實作


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;
}

運作原理

  1. 尺寸計算:首次呼叫時以分隔線控件位置為基準,記錄完整對話框矩形 rcLarge 與收合後矩形 rcSmall。
  2. 視窗縮放:SetWindowPos 配合 SWP_NOMOVE | SWP_NOZORDER 僅改變寬高,位置與 Z-order 不變。
  3. 子控件啟用同步:遍歷所有子視窗,依據其矩形是否與目前可見客戶區相交決定 EnableWindow,避免隱藏區域控件仍可透過 Tab 鍵焦點或快速鍵觸發。

擴充建議

  • 加入動畫效果:使用 AnimateWindow (AW_SLIDE | AW_VER_POSITIVE) 實現滑動展開。
  • 儲存使用者偏好:關閉對話框時將 bExpand 寫入登錄或 INI,下次啟動還原狀態。
  • 多階段展開:若有多組選填區域,可擴充為陣列管理多個分隔線與狀態。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved