Share via


TN011:將 MFC 當成 DLL 的一部分來使用

此附注描述一般 MFC DLL,可讓您使用 MFC 程式庫作為 Windows 動態連結程式庫 (DLL) 的一部分。 它假設您熟悉 Windows DLL 並知道如何建置它們。 如需 MFC 擴充功能 DLL 的相關資訊,您可以建立 MFC 程式庫的延伸模組,請參閱 MFC 的 DLL 版本。

DLL 介面

一般 MFC DLL 假設應用程式與 DLL 之間的介面是在類似 C 的函式或明確匯出的類別中指定。 MFC 類別介面無法匯出。

如果 DLL 和應用程式都要使用 MFC,二者均可選擇要使用共用版本的 MFC 程式庫或靜態地連結至程式庫的複本。 應用程式和 DLL 可能都使用其中一個標準版本的 MFC 程式庫。

一般 MFC DLL 有幾個優點:

  • 使用 DLL 的應用程式不一定要使用 MFC,而且不一定要是 Visual C++ 應用程式。

  • 使用靜態連結至 MFC 的一般 MFC DLL 時,DLL 的大小只取決於使用和連結的 MFC 和 C 執行時間常式。

  • 透過動態連結至 MFC 的一般 MFC DLL,使用共用 MFC 版本的記憶體節省可能會相當重要。 不過,您必須使用 DLL 散發共用 DLL、Mfc version.dll > 和 Msvvcrt < version.dll > 。 <

  • DLL 的設計與如何實作類別無關。 您的 DLL 設計只會匯出至您要的 API。 因此,如果實作變更,一般 MFC DLL 仍然有效。

  • 使用靜態連結至 MFC 的一般 MFC DLL,如果 DLL 和應用程式都使用 MFC,則應用程式沒有問題,該應用程式想要與 DLL 不同的版本,反之亦然。 因為 MFC 程式庫是靜態連結至每個 DLL 或 EXE,所以您擁有什麼版本並不會造成任何問題。

API 限制

部分 MFC 功能會因為技術上的限制,或是因為這些服務通常由應用程式提供,而不適用於 DLL 版本。 若是目前版本的 MFC,唯一不適用的函式是 CWinApp::SetDialogBkColor

建置 DLL

編譯靜態連結至 MFC 的一般 MFC DLL 時,必須定義 符號 _USRDLL_WINDLL 。 您的 DLL 程式碼也必須使用下列編譯器參數進行編譯:

  • /D_WINDLL 表示編譯適用于 DLL

  • /D_USRDLL 指定您要建置一般 MFC DLL

當您編譯動態連結至 MFC 的一般 MFC DLL 時,您也必須定義這些符號,並使用這些編譯器參數。 此外,符號 _AFXDLL 必須加以定義,而且您的 DLL 程式碼必須使用下列項目進行編譯:

  • /D_AFXDLL 指定您要建置一般 MFC DLL,以動態方式連結至 MFC

應用程式和 DLL 之間的介面 (API) 必須明確地匯出。 建議您定義介面為低頻寬,並且可以的話只使用 C 介面。 直接 C 介面比較複雜的 C++ 類別容易維護。

將 API 放在 C 和 C++ 檔案都可包含的個別標頭中。 如需範例,請參閱 MFC 進階概念範例 DLLScreenCap 中的標頭 ScreenCap.h 。 若要匯出函式,請在您的模組定義檔 (.DEF) 的 EXPORTS 區段中輸入那些函式,或者在您的函式定義包括 __declspec(dllexport)。 使用 __declspec(dllimport) 將這些函式匯入用戶端可執行檔。

您必須在一般 MFC DLL 中動態連結至 MFC 的所有匯出函式開頭新增AFX_MANAGE_STATE宏。 這個巨集會將目前的模組狀態設定為 DLL 的狀態。 若要使用這個巨集,請將以下程式碼行加入至從 DLL 匯出的函式開頭:

AFX_MANAGE_STATE(AfxGetStaticModuleState( ))

WinMain - > DllMain

MFC 程式庫會定義標準 Win32 DllMain 進入點,以在一般 MFC 應用程式中將 CWinApp 衍生的物件初始化 為 。 將所有 DLL 特定的初始化放在 InitInstance 方法中,如同在一般 MFC 應用程式中一樣。

請注意, CWinApp::Run 機制不適用於 DLL,因為應用程式擁有主要訊息幫浦。 如果您的 DLL 顯示無強制回應對話方塊,或有自己的主框架視窗,則應用程式的主要訊息幫浦必須呼叫呼叫 CWinApp::P reTranslateMessage 的 DLL 匯出常式。

有關這個函式的使用,請參閱 DLLScreenCap 範例。

DllMainMFC 提供的函式會呼叫 您類別的 CWinApp::ExitInstance 方法,該方法衍生自 CWinApp DLL 卸載之前。

連結您的 DLL

使用靜態連結至 MFC 的一般 MFC DLL,您必須將 DLL 與 Nafxcwd.lib 或 Nafxcw.lib 連結,以及名為 Libcmt.lib 的 C 執行時間版本。 這些程式庫為預先建置,並且可以透過在執行 Visual C++ 設定時進行指定來加以安裝。

範例程式碼

如需完整的範例,請參閱 MFC 進階概念範例程式 DLLScreenCap。 此範例中的提示有以下幾點注意事項:

  • DLL 的編譯器旗標和應用程式的編譯器旗標不同。

  • DLL 的連結程式行和 .DEF 檔和應用程式的連結程式行和 .DEF 檔不同。

  • 使用 DLL 的應用程式不一定要在 C++ 中。

  • 應用程式和 DLL 之間的介面是可由 C 或 C++ 使用的 API,並且使用 DLLScreenCap.def 匯出。

下列範例說明在靜態連結至 MFC 的一般 MFC DLL 中定義的 API。 在此範例中,宣告是括在 C++ 使用者的 extern "C" { } 區塊中。 這有幾項優點。 首先,它可讓非 C++ 用戶端應用程式也能夠使用您的 DLL API。 第二,它降低了 DLL 的額外負荷,因為 C++ 名稱重整 (Name Mangling) 不會套用至已匯出的名稱。 最後,它可讓您更易明確地加入至 .DEF 檔案 (以便於依序匯出),而不需要擔心名稱修飾。

#ifdef __cplusplus
extern "C" {
#endif  /* __cplusplus */

struct TracerData
{
    BOOL bEnabled;
    UINT flags;
};

BOOL PromptTraceFlags(TracerData FAR* lpData);

#ifdef __cplusplus
}
#endif

API 所使用的結構不是從 MFC 類別衍生,而是在 API 標頭中定義。 這可減少 DLL 和應用程式之間介面的複雜度,並讓 C 程式能夠使用 DLL。

另請參閱

依編號顯示的技術提示
依分類區分的技術提示