久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

VC++動態(tài)鏈接庫編程之MFC擴(kuò)展DLL

 king9413 2010-05-02

前文我們對非MFC DLL和MFC規(guī)則DLL進(jìn)行了介紹,現(xiàn)在開始詳細(xì)分析DLL的最后一種類型――MFC擴(kuò)展DLL,。

6.1概論

MFC擴(kuò)展DLL與MFC規(guī)則DLL的相同點在于在兩種DLL的內(nèi)部都可以使用MFC類庫,,其不同點在于MFC擴(kuò)展DLL與應(yīng)用程序的接口可以是MFC的。MFC擴(kuò)展DLL的含義在于它是MFC的擴(kuò)展,,其主要功能是實現(xiàn)從現(xiàn)有MFC庫類中派生出可重用的類,。MFC擴(kuò)展DLL使用MFC 動態(tài)鏈接庫版本,因此只有用共享MFC 版本生成的MFC 可執(zhí)行文件(應(yīng)用程序或規(guī)則DLL)才能使用MFC擴(kuò)展DLL,。

從前文可知,,MFC規(guī)則DLL被MFC向?qū)ё詣犹砑恿艘粋€CWinApp的對象,而MFC擴(kuò)展DLL則不包含該對象,,它只是被自動添加了DllMain 函數(shù),。對于MFC擴(kuò)展DLL,開發(fā)人員必須在DLL的DllMain函數(shù)中添加初始化和結(jié)束代碼,。

從下表我們可以看出三種DLL對DllMain入口函數(shù)的不同處理方式:

DLL類型 入口函數(shù)
非 MFC DLL 編程者提供DllMain函數(shù)
MFC規(guī)則 DLL CWinApp對象的InitInstance 和 ExitInstance
MFC擴(kuò)展 DLL MFC DLL向?qū)蒁llMain 函數(shù)

對于MFC擴(kuò)展DLL,,系統(tǒng)會自動在工程中添加如下表所示的宏,這些宏為DLL和應(yīng)用程序的編寫提供了方便,。像AFX_EXT_CLASS,、AFX_EXT_API、AFX_EXT_DATA這樣的宏,,在DLL和應(yīng)用程序中將具有不同的定義,,這取決于_AFXEXT宏是否被定義。這使得在DLL和應(yīng)用程序中,,使用統(tǒng)一的一個宏就可以表示出輸出和輸入的不同意思,。在DLL中,表示輸出(因為_AFXEXT被定義,,通常是在編譯器的標(biāo)識參數(shù)中指定/D_AFXEXT),;在應(yīng)用程序中,則表示輸入(_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擴(kuò)展DLL導(dǎo)出MFC派生類

在這個例子中,,我們將產(chǎn)生一個名為“ExtDll”的MFC擴(kuò)展DLL工程,在這個DLL中導(dǎo)出一個對話框類,,這個對話框類派生自MFC類CDialog。

使用MFC向?qū)蒑FC擴(kuò)展DLL時,,系統(tǒng)會自動添加如下代碼:

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是一個被系統(tǒng)所保留的參數(shù),,對于隱式鏈接是一個非零值,對于顯式鏈接值是零

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

}

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

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

(2)初始化期間所創(chuàng)建的 CDynLinkLibrary 對象使MFC擴(kuò)展 DLL 可以將 DLL中的CRuntimeClass 對象或資源導(dǎo)出到應(yīng)用程序,;

(3)AfxInitExtensionModule函數(shù)捕獲模塊的CRuntimeClass 結(jié)構(gòu)和在創(chuàng)建 CDynLinkLibrary 對象時使用的對象工廠(COleObjectFactory 對象);

(4)AfxTermExtensionModule函數(shù)使 MFC 得以在每個進(jìn)程與擴(kuò)展 DLL 分離時(進(jìn)程退出或使用AfxFreeLibrary卸載DLL時)清除擴(kuò)展 DLL,;

(5)第一條語句static AFX_EXTENSION_MODULE ExtDllDLL = { NULL, NULL };定義了一個AFX_EXTENSION_MODULE類的靜態(tài)全局對象,,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類向?qū)槠涮砑右粋€對應(yīng)的類CExtDialog,,系統(tǒng)自動添加了ExtDialog.h和ExtDialog.cpp兩個頭文件,。

 

圖15 MFC擴(kuò)展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類被導(dǎo)出,。
 
6.3 MFC擴(kuò)展DLL的加載

 

6.3.1 隱式加載

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

 

