DLL動態鏈接庫編程入門之三:MFC規則DLL(上)

      上一節中講解了非MFC DLL,本節將介紹如何創建MFC規則DLL及使用MFC規則DLL的方法。 

  一、MFC規則DLL概述

  MFC規則DLL的概念體現在兩方面:

  (1)它是MFC的

  “是MFC的”意味着可以在這種DLL的內部使用MFC;

  (2)它是規則的

  “是規則的”意味着它不同於MFC擴展DLL,在MFC規則DLL的內部雖然可以使用MFC,但是其與應用程序的接口不能是MFC。而MFC擴展DLL與應用程序的接口可以是MFC,可以從MFC擴展DLL中導出一個MFC類的派生類。

  Regular DLL能夠被所有支持DLL技術的語言所編寫的應用程序調用,當然也包括使用MFC的應用程序。在這種動態連接庫中,包含一個從CWinApp繼承下來的類,DllMain函數則由MFC自動提供。

  Regular DLL分爲兩類:

  (1)靜態鏈接到MFC 的規則DLL

  靜態鏈接到MFC的規則DLL與MFC庫(包括MFC擴展 DLL)靜態鏈接,將MFC庫的代碼直接生成在.dll文件中。在調用這種DLL的接口時,MFC使用DLL的資源。因此,在靜態鏈接到MFC 的規則DLL中不需要進行模塊狀態的切換。

  使用這種方法生成的規則DLL其程序較大,也可能包含重複的代碼。

  (2)動態鏈接到MFC 的規則DLL

  動態鏈接到MFC 的規則DLL 可以和使用它的可執行文件同時動態鏈接到 MFC DLL 和任何MFC擴展 DLL。在使用了MFC共享庫的時候,默認情況下,MFC使用主應用程序的資源句柄來加載資源模板。這樣,當DLL和應用程序中存在相同ID的資源時(即所謂的資源重複問題),系統可能不能獲得正確的資源。因此,對於共享MFC DLL的規則DLL,我們必須進行模塊切換以使得MFC能夠找到正確的資源模板。

       我們可以在Visual C++中設置MFC規則DLL是靜態鏈接到MFC DLL還是動態鏈接到MFC DLL。如圖1,依次選擇Visual C++的project -> Settings -> General菜單或選項,在Microsoft Foundation Classes中進行設置。

設置動態/靜態鏈接MFC DLL

圖1 設置動態/靜態鏈接MFC DLL

  二、MFC規則DLL的創建

  我們來一步步講述使用MFC嚮導創建MFC規則DLL的過程,首先新建一個project,如圖2,選擇project的類型爲MFC AppWizard(dll)。點擊OK進入如圖3所示的對話框

MFC DLL工程的創建

圖2 MFC DLL工程的創建

MFC DLL的創建選項

圖3 MFC DLL的創建選項

       圖3所示對話框中的1區選擇MFC DLL的類別。

  2區選擇是否支持automation(自動化)技術, automation 允許用戶在一個應用程序中操縱另外一個應用程序或組件。例如,我們可以在應用程序中利用 Microsoft Word 或Microsoft Excel的工具,而這種使用對用戶而言是透明的。自動化技術可以大大簡化和加快應用程序的開發。

  3區選擇是否支持Windows Sockets,當選擇此項目時,應用程序能在 TCP/IP 網絡上進行通信。 CWinApp派生類的InitInstance成員函數會初始化通訊端的支持,同時工程中的StdAfx.h文件會自動include <AfxSock.h>頭文件。

  添加socket通訊支持後的InitInstance成員函數如下:

C++代碼
  1. BOOL CRegularDllSocketApp::InitInstance()   
  2. {   
  3.     if (!AfxSocketInit())   
  4.     {   
  5.         AfxMessageBox(IDP_SOCKETS_INIT_FAILED);   
  6.         return FALSE;   
  7.     }   
  8.     return TRUE;   
  9. }  

       4區選擇是否由MFC嚮導自動在源代碼中添加註釋,一般我們選擇“Yes,please”。

       三、一個簡單的MFC規則DLL

  這個DLL的例子(屬於靜態鏈接到MFC 的規則DLL)中提供了一個如圖4所示的對話框。

MFC規則DLL例子

圖4 MFC規則DLL例子

  在DLL中添加對話框的方式與在MFC應用程序中是一樣的。

  在圖4所示DLL中的對話框的Hello按鈕上點擊時將MessageBox一個“Hello,pconline的網友”對話框,下面是相關的文件及源代碼,其中刪除了MFC嚮導自動生成的絕大多數註釋:

  第一組文件:CWinApp繼承類的聲明與實現

