.cpl 的特殊 DLL,位於 Windows\System 目錄。CONTROL.EXE 啟動時遍歷加載所有 CPL。CPlApplet 函數,原型:
typedef LONG (APIENTRY *APPLET_PROC)(HWND hwndCpl, UINT msg, LONG lParam1, LONG lParam2);
CPL_INIT:初始化,分配資源。返回 0 表示失敗,控制面板將卸載該 CPL。CPL_GETCOUNT:返回該 CPL 支持的組件數(圖標數)。CPL_NEWINQUIRE:針對每個組件獲取圖標、名稱、提示信息(NEWCPLINFO 結構)。Win32 忽略舊版 CPL_INQUIRE。CPL_DBLCLK:讀取註冊表/INI 參數,彈出設置對話框。CPL_STOP(每組件)→ CPL_EXIT(整個 CPL)釋放資源。MFC 無現成 CPL 類,本文提供可繼承的基類,封裝消息分發與默認處理。
.cpl(Project Settings → General → Output file name)。CPlApplet 添加到 .def 導出表。// 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;
};
// 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 讀取註冊表、彈出對話框、保存設置。
CtrlPan.h/cpp,DEF 導出 CPlApplet。CControlPanel,重載 OnInquire/OnDblClk(多組件再重載 OnGetCount)。System 目錄測試。