本系列第四部分聚焦 MFC 擴展 DLL:專為 MFC 應用程式擴展 MFC 類庫功能,導出介面可直接使用 MFC 類型(如 CString、CWnd 派生類),調用端無需轉換介面,如同使用 MFC 自身 DLL 般自然。
DllMain 由向導自動生成,含 AfxInitExtensionModule / AfxTermExtensionModule 與 CDynLinkLibrary 掛載資源鏈。__declspec(dllexport) / .def),但介面可直接暴露 MFC 派生類。extern "C" int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID) {
if (dwReason == DLL_PROCESS_ATTACH) {
TRACE0("MyExtDLL Initializing!\n");
if (!AfxInitExtensionModule(MyExtDLL, hInstance)) return 0;
new CDynLinkLibrary(MyExtDLL); // 掛載資源鏈
} else if (dwReason == DLL_PROCESS_DETACH) {
TRACE0("MyExtDLL Terminating!\n");
AfxTermExtensionModule(MyExtDLL);
}
return 1;
}
注意:若被 MFC 普通 DLL(如 ActiveX 控件)隱式鏈接,需將 new CDynLinkLibrary 移至導出初始化函數,由宿主 DLL 顯式調用,否則資源查找失敗。
// MyExtDLL.h
#ifndef AFX_DATA_EXPORT
#define AFX_DATA_EXPORT __declspec(dllexport)
#endif
#ifndef AFX_DATA_IMPORT
#define AFX_DATA_IMPORT __declspec(dllimport)
#endif
#ifndef AFX_CLASS_EXPORT
#define AFX_CLASS_EXPORT __declspec(dllexport)
#endif
#ifndef AFX_CLASS_IMPORT
#define AFX_CLASS_IMPORT __declspec(dllimport)
#endif
#ifndef AFX_API_EXPORT
#define AFX_API_EXPORT __declspec(dllexport)
#endif
#ifndef AFX_API_IMPORT
#define AFX_API_IMPORT __declspec(dllimport)
#endif
應用程式包含此頭檔時,定義 MYEXTDLL_IMPORT 宏切換為 dllimport。
需求:MFC CButton 僅支援「純文字」或「純位圖」,無法同時顯示。擴展類 CSXButton 實現「圖文混排」。
// SXButton.h
class AFX_CLASS_EXPORT CSXButton : public CButton {
DECLARE_DYNAMIC(CSXButton)
public:
CSXButton();
virtual ~CSXButton();
void SetBitmap(UINT nIDResource); // 設定位圖資源 ID
void SetTextAlign(UINT nAlign); // 文字對齊方式
protected:
afx_msg void OnPaint();
DECLARE_MESSAGE_MAP()
CBitmap m_bmp;
UINT m_nTextAlign;
};
// SXButton.cpp
IMPLEMENT_DYNAMIC(CSXButton, CButton)
BEGIN_MESSAGE_MAP(CSXButton, CButton)
ON_WM_PAINT()
END_MESSAGE_MAP()
void CSXButton::OnPaint() {
CPaintDC dc(this);
CRect rect; GetClientRect(rect);
// 1. 繪製背景/邊框
// 2. 若有位圖,計算位圖矩形並 dc.DrawState 或透明繪製
// 3. 計算文字矩形,dc.DrawText 按 m_nTextAlign 繪製
// 完整代碼略,核心為 DC 繪圖組合
}
// 應用程式專案設定
// Link → Input → Additional Dependencies: MyExtDLL.lib
// C/C++ → Preprocessor → Definitions: MYEXTDLL_IMPORT
#include "SXButton.h" // DLL 導出頭檔
// 對話框類成員
CSXButton m_btnCustom;
BOOL CMyDlg::OnInitDialog() {
CDialog::OnInitDialog();
m_btnCustom.SubclassDlgItem(IDC_MYBTN, this);
m_btnCustom.SetBitmap(IDB_MYICON); // 位圖資源在 DLL 或主程式均可
m_btnCustom.SetTextAlign(DT_CENTER | DT_VCENTER | DT_SINGLELINE);
m_btnCustom.SetWindowText(_T("圖文按鈕"));
return TRUE;
}
AFX_CLASS_EXPORT,應用端頭檔定義 MYEXTDLL_IMPORT 後包含。AfxFindResourceHandle 查找)或主程式,由協約決定。MFC 擴展 DLL 是構建 MFC 類庫級擴展、跨專案複用 MFC 派生類的標準化路徑,掌握其資源鏈機制與導出宏規範,能避開「資源找不到、類型不匹配、調試進不去」等經典坑點。