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

MFC 彈出式控制項容器:CPopup 類別實現任意位置彈出控制項

     編輯:關於C語言

需要在按鈕下方、工具列按鈕旁、甚至視窗框架外彈出樹狀清單、下拉選單、日曆等控制項?`CPopup` 類別繼承自 `CMiniFrameWnd`,提供無標題列、無邊框的輕量級浮動視窗,可承載任意 `CWnd` 衍生控制項,支援自動定位(優先左下、空間不足時右/上對齊)、焦點管理與事件回呼介面。

類別架構


class CPopup : public CMiniFrameWnd {
public:
    // 顯示彈出控制項
    // pControl   : 要彈出的控制項 (ListBox, TreeCtrl, FormView, ActiveX...)
    // pCaller    : 觸發者視窗 (彈出結束時回歸焦點),可為 NULL
    // rcCaller   : 觸發者螢幕座標矩形 (按鈕區域、工具按鈕區域)
    // pEvents    : 選用事件介面指標
    bool Display(CWnd* pControl, CWnd* pCaller, CRect& rcCaller, IPopupCtrlEvent* pEvents = NULL);

protected:
    CPopup();                     // 動態建立 (CreateObject)
    virtual ~CPopup() {}
    void EndPopup(bool bAbort = false, bool bSetFocus = true); // 關閉彈出
    DECLARE_DYNCREATE(CPopup)
};

事件回呼介面 IPopupCtrlEvent


class IPopupCtrlEvent {
public:
    virtual bool OnInit() = 0;                 // 彈出前初始化
    virtual void OnShow() = 0;                 // 顯示後
    virtual void OnHide(bool bAbort) = 0;      // 隱藏/關閉
    virtual int OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) = 0;
    virtual int OnLButtonDown(UINT nFlags, CPoint point) = 0;
    virtual int OnLButtonUp(UINT nFlags, CPoint point) = 0;
    virtual IPopupCtrlEvent* GetInterfaceOf(HWND hWnd) = 0; // 查詢子控制項介面
};

使用範例:按鈕下方彈出樹狀清單


void CMyDialog::OnButtonPopup() {
    // 1. 確保控制項已建立 (可在 OnInitDialog 建立隱藏)
    if (!m_tree.m_hWnd) {
        m_tree.Create(WS_CHILD | WS_VISIBLE | TVS_HASBUTTONS | TVS_LINESATROOT,
                      CRect(0,0,200,150), this, IDC_POPUP_TREE);
        // 填充樹節點...
    }

    // 2. 取得按鈕螢幕座標
    CRect rcBtn;
    m_btn.GetWindowRect(&rcBtn);

    // 3. 動態建立 CPopup 並顯示
    CPopup* pPopup = (CPopup*)CPopup::CreateObject();
    pPopup->Display(&m_tree, this, rcBtn, this); // this 實作 IPopupCtrlEvent
}

關鍵特性

  • 自動定位:預設彈出於 `rcCaller` 左下角;若右側/下方空間不足,自動靠右/靠上對齊
  • 尺寸自適應:彈出視窗大小 = 控制項當前大小 (`GetWindowRect`)
  • 焦點管理:彈出時控制項獲得焦點;關閉時焦點回歸 `pCaller`
  • 框架外顯示:繼承 `CMiniFrameWnd`,可突破父視窗剪裁區域
  • 動態建立/銷毀:必須用 `CreateObject()` 建立,關閉時自動 `delete this`

實作 IPopupCtrlEvent 範例 (在對話框類別中)


bool CMyDialog::OnInit() {
    // 彈出前準備:展開樹節點、選取項目等
    return true;
}
void CMyDialog::OnShow() { /* 可播放動畫聲音 */ }
void CMyDialog::OnHide(bool bAbort) {
    if (!bAbort) {
        // 使用者正常選取,取得結果
        HTREEITEM hSel = m_tree.GetSelectedItem();
        // ...
    }
}
int CMyDialog::OnKeyDown(UINT nChar, ...) {
    if (nChar == VK_ESCAPE) return 1; // 1=關閉彈出, 0=繼續處理
    return 0;
}
// 其他滑鼠事件同理...
IPopupCtrlEvent* CMyDialog::GetInterfaceOf(HWND hWnd) {
    return (hWnd == m_tree.m_hWnd) ? this : NULL;
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved