本系列第三部分詳細講解 MFC 普通 DLL (Regular DLL):內部可使用 MFC,但導出介面必須為 C 風格函數或非 MFC 類,可被任意語言(VB、Delphi、C#、純 C++)調用。核心難點在於靜態/動態鏈接 MFC 的選擇與模塊狀態切換。
| 維度 | 靜態鏈接 MFC | 動態鏈接 MFC (共享 MFC DLL) |
|---|---|---|
| MFC 代碼 | 直接鏈接進 DLL 體積較大 | 運行時依賴 MFCxx.dll 體積小 |
| 資源處理 | 自動使用 DLL 自身資源,無需切換 | 默認使用宿主 EXE 資源句柄,必須手動切換模塊狀態 |
| 適用場景 | 簡單工具類 DLL、避免部署依賴 | 大型 DLL、多 DLL 共享 MFC、插件架構 |
Project → Settings → General → Microsoft Foundation Classes 下拉選單:
File → New → Projects → MFC AppWizard (dll)AfxSocketInit)、Source file comments。MFC 透過 AFX_MODULE_STATE 追蹤當前資源鏈。DLL 導出函數入口必須執行:
// 導出函數標準模板
extern "C" AFX_API_EXPORT void MyExportedFunction() {
AFX_MANAGE_STATE(AfxGetStaticModuleState()); // 關鍵:切換到 DLL 模塊狀態
// 此處安全使用 DLL 內資源:LoadIcon, DoModal, LoadString 等
CMyDialog dlg;
dlg.DoModal();
}
AFX_MANAGE_STATE 構造函數保存舊狀態並設定新狀態,析構函數自動恢復,確保線程安全與異常安全。
IDD_MYDLG,按鈕 IDC_HELLO。CMyDialog : CDialog,處理 BN_CLICKED 彈出 MessageBox。// MyDll.cpp
#include "stdafx.h"
#include "MyDll.h"
#include "MyDialog.h"
extern "C" AFX_API_EXPORT void ShowMyDialog() {
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CMyDialog dlg;
dlg.DoModal();
}
// 宿主 EXE (任意語言)
extern "C" __declspec(dllimport) void ShowMyDialog(); // VC++
// 或 Declare Sub ShowMyDialog Lib "MyDll.dll" () ' VB6
// 按鈕點擊
ShowMyDialog(); // 彈出 DLL 內對話框,資源正確加載
無需 AFX_MANAGE_STATE,直接使用 DLL 內資源。但 DLL 體積膨脹(約 +300KB),且多個靜態鏈接 DLL 同時載入會有重複 MFC 代碼。
F11 單步進入 DLL 源碼。MFC42.DLL / MSVCRT.DLL。掌握「鏈接模式選擇 → 資源切換 → 導出介面設計」三部曲,即可游刃有餘開發高兼容性的 MFC 普通 DLL。