首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

VC++ DLL 編程深度解析(四):MFC 擴展 DLL 創建與導出類實戰

     編輯:VC 教學

本系列第四部分聚焦 MFC 擴展 DLL:專為 MFC 應用程式擴展 MFC 類庫功能,導出介面可直接使用 MFC 類型(如 CString、CWnd 派生類),調用端無需轉換介面,如同使用 MFC 自身 DLL 般自然。

MFC 擴展 DLL 特徵

  • 內部完整使用 MFC,DllMain 由向導自動生成,含 AfxInitExtensionModule / AfxTermExtensionModule 與 CDynLinkLibrary 掛載資源鏈。
  • 導出函數/類方式與普通 DLL 一致(__declspec(dllexport) / .def),但介面可直接暴露 MFC 派生類。
  • 僅能被同版本 MFC 共享庫的 MFC 應用程式調用(非 MFC 或靜態鏈接 MFC 的程式無法使用)。

向導生成的 DllMain 關鍵代碼

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。

實戰:導出增強按鈕類 CSXButton

需求:MFC CButton 僅支援「純文字」或「純位圖」,無法同時顯示。擴展類 CSXButton 實現「圖文混排」。

DLL 端:類定義與導出

// 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;
};

DLL 端:實現繪製邏輯

// 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;
}

編譯與部署檢查表

  • DLL 與應用程式必須使用相同版本 MFC 共享庫(VC6 對應 MFC42.dll,VS2019 對應 MFC140.dll 等)。
  • DLL 導出類使用 AFX_CLASS_EXPORT,應用端頭檔定義 MYEXTDLL_IMPORT 後包含。
  • 資源(位圖、圖示、對話框模板)可放在 DLL 內(透過 AfxFindResourceHandle 查找)或主程式,由協約決定。
  • 調試時將 DLL 專案與應用專案置於同一工作區,應用專案設為啟動項,斷點可直接進入 DLL 源碼。

MFC 擴展 DLL 是構建 MFC 類庫級擴展、跨專案複用 MFC 派生類的標準化路徑,掌握其資源鏈機制與導出宏規範,能避開「資源找不到、類型不匹配、調試進不去」等經典坑點。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved