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

VC++ 編寫 Windows 控制面板 CPL 組件:從原理到 MFC 封裝實戰

     編輯:關於VC++

一、控制面板組件 (CPL) 工作原理

  • 本質:擴展名為 .cpl 的特殊 DLL,位於 Windows\System 目錄。
  • 主程序 CONTROL.EXE 啟動時遍歷加載所有 CPL。
  • 每個 CPL 必須導出 CPlApplet 函數,原型:
    typedef LONG (APIENTRY *APPLET_PROC)(HWND hwndCpl, UINT msg, LONG lParam1, LONG lParam2);
  • 消息流程:
    1. CPL_INIT:初始化,分配資源。返回 0 表示失敗,控制面板將卸載該 CPL。
    2. CPL_GETCOUNT:返回該 CPL 支持的組件數(圖標數)。
    3. CPL_NEWINQUIRE:針對每個組件獲取圖標、名稱、提示信息(NEWCPLINFO 結構)。Win32 忽略舊版 CPL_INQUIRE。
    4. 用戶雙擊圖標 → CPL_DBLCLK:讀取註冊表/INI 參數,彈出設置對話框。
    5. 用戶按「應用」→ 保存參數;按「取消」→ 放棄修改。
    6. 控制面板關閉 → CPL_STOP(每組件)→ CPL_EXIT(整個 CPL)釋放資源。

二、MFC 封裝基類:CControlPanel

MFC 無現成 CPL 類,本文提供可繼承的基類,封裝消息分發與默認處理。

1. 專案設置

  1. AppWizard 創建「使用 MFC 的 DLL」,靜態鏈接 MFC。
  2. 修改輸出文件擴展名為 .cpl(Project Settings → General → Output file name)。
  3. 將 CPlApplet 添加到 .def 導出表。

2. 基類聲明

// CtrlPan.h
class CControlPanel {
public:
    CControlPanel(); virtual ~CControlPanel();
    // 可重載的虛函數
    virtual LONG OnDblClk(HWND hwndCPl, UINT uAppNum, LONG lData);
    virtual LONG OnExit();
    virtual LONG OnGetCount();
    virtual LONG OnInit();
    virtual LONG OnInquire(UINT uAppNum, NEWCPLINFO* pInfo);
    virtual LONG OnSelect(UINT uAppNum, LONG lData);
    virtual LONG OnStop(UINT uAppNum, LONG lData);
    // 導出入口
    static LONG APIENTRY CPlApplet(HWND hwndCPl, UINT uMsg, LONG lParam1, LONG lParam2);
    static CControlPanel* m_pThis;
};

3. 基類實現(消息分發)

// CtrlPan.cpp
CControlPanel* CControlPanel::m_pThis = NULL;

LONG APIENTRY CControlPanel::CPlApplet(HWND hwndCPl, UINT uMsg, LONG lParam1, LONG lParam2) {
    CControlPanel* pCtrl = m_pThis;
    ASSERT(pCtrl);
    switch (uMsg) {
        case CPL_DBLCLK:   return pCtrl->OnDblClk(hwndCPl, lParam1, lParam2);
        case CPL_EXIT:     return pCtrl->OnExit();
        case CPL_GETCOUNT: return pCtrl->OnGetCount();
        case CPL_INIT:     return pCtrl->OnInit();
        case CPL_NEWINQUIRE: return pCtrl->OnInquire(lParam1, (NEWCPLINFO*)lParam2);
        case CPL_INQUIRE:  return 0; // Win32 忽略
        case CPL_SELECT:   return pCtrl->OnSelect(lParam1, lParam2);
        case CPL_STOP:     return pCtrl->OnStop(lParam1, lParam2);
        default: break;
    }
    return 1;
}

// 默認實現
LONG CControlPanel::OnGetCount() { return 1; } // 默認 1 個組件
LONG CControlPanel::OnInit() { return 1; }
LONG CControlPanel::OnInquire(UINT uAppNum, NEWCPLINFO* pInfo) {
    pInfo->dwSize = sizeof(NEWCPLINFO);
    pInfo->dwFlags = 0;
    pInfo->hIcon = ::LoadIcon(AfxGetResourceHandle(), MAKEINTRESOURCE(1));
    lstrcpy(pInfo->szName, _T("Applet"));
    lstrcpy(pInfo->szInfo, _T("Default Control Panel Applet"));
    return 0;
}
LONG CControlPanel::OnDblClk(HWND, UINT, LONG) { return 0; }
LONG CControlPanel::OnSelect(UINT, LONG) { return 1; }
LONG CControlPanel::OnStop(UINT, LONG) { return 1; }
LONG CControlPanel::OnExit() { return 1; }

三、派生實現具體組件

#include "ctrlpan.h"
class CMyCpl : public CControlPanel {
public:
    virtual LONG OnInquire(UINT uAppNum, NEWCPLINFO* pInfo) override;
    virtual LONG OnDblClk(HWND hwndCPl, UINT uAppNum, LONG lData) override;
};

// 多組件時需重載
virtual LONG OnGetCount() override { return 2; }

OnInquire 填充圖標/名稱/提示;OnDblClk 讀取註冊表、彈出對話框、保存設置。

四、開發步驟總結

  1. AppWizard 創建 MFC DLL 專案,輸出改為 .cpl。
  2. 加入 CtrlPan.h/cpp,DEF 導出 CPlApplet。
  3. 派生 CControlPanel,重載 OnInquire/OnDblClk(多組件再重載 OnGetCount)。
  4. 設計對話框資源,ClassWizard 生成類,編寫參數讀寫邏輯。
  5. 編譯生成 Debug 版 .cpl,複製到 System 目錄測試。
  6. 驗證無誤後構建 Release 版部署。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved