博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
VC++动态链接库(DLL)编程深入浅出(四)(转)
阅读量:6819 次
发布时间:2019-06-26

本文共 5617 字,大约阅读时间需要 18 分钟。

 这是《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:

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)
#endif
//
 for classes
#ifndef AFX_CLASS_EXPORT
#define
 AFX_CLASS_EXPORT __declspec(dllexport)
#endif
#ifndef AFX_CLASS_IMPORT
#define
 AFX_CLASS_IMPORT __declspec(dllimport)
#endif
//
 for global APIs
#ifndef AFX_API_EXPORT
#define
 AFX_API_EXPORT __declspec(dllexport)
#endif
#ifndef AFX_API_IMPORT
#define
 AFX_API_IMPORT __declspec(dllimport)
#endif
#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
 
#define
 AFX_EXT_DATADEF
#endif
#endif

导出一个类,直接在类声明头文件中使用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
public
:
//
Positioning
int
 SetImageOffset( 
int
 nPixels );
int
 SetTextOffset( 
int
 nPixels );
CPointSetImagePos( CPoint p );
CPointSetTextPos( CPoint p );
//
Image
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
 ); }
//
Color Tab
voidSetColorTab(COLORREF crTab);
//
State
BOOLSetDefaultButton( BOOL bState 
=
 TRUE );
private
:
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)
public
:
virtual
 
void
 DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
//
}}AFX_VIRTUAL
//
 Implementation
public
:
virtual
 
~
CSXButton();
//
 Generated message map functions
protected
:
//
{
{AFX_MSG(CSXButton)
afx_msg LRESULT OnGetText(WPARAM wParam, LPARAM lParam);
//
}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
#endif

把SXBUTTON.CPP文件直接添加到工程,编译工程,得到“mfcexpenddll.lib”和“mfcexpenddll.dll”两个文件。我们用Visual Studio自带的Depends工具可以查看这个.dll,发现其导出了众多符号(见图15)。

2011042213463077.gif

 图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
……………………………………………………………………..//省略

1173953311_ddvip_5974.gif

本文转自 不得闲 博客园博客,原文链接:http://www.cnblogs.com/DxSoft/archive/2011/04/22/2024844.html   ,如需转载请自行联系原作者

你可能感兴趣的文章