圖16 MFC擴(kuò)展DLL調(diào)用工程中的對話框

在與圖16對應(yīng)對話框類實現(xiàn)文件的頭部添加:

// LoadExtDllDlg.cpp : implementation file

//

#include "..\ExtDialog.h"

#pragma comment( lib, "ExtDll.lib" )

而“調(diào)用DLL”按鈕的單擊事件的消息處理函數(shù)為:

void CLoadExtDllDlg::OnDllcallButton()

{

CExtDialog extDialog;

extDialog.DoModal();

}

當(dāng)我們單擊“調(diào)用DLL”的時候,彈出了如圖15的對話框,。

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

(1)描述DLL中擴(kuò)展類的頭文件,;

(2)與動態(tài)鏈接庫對應(yīng)的.LIB文件,;

(3)動態(tài)鏈接庫.DLL文件本身。

有了這三個文件,,應(yīng)用程序的開發(fā)者才可充分利用MFC擴(kuò)展DLL,。

6.3.2 顯示加載

顯示加載MFC擴(kuò)展DLL應(yīng)使用MFC全局函數(shù)AfxLoadLibrary而不是WIN32 API中的LoadLibrary。AfxLoadLibrary 最終也調(diào)用了 LoadLibrary這個API,,但是在調(diào)用之前進(jìn)行了線程同步的處理,。

AfxLoadLibrary 的函數(shù)原型與 LoadLibrary完全相同,為:

HINSTANCE AFXAPI AfxLoadLibrary( LPCTSTR lpszModuleName );

與之相對應(yīng)的是,,MFC 應(yīng)用程序應(yīng)使用AfxFreeLibrary 而非FreeLibrary 卸載MFC擴(kuò)展DLL,。AfxFreeLibrary的函數(shù)原型也與 FreeLibrary完全相同,為:

BOOL AFXAPI AfxFreeLibrary( HINSTANCE hInstLib );

如果我們把上例中的“調(diào)用DLL”按鈕單擊事件的消息處理函數(shù)改為:

void CLoadExtDllDlg::OnDllcallButton()

{

HINSTANCE hDll = AfxLoadLibrary( "ExtDll.dll" );

if(NULL == hDll)

{

AfxMessageBox( "MFC擴(kuò)展DLL動態(tài)加載失敗" );

return;

}

CExtDialog extDialog;

extDialog.DoModal();

AfxFreeLibrary(hDll);

}

則工程會出現(xiàn)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的構(gòu)造函數(shù)和析構(gòu)函數(shù)均無法找到,!是的,,對于派生MFC類的MFC擴(kuò)展DLL,當(dāng)我們要在應(yīng)用程序中使用DLL中定義的派生類時,,我們不宜使用動態(tài)加載DLL的方法,。

6.4 MFC擴(kuò)展DLL加載MFC擴(kuò)展DLL

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

我們將會在調(diào)用MFC擴(kuò)展DLL的DLL中看到link錯誤:

error LNK2001: unresolved external symbol ….......

因此,,在調(diào)用MFC擴(kuò)展DLL的MFC擴(kuò)展DLL中,在包含被調(diào)用DLL的頭文件之前,,需要臨時重新定義AFX_EXT_CLASS的值,。下面的例子顯示了如何實現(xiàn):

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

#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

//包含被調(diào)用MFC擴(kuò)展DLL的頭文件

#include "CalledDLL.h"

//恢復(fù)宏的含義為輸出

#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擴(kuò)展DLL導(dǎo)出函數(shù)和變量

 

MFC擴(kuò)展DLL導(dǎo)出函數(shù)和變量的方法也十分簡單,下面我們給出一個簡單的例子,。

我們在MFC向?qū)傻腗FC擴(kuò)展DLL工程中添加gobal.h和global.cpp兩個文件:

//global.h:MFC擴(kuò)展DLL導(dǎo)出變量和函數(shù)的聲明

extern "C"

{

int AFX_EXT_DATA total; //導(dǎo)出變量

int AFX_EXT_API add( int x, int y ); //導(dǎo)出函數(shù)

}

//global.cpp:MFC擴(kuò)展DLL導(dǎo)出變量和函數(shù)定義

#include "StdAfx.h"

#include "global.h"

extern "C" int total;

int add(int x,int y)

{

total = x + y;

return total;

}

編寫一個簡單的控制臺程序來調(diào)用這個MFC擴(kuò)展DLL:

#include <iostream.h>

#include <afxver_.h>

