亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

VC++動態鏈接庫編程之MFC擴展 DLL

2019-11-17 05:01:57
字體:
來源:轉載
供稿:網友
DLL類型入口函數 非 MFC DLL 編程者提供DllMain函數 MFC規則 DLL CWinApp對象的InitInstance 和 ExitInstance MFC擴展 DLL MFC DLL向導生成DllMain 函數
  對于MFC擴展DLL,系統會自動在工程中添加如下表所示的宏,這些宏為DLL和應用程序的編寫提供了方便。像AFX_EXT_CLASS、AFX_EXT_API、AFX_EXT_DATA這樣的宏,在DLL和應用程序中將具有不同的定義,這取決于_AFXEXT宏是否被定義。這使得在DLL和應用程序中,使用統一的一個宏就可以表示出輸出和輸入的不同意思。在DLL中,表示輸出(因為_AFXEXT被定義,通常是在編譯器的標識參數中指定/D_AFXEXT);在應用程序中,則表示輸入(_AFXEXT沒有定義)。

宏定義 AFX_CLASS_IMPORT __declspec(dlleXPort) AFX_API_IMPORT __declspec(dllexport) AFX_DATA_IMPORT __declspec(dllexport) AFX_CLASS_EXPORT __declspec(dllexport) AFX_API_EXPORT __declspec(dllexport) AFX_DATA_EXPORT __declspec(dllexport) AFX_EXT_CLASS #ifdef _AFXEXT
 AFX_CLASS_EXPORT
#else
 AFX_CLASS_IMPORT AFX_EXT_API #ifdef _AFXEXT
 AFX_API_EXPORT
#else
 AFX_API_IMPORT AFX_EXT_DATA #ifdef _AFXEXT
 AFX_DATA_EXPORT
#else
 AFX_DATA_IMPORT
  6.2 MFC擴展DLL導出MFC派生類

  在這個例子中,我們將產生一個名為“ExtDll”的MFC擴展DLL工程,在這個DLL中導出一個對話框類,這個對話框類派生自MFC類CDialog。

  使用MFC向導生成MFC擴展DLL時,系統會自動添加如下代碼:

static AFX_EXTENSION_MODULE ExtDllDLL = { NULL, NULL };
extern "C" int APIENTRY

DllMain( HINSTANCE hInstance, DWord dwReason, LPVOID lPReserved )
{
 // Remove this if you use lpReserved

 UNREFERENCED_PARAMETER( lpReserved );

 //說明:lpReserved是一個被系統所保留的參數,對于隱式鏈接是一個非零值,對于顯式鏈接值是零

 if (dwReason == DLL_PROCESS_ATTACH)
 {
  TRACE0( "EXTDLL.DLL Initializing!/n" );
  // Extension DLL one-time initialization
  if ( !AfxInitExtensionModule( ExtDllDLL, hInstance ))
   return 0;
   // Insert this DLL into the resource chain
  new CDynLinkLibrary( ExtDllDLL );
 }
 else if (dwReason == DLL_PROCESS_DETACH)
 {
  TRACE0( "EXTDLL.DLL Terminating!/n" );
  // Terminate the library before destrUCtors are called
  AfxTermExtensionModule( ExtDllDLL );
 }
 return 1; // ok
}

  這一段代碼含義晦澀,我們需要對其進行解讀:

  (1)上述代碼完成MFC擴展DLL的初始化和終止處理;

  (2)初始化期間所創建的 CDynLinkLibrary 對象使MFC擴展 DLL 可以將 DLL中的CRuntimeClass 對象或資源導出到應用程序;

 ?。?)AfxInitExtensionModule函數捕捉模塊的CRuntimeClass 結構和在創建 CDynLinkLibrary 對象時使用的對象工廠(COleObjectFactory 對象);

 ?。?)AfxTermExtensionModule函數使 MFC 得以在每個進程與擴展 DLL 分離時(進程退出或使用AfxFreeLibrary卸載DLL時)清除擴展 DLL;

 ?。?)第一條語句static AFX_EXTENSION_MODULE ExtDllDLL = { NULL, NULL };定義了一個AFX_EXTENSION_MODULE類的靜態全局對象,AFX_EXTENSION_MODULE的定義如下:

struct AFX_EXTENSION_MODULE
{
 BOOL bInitialized;
 HMODULE hModule;
 HMODULE hResource;
 CRuntimeClass* pFirstSharedClass;
 COleObjectFactory* pFirstSharedFactory;

};

  由AFX_EXTENSION_MODULE的定義我們可以更好的理解(2)、(3)、(4)點。

  在資源編輯器中添加一個如圖15所示的對話框,并使用MFC類向導為其添加一個對應的類CExtDialog,系統自動添加了ExtDialog.h和ExtDialog.cpp兩個頭文件。

VC++動態鏈接庫編程之MFC擴展 DLL(圖一)
圖15 MFC擴展DLL中的對話框
  修改ExtDialog.h中CExtDialog類的聲明為:

class AFX_EXT_CLASS CExtDialog : public CDialog
{
 public:
  CExtDialog( CWnd* pParent = NULL );
  enum { IDD = IDD_DLL_DIALOG };
 protected:
  virtual void DoDataExchange( CDataExchange* pDX );
  DECLARE_MESSAGE_MAP()
};

  這其中最主要的改變是我們在class AFX_EXT_CLASS CExtDialog語句中添加了“AFX_EXT_CLASS”宏,則使得DLL中的CExtDialog類被導出。
6.3 MFC擴展DLL的加載

  6.3.1 隱式加載

  我們在6.2工程所在的工作區中添加一個LoadExtDllDlg工程,用于演示MFC擴展DLL的加載。在LoadExtDllDlg工程中添加一個如圖16所示的對話框,這個對話框上包括一個“調用DLL”按鈕。

VC++動態鏈接庫編程之MFC擴展 DLL(圖二)
圖16 MFC擴展DLL調用工程中的對話框
  在與圖16對應對話框類實現文件的頭部添加:

// LoadExtDllDlg.cpp : implementation file
//

#include "../ExtDialog.h"
#pragma comment( lib, "ExtDll.lib" )

而“調用DLL”按鈕的單擊事件的消息處理函數為:

void CLoadExtDllDlg::OnDllcallButton()
{
 CExtDialog extDialog;
 extDialog.DoModal();
}

  當我們單擊“調用DLL”的時候,彈出了如圖15的對話框。

  為提供給用戶隱式加載(MFC擴展DLL一般使用隱式加載,具體原因見下節),MFC擴展DLL需要提供三個文件:

 ?。?)描述DLL中擴展類的頭文件;

 ?。?)與動態鏈接庫對應的.LIB文件;

 ?。?)動態鏈接庫.DLL文件本身。

  有了這三個文件,應用程序的開發者才可充分利用MFC擴展DLL。

  6.3.2 顯示加載

  顯示加載MFC擴展DLL應使用MFC全局函數AfxLoadLibrary而不是WIN32 API中的LoadLibrary。AfxLoadLibrary 最終也調用了 LoadLibrary這個API,但是在調用之前進行了線程同步的處理。

  AfxLoadLibrary 的函數原型與 LoadLibrary完全相同,為:

HINSTANCE AFXAPI AfxLoadLibrary( LPCTSTR lpszModuleName );
  與之相對應的是,MFC 應用程序應使用AfxFreeLibrary 而非FreeLibrary 卸載MFC擴展DLL。AfxFreeLibrary的函數原型也與 FreeLibrary完全相同,為:

BOOL AFXAPI AfxFreeLibrary( HINSTANCE hInstLib );
  假如我們把上例中的“調用DLL”按鈕單擊事件的消息處理函數改為:

void CLoadExtDllDlg::OnDllcallButton()
{
 HINSTANCE hDll = AfxLoadLibrary( "ExtDll.dll" );
 if(NULL == hDll)
 {
  AfxMessageBox( "MFC擴展DLL動態加載失敗" );
  return;
 }

 CExtDialog extDialog;
 extDialog.DoModal();
 AfxFreeLibrary(hDll);
}

  則工程會出現link錯誤:

LoadExtDllDlg.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: virtual __thiscall CExtDialog::~CExtDialog(void)" (__imp_??1CExtDialogUAE@XZ)

LoadExtDllDlg.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall CExtDialog::CExtDialog(class CWnd *)" (__imp_??0CExtDialogQAE@PAVCWnd@Z)

  提示CExtDialog的構造函數和析構函數均無法找到!是的,對于派生MFC類的MFC擴展DLL,當我們要在應用程序中使用DLL中定義的派生類時,我們不宜使用動態加載DLL的方法。

  6.4 MFC擴展DLL加載MFC擴展DLL

  我們可以在MFC擴展DLL中再次使用MFC擴展DLL,但是,由于在兩個DLL中對于AFX_EXT_CLASS、AFX_EXT_API、AFX_EXT_DATA宏的定義都是輸出,這會導致調用的時候出現問題。


  我們將會在調用MFC擴展DLL的DLL中看到link錯誤:

