這是《VC++動态連結庫(DLL)程式設計深入淺出》的第四部分,閱讀本文前,請先閱讀前三部分:(一)、(二)、(三)。
MFC擴充DLL的内涵為MFC的擴充,使用者使用MFC擴充DLL就像使用MFC本身的DLL一樣。除了可以在MFC擴充DLL的内部使用MFC以外,MFC擴充DLL與應用程式的接口部分也可以是MFC。我們一般使用MFC擴充DLL來包含一些MFC的增強功能,譬如擴充MFC的CStatic、CButton等類使之具備更強大的能力。
使用Visual C++向導生産MFC擴充DLL時,MFC向導會自動增加DLL的入口函數DllMain:
<a></a>
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
// Remove this if you use lpReserved
UNREFERENCED_PARAMETER(lpReserved);
if (dwReason == DLL_PROCESS_ATTACH)
TRACE0("MFCEXPENDDLL.DLL Initializing! ");
// Extension DLL one-time initialization
if (!AfxInitExtensionModule(MfcexpenddllDLL, hInstance))
return 0;
// Insert this DLL into the resource chain
// NOTE: If this Extension DLL is being implicitly linked to by
// an MFC Regular DLL (such as an ActiveX Control)
// instead of an MFC application, then you will want to
// remove this line from DllMain and put it in a separate
// function exported from this Extension DLL. The Regular DLL
// that uses this Extension DLL should then explicitly call that
// function to initialize this Extension DLL. Otherwise,
// the CDynLinkLibrary object will not be attached to the
// Regular DLL's resource chain, and serious problems will
// result.
new CDynLinkLibrary(MfcexpenddllDLL);
}
else if (dwReason == DLL_PROCESS_DETACH)
TRACE0("MFCEXPENDDLL.DLL Terminating! ");
// Terminate the library before destructors are called
AfxTermExtensionModule(MfcexpenddllDLL);
return 1; // ok
由于MFC擴充DLL導出函數和變量的方式與其它DLL沒有什麼差別,我們不再細緻講解。下面直接給出一個MFC擴充DLL的建立及在應用程式中調用它的例子。
6.1 MFC擴充DLL的建立
下面我們将在MFC擴充DLL中導出一個按鈕類CSXButton(擴充自MFC的CButton類),類CSXButton是一個用以取代 CButton的類,它使你能在同一個按鈕上顯示位圖和文字,而MFC的按鈕僅可顯示二者之一。類CSXbutton的源代碼在Internet上廣泛流傳,有很好的“群衆基礎”,是以用這個類來講解MFC擴充DLL有其特殊的功效。
MFC中包含一些宏,這些宏在DLL和調用DLL的應用程式中被以不同的方式展開,這使得在DLL和應用程式中,使用統一的一個宏就可以表示出輸出和輸入的不同意思:
// for data
#ifndef AFX_DATA_EXPORT
#define AFX_DATA_EXPORT __declspec(dllexport)
#endif
#ifndef AFX_DATA_IMPORT
#define AFX_DATA_IMPORT __declspec(dllimport)
// for classes
#ifndef AFX_CLASS_EXPORT
#define AFX_CLASS_EXPORT __declspec(dllexport)
#ifndef AFX_CLASS_IMPORT
#define AFX_CLASS_IMPORT __declspec(dllimport)
// for global APIs
#ifndef AFX_API_EXPORT
#define AFX_API_EXPORT __declspec(dllexport)
#ifndef AFX_API_IMPORT
#define AFX_API_IMPORT __declspec(dllimport)
#ifndef AFX_EXT_DATA
#ifdef _AFXEXT
#define AFX_EXT_CLASS AFX_CLASS_EXPORT
#define AFX_EXT_API AFX_API_EXPORT
#define AFX_EXT_DATA AFX_DATA_EXPORT
#define AFX_EXT_DATADEF
#else
#define AFX_EXT_CLASS AFX_CLASS_IMPORT
#define AFX_EXT_API AFX_API_IMPORT
#define AFX_EXT_DATA AFX_DATA_IMPORT
導出一個類,直接在類聲明頭檔案中使用AFX_EXT_CLASS即可,以下是導出CSXButton類的例子:
#ifndef _SXBUTTON_H
#define _SXBUTTON_H
#defineSXBUTTON_CENTER-1
class AFX_EXT_CLASS CSXButton : public CButton
// Construction
public:
CSXButton();
// Attributes
private:
//Positioning
BOOL m_bUseOffset;
CPoint m_pointImage;
CPoint m_pointText;
int m_nImageOffsetFromBorder;
int m_nTextOffsetFromImage;
//Image
HICON m_hIcon;
HBITMAP m_hBitmap;
HBITMAP m_hBitmapDisabled;
int m_nImageWidth, m_nImageHeight;
//Color Tab
char m_bColorTab;
COLORREFm_crColorTab;
//State
BOOL m_bDefault;
UINT m_nOldAction;
UINT m_nOldState;
// Operations
int SetImageOffset( int nPixels );
int SetTextOffset( int nPixels );
CPointSetImagePos( CPoint p );
CPointSetTextPos( CPoint p );
BOOLSetIcon( UINT nID, int nWidth, int nHeight );
BOOLSetBitmap( UINT nID, int nWidth, int nHeight );
BOOLSetMaskedBitmap( UINT nID, int nWidth, int nHeight, COLORREF crTransparentMask );
BOOLHasImage() { return (BOOL)( m_hIcon != 0 | m_hBitmap != 0 ); }
voidSetColorTab(COLORREF crTab);
BOOLSetDefaultButton( BOOL bState = TRUE );
BOOLSetBitmapCommon( UINT nID, int nWidth, int nHeight, COLORREF crTransparentMask, BOOL bUseMask );
voidCheckPointForCentering( CPoint &p, int nWidth, int nHeight );
voidRedraw();
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CSXButton)
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
//}}AFX_VIRTUAL
// Implementation
virtual ~CSXButton();
// Generated message map functions
protected:
//{{AFX_MSG(CSXButton)
afx_msg LRESULT OnGetText(WPARAM wParam, LPARAM lParam);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
把SXBUTTON.CPP檔案直接添加到工程,編譯工程,得到“mfcexpenddll.lib”和“mfcexpenddll.dll”兩個檔案。我們用Visual Studio自帶的Depends工具可以檢視這個.dll,發現其導出了衆多符号(見圖15)。
圖15 導出類時導出的大量符号 (+放大該圖檔)
這些都是類的構造函數、析構函數及其它成員函數和變量經編譯器處理過的符号,我們直接用__declspec(dllexport)語句聲明類就導出了這些符号。
如果我們想用.lib檔案導出這些符号,是非常困難的,我們需要在工程中生成.map檔案,查詢.map檔案的符号,然後将其一一導出。如圖16,打開DLL工程的settings選項,再選擇Link,勾選其中的産生MAP檔案(Generate mapfile)就可以産生.map檔案了。
打開mfcexpenddll工程生成的.map檔案,我們發現其中包含了圖15中所示的符号(symbol)
0001:00000380 ?HasImage@CSXButton@@QAEHXZ 10001380 f i SXBUTTON.OBJ
0001:000003d0 ??0CSXButton@@QAE@XZ 100013d0 f SXBUTTON.OBJ
0001:00000500 ??_GCSXButton@@UAEPAXI@Z 10001500 f i SXBUTTON.OBJ
0001:00000570 ??_ECSXButton@@UAEPAXI@Z 10001570 f i SXBUTTON.OBJ
0001:00000630 ??1CSXButton@@UAE@XZ 10001630 f SXBUTTON.OBJ
0001:00000700 ?_GetBaseMessageMap@CSXButton@@KGPBUAFX_MSGMAP@@XZ 10001700 f SXBUTTON.OBJ
0001:00000730 ?GetMessageMap@CSXButton@@MBEPBUAFX_MSGMAP@@XZ 10001730 f SXBUTTON.OBJ
0001:00000770 ?Redraw@CSXButton@@AAEXXZ 10001770 f i SXBUTTON.OBJ
0001:000007d0 ?SetIcon@CSXButton@@QAEHIHH@Z 100017d0 f SXBUTTON.OBJ
……………………………………………………………………..//省略
本文轉自 不得閑 部落格園部落格,原文連結:http://www.cnblogs.com/DxSoft/archive/2011/04/22/2024844.html ,如需轉載請自行聯系原作者