//AFX_EXT_DATA,、AFX_EXT_API宏的定義在afxver_.h頭文件中

#pragma comment ( lib, "ExtDll.lib" )

#include "..\global.h"

int main(int argc, char* argv[])

{

cout << add(2,3) << endl;

cout << total;

return 0;

}

運行程序,在控制臺上看到:

5

5

另外,,在Visual C++下建立MFC擴(kuò)展DLL時,,MFC DLL向?qū)詣由?def文件。因此,,對于函數(shù)和變量,,我們除了可以利用AFX_EXT_DATA、AFX_EXT_API宏導(dǎo)出以外,,在.def文件中定義導(dǎo)出也是一個很好的辦法,。與之相比,在.def文件中導(dǎo)出類卻較麻煩,。通常需要從工程生成的.map文件中獲得類的所有成員函數(shù)被C++編譯器更改過的標(biāo)識符,,并且在.def文件中導(dǎo)出這些“奇怪”的標(biāo)識符。因此,,MFC擴(kuò)展DLL通常以AFX_EXT_CLASS宏直接聲明導(dǎo)出類,。

6.6 MFC擴(kuò)展DLL的應(yīng)用

上述各小節(jié)所舉MFC擴(kuò)展DLL的例子均只是為了說明某方面的問題,沒有真實地體現(xiàn)“MFC擴(kuò)展” 的內(nèi)涵,,譬如6.2派生自CDialog的類也不具備比CDialog更強(qiáng)的功能,。MFC擴(kuò)展DLL的真實內(nèi)涵體現(xiàn)在它提供的類雖然派生自MFC類,但是提供了比MFC類更強(qiáng)大的功能,、更豐富的接口,。下面我們來看一個具體的例子(單擊此處下載本工程)。

我們知道static控件所對應(yīng)的CStatic類不具備設(shè)置背景和文本顏色的接口,,這使得我們不能在對話框或其它用戶界面上自由靈活地修改static控件的顏色風(fēng)格,,因此我們需要一個提供了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()

};

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

BEGIN_MESSAGE_MAP(CMultiColorStatic, CStatic)

//{{AFX_MSG_MAP(CMultiColorStatic)

ON_WM_PAINT() //為這個類定義WM_PAINT消息處理函數(shù)

//}}AFX_MSG_MAP

END_MESSAGE_MAP()

下面是這個類中的重要成員函數(shù):

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

void CMultiColorStatic::SetTextColor( COLORREF TextColor )

{

m_TextColor = TextColor; //設(shè)置文字顏色

}

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

void CMultiColorStatic::SetBackColor( COLORREF BackColor )

{

m_BackColor = BackColor; //設(shè)置背景顏色

}

//為CMultiColorStatic類添加“設(shè)置標(biāo)題”接口

void CMultiColorStatic::SetCaption( CString strCaption )

{

m_strCaption = strCaption;

}

//重畫Static,,顏色和標(biāo)題的設(shè)置都依賴于這個函數(shù)

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 );//設(shè)置文本顏色

dc.DrawText( m_strCaption, &rect, DT_CENTER );//文本在Static中央

dc.SelectObject( pOldFont );

}

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

 

圖17 擴(kuò)展的CStatic類調(diào)用演示

下面看看應(yīng)如何編寫與這個對話框?qū)?yīng)的類。

包含這種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相關(guān)的主要成員函數(shù):

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控件關(guān)聯(lián)

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

}

//設(shè)置static控件文本顏色為紅色

void CCallDllDlg::OnRedButton()

{

m_colorstatic.SetCaption( "改變?yōu)榧t色" );

m_colorstatic.SetTextColor( RGB( 255, 0, 0 ) );

Invalidate( TRUE ); //導(dǎo)致發(fā)出WM_PAINT消息

}

//設(shè)置static控件文本顏色為藍(lán)色

void CCallDllDlg::OnBlueButton()

{

m_colorstatic.SetCaption( "改變?yōu)樗{(lán)色" );

m_colorstatic.SetTextColor( RGB( 0, 0, 255 ) );

Invalidate( TRUE ); //導(dǎo)致發(fā)出WM_PAINT消息

}

//設(shè)置static控件文本顏色為綠色

void CCallDllDlg::OnGreenButton()

{

m_colorstatic.SetCaption( "改變?yōu)榫G色" );

m_colorstatic.SetTextColor( RGB(0,255,0) );

Invalidate( TRUE ); //導(dǎo)致發(fā)出WM_PAINT消息

}

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

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多