日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

MFC下DLL编程(图解)

發布時間:2024/9/21 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MFC下DLL编程(图解) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

DLLDynamic?Link?Library,動態鏈接庫)是微軟公司為WindowsOS/2操作系統設計一種供應用程序在運行時調用的共享函數庫。DLL是應用程序的一種擴展,也是軟件共享和重用的傳統方法。

DLL除了可同時被多個應用程序共享外,還可以在不改變調用接口(從而不需修改使用它的應用程序)的情況下,改進和升級里面的庫函數。而且DLL與編寫它的語言無關,例如,用VC生成的規則DLL,可以被VBDelphi等生成的應用程序使用。

DLL可以用多種語言和工具編寫,我們這里只介紹如何使用MFC來編寫和使用DLL。相關說明文檔位于MSDN幫助的“目錄\開發工具和語言\Visual?Studio\Visual?C++\常見編程方法\DLL\”中。

8.1??基礎

本節先討論DLL與靜態庫的區別,然后列出幾種適合放置DLL的目錄,最后介紹MFC?DLL的三種類型。

8.1.1??DLL與靜態鏈接庫

靜態鏈接庫LibStatic?Link?Library),是在編譯的鏈接階段將庫函數嵌入到應用程序的內部。如果系統中運行的多個應用程序都包含所用到的公共庫函數,則必然造成很大的浪費。這樣即增加了鏈接器的負擔,也增大了可執行程序的大小,還加大了內存的消耗。Lib的好處是應用程序可以獨立運行,而不需要在操作系統中另外安裝對應的DLL

DLL采用動態鏈接,對公用的庫函數,系統只有一個拷貝(一般是位于系統目錄的*.DLL文件),而且只有在應用程序真正調用時,才加載到內存。在內存中的庫函數,也只有一個拷貝,可供所有運行的程序調用。當再也沒有程序需要調用它時,系統會自動將其卸載,并釋放其所占用的內存空間。參見圖8-1

DLL的缺點是應用程序不能獨立運行,需要在操作系統中另外安裝對應的DLL。例如,如果你的MFC項目被設置成“在共享DLL中使用MFC”的,則雖然生成的可執行程序很小,但是在其他沒有安裝Visual?C++(運行環境)的機器上是不能直接運行的,需要另外安裝MFC的動態鏈接庫(如mfc90.dll)。

8.1.2??放置DLL的目錄