error LNK2001: unresolved external symbol ….......
  因此,在調用MFC擴展DLL的MFC擴展DLL中,在包含被調用DLL的頭文件之前,需要臨時重新定義AFX_EXT_CLASS的值。下面的例子顯示了如何實現:

//臨時改變宏的含義“輸出”為“輸入”

#undef AFX_EXT_CLASS
#undef AFX_EXT_API
#undef AFX_EXT_DATA
#define AFX_EXT_CLASS AFX_CLASS_IMPORT
#define AFX_EXT_API AFX_API_IMPORT
#define AFX_EXT_DATA AFX_DATA_IMPORT

//包含被調用MFC擴展DLL的頭文件

#include "CalledDLL.h"

//恢復宏的含義為輸出

#undef AFX_EXT_CLASS
#undef AFX_EXT_API
#undef AFX_EXT_DATA
#define AFX_EXT_CLASS AFX_CLASS_EXPORT
#define AFX_EXT_API AFX_API_EXPORT
#define AFX_EXT_DATA AFX_DATA_EXPORT
 
6.5 MFC擴展DLL導出函數和變量

  MFC擴展DLL導出函數和變量的方法也十分簡單,下面我們給出一個簡單的例子。

  我們在MFC向導生成的MFC擴展DLL工程中添加gobal.h和global.cpp兩個文件:

//global.h:MFC擴展DLL導出變量和函數的聲明

extern "C"
{
 int AFX_EXT_DATA total; //導出變量
 int AFX_EXT_API add( int x, int y ); //導出函數
}

//global.cpp:MFC擴展DLL導出變量和函數定義

#include "StdAfx.h"
#include "global.h"

extern "C" int total;
int add(int x,int y)
{
 total = x + y;
 return total;
}

  編寫一個簡單的控制臺程序來調用這個MFC擴展DLL:

#include
#include 單擊此處下載本工程)。

  我們知道static控件所對應的CStatic類不具備設置背景和文本顏色的接口,這使得我們不能在對話框或其它用戶界面上自由靈活地修改static控件的顏色風格,因此我們需要一個提供了SetBackColor和SetTextColor接口的CStatic派生類CMultiColorStatic。
 
  這個類的聲明如下:

class AFX_EXT_CLASS CMultiColorStatic : public CStatic
{
 // Construction

 public:
  CMultiColorStatic();
  virtual ~CMultiColorStatic();
  // Attributes
 protected:
  CString m_strCaption;
  COLORREF m_BackColor;
  COLORREF m_TextColor;
  // Operations
 public:
  void SetTextColor( COLORREF TextColor );
  void SetBackColor( COLORREF BackColor );
  void SetCaption( CString strCaption );

  // Generated message map functions
 protected:
  afx_msg void OnPaint();
  DECLARE_MESSAGE_MAP()
};

  在這個類的實現文件中,我們需要為它提供WM_PAINT消息的處理函數(這是因為顏色的設置依靠于WM_PAINT消息):

BEGIN_MESSAGE_MAP(CMultiColorStatic, CStatic)

//{{AFX_MSG_MAP(CMultiColorStatic)
 ON_WM_PAINT() //為這個類定義WM_PAINT消息處理函數
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

  下面是這個類中的重要成員函數:

//為CMultiColorStatic類添加“設置文本顏色”接口

void CMultiColorStatic::SetTextColor( COLORREF TextColor )
{
 m_TextColor = TextColor; //設置文字顏色
}

//為CMultiColorStatic類添加“設置背景顏色”接口

void CMultiColorStatic::SetBackColor( COLORREF BackColor )
{
 m_BackColor = BackColor; //設置背景顏色
}

//為CMultiColorStatic類添加“設置標題”接口

void CMultiColorStatic::SetCaption( CString strCaption )
{
 m_strCaption = strCaption;
}

//重畫Static,顏色和標題的設置都依靠于這個函數

void CMultiColorStatic::OnPaint()
{
 CPaintDC dc(this); // device context for painting
 CRect rect;
 GetClientRect( &rect );
 dc.SetBkColor( m_BackColor );

 dc.SetBkMode( TRANSPARENT );
 CFont *pFont = GetParent()->GetFont();//得到父窗體的字體
 CFont *pOldFont;
 pOldFont = dc.SelectObject( pFont );//選用父窗體的字體
 dc.SetTextColor( m_TextColor );//設置文本顏色
 dc.DrawText( m_strCaption, &rect, DT_CENTER );//文本在Static中心
 dc.SelectObject( pOldFont );
}

  為了驗證CMultiColorStatic類,我們制作一個基于對話框的應用程序,它包含一個如圖17所示的對話框。該對話框上包括一個static控件和三個按鈕,這三個按鈕可分別把static控件設置為“紅色”、“藍色”和“綠色”。

VC++動態鏈接庫編程之MFC擴展 DLL(圖三)
圖17 擴展的CStatic類調用演示
  下面看看應如何編寫與這個對話框對應的類。

  包含這種Static的對話框類的聲明如下:

#include "../MultiColorStatic.h"
#pragma comment ( lib, "ColorStatic.lib" )

// CCallDllDlg dialog

class CCallDllDlg : public CDialog
{
 public:
  CCallDllDlg(CWnd* pParent = NULL); // standard constructor
  enum { IDD = IDD_CALLDLL_DIALOG };
  CMultiColorStatic m_colorstatic; //包含一個CMultiColorStatic的實例
 protected:
  virtual void DoDataExchange(CDataExchange* pDX);//DDX/DDV support
  HICON m_hIcon;

 // Generated message map functions
 //{{AFX_MSG(CCallDllDlg)

 virtual BOOL OnInitDialog();
 afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
 afx_msg void OnPaint();
 afx_msg HCURSOR OnQueryDragIcon();
 afx_msg void OnRedButton();
 afx_msg void OnBlueButton();
 afx_msg void OnGreenButton();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};

  下面是這個類中與使用CMultiColorStatic相關的主要成員函數:

void CCallDllDlg::DoDataExchange(CDataExchange* pDX)
{
 CDialog::DoDataExchange(pDX);
 //{{AFX_DATA_MAP(CCallDllDlg)
  DDX_Control(pDX, IDC_COLOR_STATIC, m_colorstatic);
 //使m_colorstatic與IDC_COLOR_STATIC控件關聯
 //}}AFX_DATA_MAP
}

BOOL CCallDllDlg::OnInitDialog()
{
 …
 // TODO: Add extra initialization here

 // 初始static控件的顯示

 m_colorstatic.SetCaption("最開始為黑色");
 m_colorstatic.SetTextColor(RGB(0,0,0));
 return TRUE; // return TRUE unless you set the focus to a control
}

//設置static控件文本顏色為紅色

void CCallDllDlg::OnRedButton()
{
 m_colorstatic.SetCaption( "改變為紅色" );
 m_colorstatic.SetTextColor( RGB( 255, 0, 0 ) );
 Invalidate( TRUE ); //導致發出WM_PAINT消息
}

//設置static控件文本顏色為藍色

void CCallDllDlg::OnBlueButton()
{
 m_colorstatic.SetCaption( "改變為藍色" );
 m_colorstatic.SetTextColor( RGB( 0, 0, 255 ) );
 Invalidate( TRUE ); //導致發出WM_PAINT消息
}

//設置static控件文本顏色為綠色

void CCallDllDlg::OnGreenButton()
{
 m_colorstatic.SetCaption( "改變為綠色" );
 m_colorstatic.SetTextColor( RGB(0,255,0) );
 Invalidate( TRUE ); //導致發出WM_PAINT消息
}

  至此,我們已經講解完成了所有類型的動態鏈接庫,即非MFC DLL、MFC規則DLL和MFC擴展DLL。下一節將給出DLL的三個工程實例,與讀者朋友們共同體會DLL的應用范圍和使用方法。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品爽爽爽爽爽爽在线观看| xvideos成人免费中文版| 久色乳综合思思在线视频| 国产伦精品一区二区三区精品视频| 精品亚洲aⅴ在线观看| 国产激情久久久| 欧美色播在线播放| 日韩电影中文字幕在线观看| 日韩精品免费在线播放| 午夜精品视频在线| 精品久久久久久久久久久久久久| 日韩欧美在线免费| 国产精品专区h在线观看| 红桃视频成人在线观看| 欧美日韩福利电影| 在线色欧美三级视频| 欧美日韩国产精品专区| 日韩精品欧美激情| 神马久久久久久| 国产精品自拍偷拍| 91av视频在线观看| 色偷偷av一区二区三区乱| 亚洲国产另类久久精品| 国产精品视频26uuu| 亚洲欧美在线免费| 一区二区三区回区在观看免费视频| 欧美丰满老妇厨房牲生活| 色综合久久久888| 富二代精品短视频| 欧美激情免费视频| 亚洲欧洲日产国码av系列天堂| 亚洲网站在线播放| 国产精品视频最多的网站| 久久久久久久久久久久av| 亚洲美女www午夜| 久久999免费视频| 欧美成人三级视频网站| 久久人人看视频| 欧洲亚洲妇女av| 91色视频在线观看| 国产伦精品免费视频| 日本久久91av| 日韩欧美有码在线| 高清视频欧美一级| 亚洲欧美激情视频| 欧洲亚洲女同hd| 97超视频免费观看| 福利一区福利二区微拍刺激| 欧美激情乱人伦一区| 国产精品v片在线观看不卡| 色樱桃影院亚洲精品影院| 日本a级片电影一区二区| 欧美日韩国产色| 亚洲第一页自拍| 亚洲午夜精品久久久久久久久久久久| 538国产精品视频一区二区| 精品国产91久久久久久老师| 懂色av影视一区二区三区| 欧美成人性色生活仑片| 最好看的2019年中文视频| 成人乱人伦精品视频在线观看| 亚洲欧洲免费视频| 欧美一级成年大片在线观看| 91久久嫩草影院一区二区| 国产精品一区二区在线| 欧美成人精品一区| 黑人巨大精品欧美一区免费视频| 在线视频免费一区二区| 色综合视频一区中文字幕| 成人av资源在线播放| 91在线看www| 日韩在线视频二区| 伊是香蕉大人久久| 超碰日本道色综合久久综合| 91精品国产高清| 欧美日韩国产综合新一区| 久久国产精彩视频| 奇米四色中文综合久久| 欧美高清视频在线播放| 国产在线视频一区| 欧美在线视频观看免费网站| 欧美性xxxxxx| 国产精品普通话| 亚洲电影av在线| 国产精品你懂得| 欧美极品美女电影一区| 国产精品网站入口| 九九热精品视频| 日韩欧美综合在线视频| 亚洲无线码在线一区观看| 久久视频在线直播| 亚洲一区二区免费在线| 亚洲精品黄网在线观看| 8x拔播拔播x8国产精品| 久久精品99国产精品酒店日本| 成人性教育视频在线观看| 欧美成人免费视频| 日韩欧美在线视频日韩欧美在线视频| 国产精品视频自拍| 国产成人精品a视频一区www| 精品色蜜蜜精品视频在线观看| 亚洲欧美激情另类校园| 亚洲人永久免费| 亚洲最新视频在线| 国产精品99久久99久久久二8| 亚洲精品久久视频| 中日韩美女免费视频网址在线观看| 中文字幕久精品免费视频| 国产精品视频26uuu| 欧美多人爱爱视频网站| 久久av在线看| 色综久久综合桃花网| 91午夜理伦私人影院| 国产精品 欧美在线| 国产成人av网| 精品久久香蕉国产线看观看亚洲| 亚洲欧美制服丝袜| www.欧美精品一二三区| 亚洲国产欧美在线成人app| 精品久久久久人成| 黄色精品在线看| 久久人人爽人人爽人人片av高请| 国产精品久久久999| 欧美午夜激情小视频| 国产有码在线一区二区视频| 丝袜一区二区三区| 亚洲精品一区二三区不卡| 国产91色在线| 久久亚洲成人精品| 国产大片精品免费永久看nba| 久久国产视频网站| 欧美精品精品精品精品免费| 亚洲精品国产综合久久| 国产精品久久久久aaaa九色| 日韩色av导航| 97国产一区二区精品久久呦| 久久亚洲春色中文字幕| 亚洲xxxx18| 久久99精品久久久久久琪琪| 成人久久一区二区| 亚洲a级在线观看| 欧美最猛性xxxx| 91av视频在线免费观看| 日韩中文字幕视频在线| 91精品视频大全| 欧美性猛交99久久久久99按摩| 最近2019中文字幕mv免费看| 亚洲淫片在线视频| 欧美黑人性视频| 欧美麻豆久久久久久中文| 欧美日韩国产999| 奇门遁甲1982国语版免费观看高清| 红桃视频成人在线观看| 96国产粉嫩美女| 欧美精品久久久久久久| 亚洲精品成a人在线观看| 国产精品v片在线观看不卡| 国产精品视频资源| 亚洲国产精品成人va在线观看| 亚洲天堂一区二区三区| 亚洲第一页在线| 国产精品91久久久久久| 国产99久久精品一区二区 夜夜躁日日躁| 精品人伦一区二区三区蜜桃免费|