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

無 Hook 換膚方案:基於控件子類化的動態皮膚框架

     編輯:VC++

痛點與思路

傳統換膚需逐個控件映射變量、調用 SubclassDlgItem,工程大時維護極其痛苦。本方案採用運行時自動掃描對話框子控件、按類別/樣式動態子類化,實現零侵入式換膚。

核心類:CLxpSkin

class CLxpSkin {
public:
    CLxpSkin(HWND hDlg);              // 一個實例對應一個對話框
    ~CLxpSkin();

    // 各類美化控件鏈表
    CList<CXPButton*, CXPButton*> m_btnList;
    CList<CEditEx*, CEditEx*> m_edtList;
    CList<CLineStatic*, CLineStatic*> m_lineList;
    CList<CFlatComboBox*, CFlatComboBox*> m_cmbList;
    CList<CExCheckBox*, CExCheckBox*> m_chkList;
    CList<CExGroupBox*, CExGroupBox*> m_grpList;

    // 靜態映射表:HWND -> CLxpSkin*
    static CMap<HWND, HWND, CLxpSkin*, CLxpSkin*> m_mapSkin;

    static BOOL InstallSkin(HWND hDlg);   // 安裝皮膚
    static void UnInstallSkin(HWND hDlg); // 卸載皮膚

private:
    HWND m_hDlg;
};

使用方法(極簡)

在對話框類中:

BOOL CMyDlg::OnInitDialog() {
    CDialog::OnInitDialog();
    CLxpSkin::InstallSkin(m_hWnd); // 一行代碼全搞定
    return TRUE;
}

void CMyDlg::OnDestroy() {
    CLxpSkin::UnInstallSkin(m_hWnd); // 清理
    CDialog::OnDestroy();
}

InstallSkin 核心邏輯

  1. 創建 CLxpSkin 實例,存入靜態 m_mapSkin。
  2. GetWindow(hDlg, GW_CHILD) 遍歷所有子控件。
  3. GetClassName 獲取類名,GetWindowLong(GWL_STYLE) 獲取樣式。
  4. 根據類名與樣式動態創建對應美化控件對象並 SubclassWindow:
  • Edit → CEditEx
  • Button:
    • BS_DEFPUSHBUTTON/BS_PUSHBUTTON → CXPButton
    • BS_AUTOCHECKBOX/BS_CHECKBOX → CExCheckBox
    • BS_GROUPBOX → CExGroupBox
  • Static (含 SS_ETCHEDHORZ) → CLineStatic (分割線美化)
  • ComboBox → CFlatComboBox
  • 將創建的對象指針存入對應鏈表,析構時統一 delete 釋放。
  • UnInstallSkin

    void CLxpSkin::UnInstallSkin(HWND hDlg) {
        CLxpSkin* pSkin = NULL;
        if (m_mapSkin.Lookup(hDlg, pSkin)) {
            delete pSkin; // 析構函數會遞刪所有子類化控件
            pSkin = NULL;
        }
    }

    優勢總結

    • 零代碼侵入:無需修改現有對話框佈局、變量聲明、DDX/DDV。
    • 統一管理:所有美化控件集中銷毀,無內存洩漏。
    • 擴展性強:新增控件類型只需擴展 InstallSkin 判斷邏輯與鏈表。
    • 功能可逆:隨時 UnInstallSkin 恢復原生控件外觀與行為。
    1. 上一篇文章:
    2. 下一篇文章:
    Copyright © 程式碼之家 All Rights Reserved