UseDlg,選 A simple DLL projectIDD_DLG_SHOW (僅保留 OK 鈕)、IDD_ABOUTBOX (Caption: About)UseDlg.rc,將 resource.h、UseDlg.rc 加入專案// UseDll.cpp
#include "resource.h"
HINSTANCE g_hInst = NULL;
HWND g_hDlg = NULL;
BOOL CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
BOOL CALLBACK AboutProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
BOOL APIENTRY DllMain(HANDLE hModule, DWORD reason, LPVOID lpReserved)
{
if (reason == DLL_PROCESS_ATTACH)
g_hInst = (HINSTANCE)hModule;
return TRUE;
}
extern "C" __declspec(dllexport) void ShowDlg()
{
// 建立非模態對話框
g_hDlg = CreateDialog(g_hInst, MAKEINTRESOURCE(IDD_DLG_SHOW), NULL, (DLGPROC)DlgProc);
ShowWindow(g_hDlg, SW_SHOW);
}
BOOL CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case WM_INITDIALOG: return TRUE;
case WM_COMMAND:
if (LOWORD(wp) == IDOK)
DialogBox(g_hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hDlg, (DLGPROC)AboutProc);
return TRUE;
case WM_CLOSE:
DestroyWindow(hDlg);
g_hDlg = NULL;
return TRUE;
}
return FALSE;
}
BOOL CALLBACK AboutProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
{
if (msg == WM_CLOSE) {
EndDialog(hDlg, 0);
return TRUE;
}
return FALSE;
}
Use,Dialog Based// UseDlg.cpp (呼叫端)
extern "C" __declspec(dllimport) void ShowDlg();
#pragma comment(lib, "Debug/UseDlg.lib")
void CUseDlg::OnButton1()
{
ShowDlg(); // 呼叫 DLL 匯出函數
}
UseDlg.dll、UseDlg.lib 複製到 Use\Debug 目錄g_hInst)CreateDialog (非模態) / DialogBox (模態) 直接指定資源 IDextern "C" __declspec(dllexport) 避免 C++ 名稱修飾因篇幅限制,此處略述核心差異:
| 類型 | 資源載入方式 | 典型用法 |
|---|---|---|
| MFC Extension DLL | 共享主程式資源鏈,**直接使用資源 ID** | 擴充 MFC 類別庫、自訂控制項 |
| MFC Regular DLL (共享 MFC DLL) | AfxFindResourceHandle / AfxSetResourceHandle 切換模組狀態 | 包含 MFC 對話框、視圖的功能模組 |
| MFC Regular DLL (靜態連結 MFC) | 同 Regular DLL,但體積較大 | 無 MFC DLL 部署環境時 |
// DLL 內部函數
void CMyDllClass::ShowMyDialog()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState()); // 關鍵:切換到 DLL 模組狀態
CMyDialog dlg;
dlg.DoModal(); // 此處資源 ID 會從 DLL 而非 EXE 載入
}
AFX_MANAGE_STATE 宏自動保存/還原 AfxGetResourceHandle(),確保資源正確載入。
| 錯誤現象 | 原因 | 解決 |
|---|---|---|
| 對話框不顯示/Assert 失敗 | 資源句柄指向 EXE 而非 DLL | Win32 DLL: 傳正確 hInst;MFC DLL: 加 AFX_MANAGE_STATE |
| 找不到資源 ID | 資源未編譯進 DLL、或 ID 衝突 | 檢查 .rc 檔是否加入專案、資源 ID 範圍避開系統保留值 |
| 模態對話框關閉後主視窗凍結 | 父視窗傳遞錯誤 (NULL vs 實際 HWND) | 非模態用 NULL 或主視窗;模態用實際父視窗 HWND |
| DLL 卸載時崩潰 | 非模態對話框未銷毀就 FreeLibrary | 提供 DLL 清理函數,應用程式退出前呼叫 DestroyWindow |