C++代碼
  1. // RegularDll.h : main header file for the REGULARDLL DLL   
  2. #if !defined(AFX_REGULARDLL_H__3E9CB22B_588B_4388_B778_B3416ADB79B3__INCLUDED_)   
  3. #define AFX_REGULARDLL_H__3E9CB22B_588B_4388_B778_B3416ADB79B3__INCLUDED_   
  4. #if _MSC_VER > 1000   
  5. #pragma once   
  6. #endif // _MSC_VER > 1000   
  7. #ifndef __AFXWIN_H__   
  8. #error include 'stdafx.h' before including this file for PCH   
  9. #endif   
  10. #include "resource.h" // main symbols   
  11. class CRegularDllApp : public CWinApp   
  12. {   
  13. public:   
  14. CRegularDllApp();   
  15. DECLARE_MESSAGE_MAP()   
  16. };   
  17. #endif   
  18. // RegularDll.cpp : Defines the initialization routines for the DLL.   
  19. #include "stdafx.h"   
  20. #include "RegularDll.h"   
  21. #ifdef _DEBUG   
  22. #define new DEBUG_NEW   
  23. #undef THIS_FILE   
  24. static char THIS_FILE[] = __FILE__;   
  25. #endif   
  26. BEGIN_MESSAGE_MAP(CRegularDllApp, CWinApp)   
  27. END_MESSAGE_MAP()   
  28. /////////////////////////////////////////////////////////////////////////////   
  29. // CRegularDllApp construction   
  30. CRegularDllApp::CRegularDllApp()   
  31. {   
  32. }   
  33. /////////////////////////////////////////////////////////////////////////////   
  34. // The one and only CRegularDllApp object   
  35. CRegularDllApp theApp;  

       分析:

       在這一組文件中定義了一個繼承自CWinApp的類CRegularDllApp,並同時定義了其的一個實例theApp。乍一看,您會以爲它是一個MFC應用程序,因爲MFC應用程序也包含這樣的在工程名後添加“App”組成類名的類(並繼承自CWinApp類),也定義了這個類的一個全局實例theApp。

  我們知道,在MFC應用程序中CWinApp取代了SDK程序中WinMain的地位,SDK程序WinMain所完成的工作由CWinApp的三個函數完成:

       virtual BOOL InitApplication( );
       virtual BOOL InitInstance( );
       virtual BOOL Run( ); //傳說中MFC程序的“活水源頭”

  但是MFC規則DLL並不是MFC應用程序,它所繼承自CWinApp的類不包含消息循環。這是因爲,MFC規則DLL不包含CWinApp::Run機制,主消息泵仍然由應用程序擁有。如果DLL 生成無模式對話框或有自己的主框架窗口,則應用程序的主消息泵必須調用從DLL 導出的函數來調用PreTranslateMessage成員函數。

  另外,MFC規則DLL與MFC 應用程序中一樣,需要將所有 DLL中元素的初始化放到InitInstance 成員函數中。

  第二組文件:自定義對話框類聲明及實現

  分析:

  這一部分的編程與一般的應用程序根本沒有什麼不同,我們照樣可以利用MFC類嚮導來自動爲對話框上的控件添加事件。MFC類嚮導照樣會生成類似ON_BN_CLICKED(IDC_HELLO_BUTTON, OnHelloButton)的消息映射宏。

  第三組文件:DLL中的資源文件

C++代碼
  1. //{{NO_DEPENDENCIES}}   
  2. // Microsoft Developer Studio generated include file.   
  3. // Used by RegularDll.rc   
  4. //   
  5. #define IDD_DLL_DIALOG 1000   
  6. #define IDC_HELLO_BUTTON 1000  

  分析:

       在MFC規則DLL中使用資源也與在MFC應用程序中使用資源沒有什麼不同,我們照樣可以用Visual C++的資源編輯工具進行資源的添加、刪除和屬性的更改。

  第四組文件:MFC規則DLL接口函數

C++代碼
  1. #include "StdAfx.h"   
  2. #include "DllDialog.h"   
  3. extern "C" __declspec(dllexportvoid ShowDlg(void)   
  4. {   
  5.     CDllDialog dllDialog;   
  6.     dllDialog.DoModal();   
  7. }  

       分析:

  這個接口並不使用MFC,但是在其中卻可以調用MFC擴展類CdllDialog的函數,這體現了“規則”的概類。

  與非MFC DLL完全相同,我們可以使用__declspec(dllexport)聲明或在.def中引出的方式導出MFC規則DLL中的接口。

  四、MFC規則DLL的調用

  筆者編寫了如圖5的對話框MFC程序來調用第三小節的MFC規則DLL,在這個程序的對話框上點擊“調用DLL”按鈕時彈出第三小節MFC規則DLL中的對話框。

MFC規則DLL的調用例子

圖5 MFC規則DLL的調用例子

  下面是“調用DLL”按鈕單擊事件的消息處理函數

C++代碼
  1. void CRegularDllCallDlg::OnCalldllButton()   
  2. {   
  3.     typedef void (*lpFun)(void);   
  4.     HINSTANCE hDll; //DLL句柄   
  5.     hDll = LoadLibrary("RegularDll.dll");   
  6.     if (NULL==hDll)   
  7.     {   
  8.         MessageBox("DLL加載失敗");   
  9.     }   
  10.     lpFun addFun; //函數指針   
  11.     lpFun pShowDlg = (lpFun)GetProcAddress(hDll,"ShowDlg");   
  12.     if (NULL==pShowDlg)   
  13.     {   
  14.         MessageBox("DLL中函數尋找失敗");   
  15.     }   
  16.     pShowDlg();   
  17. }  

       上述例子中給出的是顯示調用的方式,可以看出,其調用方式與上一節中非MFC DLL的調用方式沒有什麼不同。

鏈接地址:http://www.jizhuomi.com/software/297.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章