為了使需要動態鏈接庫的應用程序可以運行,需要將DLL文件放在操作系統能夠找到的地方。Windows操作系統查找DLL的目錄順序為:

  • 所在目錄——當前進程的可執行模塊所在的目錄,即應用程序的可執行文件(*.exe)所在的目錄。
  • 當前目錄——進程的當前目錄。
  • 系統目錄——Windows操作系統安裝目錄的系統子目錄,如C:\Windows\?System32。可用GetSystemDirectory函數檢索此目錄的路徑
  • Windows目錄——Windows操作系統安裝目錄,如C:\Windows\。可用GetWindowsDirectory函數檢索此目錄的路徑
  • 搜索目錄——PATH環境變量中所包含的自動搜索路徑目錄,一般包含C:\Windows\C:\Windows\System32\等目錄。可在命令行用Path命令來查看和設置,也可以通過(在“我的電腦”右鍵菜單中選“屬性”菜單項)“系統屬性”中的環境變量,來查看或編輯“Path”系統變量和“PATH”用戶變量。
  • 8.1.3??MFC?DLL的類型

    使用MFC編寫的DLL,可以分成兩大類:

    l規則DLL——規則(regularDLL中所包含的函數,可以被所有Windows應用程序使用;

    共享MFC——DLL中不包含MFC庫函數,需要另外安裝MFC動態鏈接庫后才能使用;

    靜態MFC——DLL中包含MFC庫函數,可以脫離MFC動態鏈接庫獨立使用。

    擴展DLL——擴展(extensionDLL中所定義的類和函數,只能被所MFC應用程序使用。而且擴展DLL中不能包含MFC庫函數,也需要另外安裝MFC動態鏈接庫后才能使用。

    8.1.4??導出函數的方法

    使用MFC創建DLL時,從項目中導出(export)函數到DLL文件的方法有:

    ?使用模塊定義文件(.def)

    ?使用__declspec(dllexport)關鍵字或其替代宏AFX_EXT_CLASS。

    這兩種方法是互斥的,對每個函數只需用一種方法即可。另外,DEF文件只能用來導出函數,不能用于導出整個類。導出C++類,必須用__declspec(dllexport)關鍵字或其替代宏AFX_EXT_CLASS。

    ?

    1DEF文件

    模塊定義(module?definition)文件(.def)是包含一個或多個描述DLL各種屬性的模塊語句的文本文件。DEF文件必須至少包含下列模塊定義語句:

    l?文件中的第一個語句必須是LIBRARY語句。此語句將.def文件標識為屬于DLLLIBRARY語句的后面是DLL的名稱(缺省為DLL項目名)。鏈接器將此名稱放到DLL的導入庫中。

    l?EXPORTS語句列出名稱,可能的話還會列出DLL導出函數的序號值。通過在函數名的后面加上@符和一個數字,給函數分配序號值。當指定序號值時,序號值的范圍必須是從1N,其中NDLL導出函數的個數。

    即,DEF文件的格式為:(在這兩個語句之間,還可以加上可選的描述語句:DESCRIPTION?"庫描述串"。分號;后的文本內容行為注釋)

    ;?庫名.def

    LIBRARY?庫名

    EXPORTS

    函數名1?@1

    函數名2?@2

    ……

    函數名n?@n

    在使用MFC?DLL向導創建MFC?DLL項目時,VC會自動創建一個與項目同名但沒有任何函數導出項的DEF文件(項目名.def),格式為:

    ;?項目名.def?:?聲明?DLL?的模塊參數。

    ?

    LIBRARY??????"項目名"

    ?

    EXPORTS

    ????;?此處可以是顯式導出

    例如,項目名為RegDllDEF文件(RegDll.def)的內容為:

    ;?RegDll.def?:?聲明?DLL?的模塊參數。

    ?

    LIBRARY??????"RegDll"

    ?

    EXPORTS

    ;?此處可以是顯式導出

    如果生成擴展DLL并使用.def文件導出,則將下列代碼放在包含導出類的頭文件的開頭和結尾:

    #undef?AFX_DATA

    #define?AFX_DATA?AFX_EXT_DATA

    //?<你的頭文件體>

    #undef?AFX_DATA

    #define?AFX_DATA

    這些代碼行確保內部使用的MFC變量或添加到類的變量是從擴展DLL導出(或導入)的。例如,當使用DLAECRE_DYNAMIC派生類時,該宏擴展以將CRuntimeClass成員變量添加到類。省去這四行代碼可能會導致不能正確編譯或鏈接DLL,或在客戶端應用程序鏈接到DLL時導致錯誤。

    當生成DLL時,鏈接器使用.def文件創建導出(.exp)文件和導入庫(.lib)文件。然后,鏈接器使用導出文件生成DLL文件。隱式鏈接到DLL的可執行文件在生成時鏈接到導入庫。請注意,MFC本身就是使用.def文件從MFCx0.dll導出函數和類的。

    ?

    2.關鍵字或宏

    除了使用DEF文件來導出函數外,還可以在源程序中使用__declspec(dllexport)關鍵字或其替代宏AFX_EXT_CLASS:

    #define?AFX_EXT_CLASS??AFX_CLASS_EXPORT?(定義在頭文件afxv_dll.h中)

    #define?AFX_CLASS_EXPORT??__declspec(dllexport)?(定義在頭文件afxver_.h中)

    來導出函數和整個C++類。

    具體的格式為:

    l導出整個類:

    class?AFX_EXT_CLASS?類名[?:?public基類]

    {

    ……

    }

    l?導出類的成員函數:

    class?類名[?:?public基類]

    {

    AFX_EXT_CLASS?返回類型?函數名1(……)?;

    AFX_EXT_CLASS?返回類型?函數名2(……)?;

    ……

    }

    l?導出外部C格式的(全局)函數:

    extern?"C"?__declspec(dllexport)?返回類型?函數名(……)?

    {

    ……

    }

    如果希望用MFCC++)編寫的規則DLL中的函數,也能夠被非MFC程序來調用,需要為函數聲明指定extern?"C"不然,C++編譯器會使用C++類型安全命名約定(也稱作名稱修飾)和C++調用約定(使用此調用約定從C調用會很困難)。

    為了使用方便,可以定義宏:

    #define?DllExport?extern?"C"?__declspec(dllexport)

    然后再使用它,例如:

    DllExport?int?Add(int?d1,?int?d2)?{……}

    8.2??擴展DLL

    使用MFC編寫的擴展DLL,可以導出整個類(從而能使用類中的所有成員,包括數據成員和成員函數),也可以導出指定的若干(成員或全局)函數。

    下面我們通過一個四則運算的例子,看看如何用宏AFX_EXT_CLASS來編寫和使用導出整個C++類的擴展MFC?DLL

    8.2.1??創建DLL項目

    我們創建一個名為ExtDll的擴展DLL的“Visual?C++”之“MFC”的“MFC?DLL”項目,注意需選中“創建解決方案的目錄”復選框,參見圖8-2

    ?

    8-2??新建MFC?DLL項目ExtDll的對話框

    ?

    按“確定”鈕,彈出“MFC?DLL向導”對話框。在“DLL類型”欄中,選中“擴展DLL”單選鈕,參見圖8-3。按“完成”鈕,創建ExtDll解決方案和項目。

    ?

    8-3??選擇“擴展DLL”的MFC?DLL向導對話框

    8.2.2??添加導出類

    為新項目添加用于四則計算的導出類CCompute。方法有多種,可以在項目管理區的“類視圖”頁中,選中項目名“ExtDll”,按鼠標右鍵,在彈出菜單中選“添加\類”。在彈出的“添加類”對話框中,選擇“Visual?C++”之“MFC”的“MFC類”項,參見圖8-4

    ?

    8-4??添加類對話框

    ?

    按“添加”鈕,彈出“MFC類向導”對話框。在“類名”欄中鍵入“CCompute”,在“基類”下拉式列表,選“CObject”,參見圖8-5。按“完成”鈕,添加該類到ExtDll項目。

    ?

    8-5??MFC類向導對話框

    8.2.3??編寫導出類代碼

    我們將整個CCompute類設為導出類,并在里面添加2個成員變量、1個構造函數和4個用于四則運算的成員函數,外加1個演示導出函數的取模全局函數Mod

    下面是CCompute類的頭文件(Compute.h),其中紅色的部分是自己添加:(注意導出宏AFX_EXT_CLASS的使用)

    #pragma once// CCompute 命令目標class AFX_EXT_CLASS CCompute : public CObject{public:int m_data1, m_data2;public:CCompute();CCompute(int d1, int d2);virtual ~CCompute();public:int Add();int Sub();int Mul();double Div();};AFX_EXT_CLASS int Mod(int d1, int d2);

    ?

    下面是CCompute類的代碼源文件(Compute.cpp),其中紅色為自己添加的部分:

    // Compute.cpp : 實現文件// #include "stdafx.h"#include "Compute.h"// CCompute CCompute::CCompute(){}CCompute::CCompute(int d1, int d2){m_data1 = d1;m_data2 = d2;}CCompute::~CCompute(){}// CCompute 成員函數int CCompute::Add(){return m_data1 + m_data2;}int CCompute::Sub(){return m_data1 - m_data2;}int CCompute::Mul(){return m_data1 * m_data2;}double CCompute::Div(){if (m_data2 == 0 ) {AfxMessageBox(L"Divided by zero!");return 0;}return (double)m_data1 / m_data2;}int Mod(int d1, int d2){if (d2 == 0 ) {AfxMessageBox(L"Modulo by zero!");return 0;}return d1 % d2;}

    ?

    編譯運行時,后彈出圖8-6所示的對話框:

    ?

    8-6??調試會話的可執行文件對話框

    要求你選擇或輸入使用此DLL的應用程序之可執行文件的名稱或路徑。這是因為DLL雖然包含了可運行函數的二進制代碼,但是它并不是獨立的應用程序,不能單獨運行。因此,我們必須編寫使用DLL的客戶程序。

    8.2.4??添加客戶程序項目

    為了演示擴展DLL的應用,我們在原解決方案ExtDll中,添加一個客戶程序項目ExtClient。具體做法是,打開新建項目對話框,選中“Visual?C++”之“MFC”的“MFC應用程序”模板,鍵入項目名ExtClient。注意,需選在對話框底部的“解決方案”下拉式列表中選中“添入解決方案”表項,參見圖8-7

    ?

    8-6??新建客戶程序項目的對話框

    ?

    按“確定”鈕進入“MFC應用程序向導”對話框,在“應用程序類型”頁,選中“基于對話框”單選鈕,按“完成”添加項目。

    此時,ExtDll解決方案包含兩個項目:DLL項目ExtDll和客戶程序項目ExtClient,生成的文件目錄結構為:

    ExtDll?←解決方案目錄

    Debug?←解決方案的調試目錄

    Release?←解決方案的發行目錄

    ExtDll?←DLL項目目錄

    Debug?←DLL的調試目錄

    Release?←DLL的發行目錄

    res?←DLL的資源目錄

    ExtClient?←客戶程序項目目錄

    Debug?←客戶程序的調試目錄

    Release?←客戶程序的發行目錄

    res?←客戶程序的資源目錄

    8.2.5??設置依賴項(個人看還要添加引用ExtDll)

    為了使客戶程序可以調用DLL,需要將它們關聯起來。最簡單的辦法是設置DLL項目為客戶項目的依賴項。具體做法是,在項目管理區中選中客戶項目名“ExtClient”,選中菜單項“項目\項目依賴項”,在彈出的“項目依賴項”對話框中,選中“依賴欄”中的“ExtDll”復選框,參見圖8-7

    ?

    8-7??設置ExtClient項目依賴項的對話框

    8.2.6??編寫客戶程序代碼

    1.編輯對話框資源

    添加表示操作數的2個靜態文本框和2個文本編輯框(ID值分別為IDC_DATA1和IDC_DATA2)、5個表示四則運算和取模運算的按鈕(ID值分別為IDC_ADDIDC_SUBIDC_MULIDC_DIVIDC_MOD)、表示計算結果的1個靜態文本框和1個文本編輯框(ID值為IDC_RESULT),刪除原來“確定”按鈕,將原來的“取消”按鈕的“Caption”屬性值改為“退出”,參見圖8-8

    ?

    8-8??客戶程序的對話框界面

    ?

    2.添加控件變量

    為了動態獲取用戶輸入的數據,我們需要為2個表示操作數據的文本編輯框,添加控件的Value值類別int型變量m_iData1和m_iData2

    3.添加事件處理

    分別對5個計算按鈕,為對話框類CExtClientDlg添加按鈕通知消息BN_CLICKED(鼠標單擊)事件的處理程序OnBnClickedAdd等。

    4.編寫代碼

    為了讓客戶程序可以使用DLL項目中的計算類CCompute,需要在客戶程序對話框類CExtClientDlg的頭文件

    ?

    在ExtClientDlg.h?中

    添加??#include?"..\ExtDll\Compute.h"//相對路徑(這個比絕對路徑要好),看情況..\表示相對自己上一級目錄。用來引入CCompute類。

    檢查class?CAboutDlg?:?public?CDialogEx?中的,對話框數據enum?{?IDD?=?操作對話框數據ID?};

    在對話框類的定義中,手工添加公共型類變量和成員函數:

    public:???CCompute?*m_pComp; ???void?Comp(UINT?nID);

    ?

    ?

    ?ExtClientDlg.c?//文件

    // CExtClientDlg 對話框class CExtClientDlg : public CDialog{……public:int m_iData1;int m_iData2;CCompute *m_pComp;void Comp(UINT nID);afx_msg void OnBnClickedAdd();afx_msg void OnBnClickedSub();afx_msg void OnBnClickedMul();afx_msg void OnBnClickedDiv();afx_msg void OnBnClickedMod(); };
    在客戶對話框類ExtClientDlg.cpp的初始化對話框成員函數OnInitDialog中,手工添加設置數據編輯框初值的代碼(紅色部分): BOOL CExtClientDlg::OnInitDialog(){CDialog::OnInitDialog();……// TODO: 在此添加額外的初始化代碼 SetDlgItemInt(IDC_DATA1, 5);SetDlgItemInt(IDC_DATA2, 3);return TRUE; // 除非將焦點設置到控件,否則返回 TRUE }

    ?

    ?

    代碼文件ExtClientDlg.cpp中其他新加內容有:(其中紅色部分為手工添加的)

    void CExtClientDlg::OnBnClickedAdd(){// TODO: 在此添加控件通知處理程序代碼 Comp(IDC_ADD);}void CExtClientDlg::OnBnClickedSub(){// TODO: 在此添加控件通知處理程序代碼 Comp(IDC_SUB); }void CExtClientDlg::OnBnClickedMul(){// TODO: 在此添加控件通知處理程序代碼 Comp(IDC_MUL);}void CExtClientDlg::OnBnClickedDiv(){// TODO: 在此添加控件通知處理程序代碼 Comp(IDC_DIV);} void CExtClientDlg::OnBnClickedMod(){// TODO: 在此添加控件通知處理程序代碼 Comp(IDC_MOD);}void CExtClientDlg::Comp(UINT nID){UpdateData(); // 動態獲取用戶輸入的數據并賦值給對應的控件變量m_pComp = new CCompute(m_iData1, m_iData2); // 創建計算對象int r;double dr;switch(nID) { // 進行四則和取模運算case IDC_ADD: r = m_pComp->Add(); break;case IDC_SUB: r = m_pComp->Sub(); break;case IDC_MUL: r = m_pComp->Mul(); break;case IDC_DIV: dr = m_pComp->Div(); break;case IDC_MOD: r = Mod(m_iData1, m_iData2); break;}delete m_pComp;if (nID != IDC_DIV) SetDlgItemInt(IDC_RESULT, r); // 顯示整數結果else { // 顯示除法所得的實數結果wchar_t buf[20];swprintf_s(buf, 20, L"%g", dr);SetDlgItemText(IDC_RESULT, buf);}}//修改點擊退出按鈕動作----退出void CExtClientDlg::OnBnClickedCancel(){// TODO:在此添加控件通知處理程序代碼 exit(0); }

    ?

    ?

    8.2.7??編譯運行

    為了運行客戶程序,需要將客戶程序項目設置成啟動項目。具體做法是,先在項目管理區中選中ExtClient項目,然后選擇菜單項“項目\設為啟動項目”。

    編譯后,會在解決方案的DebugRelease目錄中生成動態鏈接庫文件ExtDll.dll和客戶程序的可執行文件ExtClient.exe,以及DLL的導出文件ExtDll.exp和(靜態連接)庫文件ExtDll.lib如果出現:

    >ExtClientDlg.obj?:?error?LNK2019:?無法解析的外部符號?"__declspec(dllimport)?public:?__thiscall?CCompute::CCompute(int,int)"?(__imp_??0CCompute@@QAE@HH@Z),該符號在函數?"public:?void?__thiscall?CExtClientDlg::Comp(unsigned?int)"?(?Comp@CExtClientDlg@@QAEXI@Z)?中被引用

    1>ExtClientDlg.obj?:?error?LNK2019:?無法解析的外部符號?"__declspec(dllimport)?public:?virtual?__thiscall?CCompute::~CCompute(void)"?(__imp_??1CCompute@@UAE@XZ),該符號在函數?"public:?virtual?void?*?__thiscall?CCompute::`scalar?deleting?destructor'(unsigned?int)"?(??_GCCompute@@UAEPAXI@Z)?中被引用

    1>D:\ExtDll\Debug\ExtClient.exe?:?fatal?error?LNK1120:?7?個無法解析的外部命令

    這樣的錯誤是因為缺少lib庫導致添加操作如下,這里是缺少

    右鍵“ExtClient”項目名稱出現

    下一步添加lib

    添加路徑:

    ?

    問題解決。

    運行結果如圖8-9所示:

    ?

    8-9??客戶程序ExtClient的運行結果

    8.3??規則DLL

    使用MFC編寫的規則DLL,雖然只能導出函數而不能導出整個類,但是其導出的函數卻可以其他被非MFC應用程序所調用。下面我們仍通過上面的四則運算的例子,看看如何用關鍵字__declspec(dllexport)extern?"C"來編寫和使用導出若干(全局)C函數的規則MFC?DLL

    8.3.1??創建DLL項目

    我們創建一個名為RegDll的規則DLL的“Visual?C++”之“MFC”的“MFC?DLL”項目,注意仍需選中“創建解決方案的目錄”復選框,參見圖8-10

    ?

    8-10??新建MFC?DLL項目RegDll的對話框

    ?

    按“確定”鈕,彈出“MFC?DLL向導”對話框。在“DLL類型”欄中,選中“使用共享MFC?DLL的規則DLL”單選鈕,參見圖8-11。按“完成”鈕,創建RegDll解決方案和項目。

    ?

    8-11??選擇規則DLLMFC?DLL向導對話框

    ?

    也可以選擇“帶靜態鏈接MFC的規則DLL”,差別是所生成的DLL中會包含MFC庫,當然所生成的庫文件也會大一些(但因此可不用另外安裝MFC動態鏈接庫)。例如,在此例中,選共享MFC所生成的RegDll.dll文件只有13KB大,而選擇靜態MFC的則有199KB

    規則DLL項目是使用共享MFC還是使用靜態MFC,也可以在生成DLL項目之后,通過項目屬性對話框的“配置屬性\常規”頁中的“MFC的使用”欄中的下拉式列表選項來切換,這一點與普通MFC應用程序項目的類似

    8.3.2??使用DEF文件導出函數

    1.編輯DEF文件

    在項目管理區中,選擇“解決方案資源管理器”頁,展開“RegDll”項目項,雙擊其“RegDll.def”子項,打開DLL項目中自動生成的DEF文件。在該DEF文件中加入需要導出的5個函數項:(紅色部分為手工添加的)

    ;?RegDll.def?:?聲明?DLL?的模塊參數。

    ?

    LIBRARY??????"RegDll"

    ?

    EXPORTS

    ????;?此處可以是顯式導出

    ????Add @1

    ????Sub @2

    ????Mul @3

    ????Div @4

    ? ? Mod @5

    2.編寫導出函數代碼

    可以在RegDll項目的應用程序類的代碼文件RegDll.cpp的尾部手工添加如下代碼:

    extern "C" int Add(int d1, int d2) { return d1 + d2;}extern "C" int Sub(int d1, int d2) { return d1 - d2;}extern "C" int Mul(int d1, int d2) { return d1 * d2;}extern "C" double Div(int d1, int d2) {if (d2 == 0) {AfxMessageBox(L"Divided by zero!");return 0;}return (double)d1 / d2;}extern "C" int Mod(int d1, int d2) {return d1 % d2;}

    ?

    注意,函數前的extern?"C"是不可少的,它指定按C語言約定來生成導出函數。不然,缺省情況下,C++編譯器會生成冗長的函數修飾符,不能簡單地用函數名來調用。

    8.3.3??使用關鍵字__declspec(dllexport)導出函數

    也可以不修改DEF文件,而在代碼文件中直接用關鍵字__declspec(dllexport)和extern?"C"來指定導出函數。對應的代碼為:(也加在RegDll.cpp的尾部)

    #define DllExport extern "C" __declspec(dllexport)DllExport int Add(int d1, int d2) { return d1 + d2;}DllExport int Sub(int d1, int d2) { return d1 - d2;}DllExport int Mul(int d1, int d2) { return d1 * d2;}DllExport double Div(int d1, int d2) {if (d2 == 0) {AfxMessageBox(L"Divided by zero!");return 0;}return (double)d1 / d2;}DllExport int Mod(int d1, int d2) {if (d2 == 0) {AfxMessageBox(L"Modulo by zero!");return 0;}return d1 % d2;}

    ?

    8.3.4??編寫客戶程序?

    1.添加客戶程序項目

    與上節類似,為例演示DLL的調用,我們也為RegDLL解決方案添加一個客戶程序——基于對話框的MFC應用程序項目RegClient,參見圖8-12

    ?

    8-12??添加客戶程序項目RegClient的對話框

    ?

    2.設置依賴項

    我們也通過設置DLL項目為客戶項目的依賴項將RegClientRegDll.dll關聯起來,參見圖8-13

    ?

    8-13??設置RegClient項目依賴項的對話框

    ?

    3.編輯對話框資源

    為了節省時間,避免重復勞動,可以復制ExtClient項目中的對話框。具體做法是:在RegDll解決方案環境中打開ExtDll解決方案中ExtClient項目的資源文件ExtClient.rc文件,(用鼠標或按Ctrl?+?A組合鍵)選中其主對話框中的所有控件,(按Ctrl?+?CCtrl?+?Insert組合鍵)復制它們到剪接板。然后打開RegClient項目的主對話框編輯器,先刪除其中的所有控件,然后再粘貼剪接板中的控件到對話框,參見圖8-8具體操作如下:

    ?

    打開ExtClient.rc文件

    ?

    如下圖

    ?

    選擇主對話框:

    ?

    復制粘貼

    ?

    4.編寫代碼

    類似ExtClient程序,我們也需要為2個數據編輯框添加類變量,并逐個為運算符按鈕添加單擊事件處理函數。在頭文件RegClientDlg.h的尾部會出現如下代碼:(其中紅色的Comp函數原型是手工添加的)

    public:int m_iData1;int m_iData2;void Comp(UINT nID);afx_msg void OnBnClickedAdd();afx_msg void OnBnClickedSub();afx_msg void OnBnClickedMul();afx_msg void OnBnClickedDiv();afx_msg void OnBnClickedMod();

    ?

    在客戶對話框類RegClientDlg.cpp的初始化對話框成員函數OnInitDialog中,手工添加設置數據編輯框初值的代碼(紅色部分):

    BOOL CRegClientDlg::OnInitDialog(){CDialog::OnInitDialog();……// TODO: 在此添加額外的初始化代碼 SetDlgItemInt(IDC_DATA1, 5);SetDlgItemInt(IDC_DATA2, 3);return TRUE; // 除非將焦點設置到控件,否則返回 TRUE }對應的代碼文件RegClientDlg.cpp尾部新增的代碼為:(其中紅色部分是手工添加的)void CRegClientDlg::OnBnClickedAdd(){// TODO: 在此添加控件通知處理程序代碼 Comp(IDC_ADD);}void CRegClientDlg::OnBnClickedSub(){// TODO: 在此添加控件通知處理程序代碼 Comp(IDC_SUB);}void CRegClientDlg::OnBnClickedMul(){// TODO: 在此添加控件通知處理程序代碼 Comp(IDC_MUL);}void CRegClientDlg::OnBnClickedDiv(){// TODO: 在此添加控件通知處理程序代碼 Comp(IDC_DIV);}void CRegClientDlg::OnBnClickedMod(){// TODO: 在此添加控件通知處理程序代碼 Comp(IDC_MOD);}#define DllImport extern "C" _declspec(dllimport)DllImport int Add(int d1, int d2);DllImport int Sub(int d1, int d2);DllImport int Mul(int d1, int d2);DllImport double Div(int d1, int d2);DllImport int Mod(int d1, int d2);void CRegClientDlg::Comp(UINT nID){UpdateData();int r;double dr;switch(nID) {case IDC_ADD: r = Add(m_iData1, m_iData2); break;case IDC_SUB: r = Sub(m_iData1, m_iData2); break;case IDC_MUL: r = Mul(m_iData1, m_iData2); break;case IDC_MOD: r = Mod(m_iData1, m_iData2); break;case IDC_DIV: dr = Div(m_iData1, m_iData2); break;}if (nID != IDC_DIV) SetDlgItemInt(IDC_RESULT, r);else {wchar_t buf[20];swprintf_s(buf, 20, L"%g", dr);SetDlgItemText(IDC_RESULT, buf);}}

    ?

    5.編譯運行

    似上節的ExtClient項目,先設置RegClient項目為啟動項目,再編譯運行,結果如圖8-14所示:

    ?

    8-14??客戶程序RegClient的運行結果

    ?

    總結

    以上是生活随笔為你收集整理的MFC下DLL编程(图解)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。