这是《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 ;
  // 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 ;  // 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-
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 !=  | m_hBitmap != ); }
//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)。

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

  图16 产生.map文件 (+放大该图片)

  所以,对于MFC扩展DLL,我们不宜以.lib文件导出类。

引自:pconline

VC++动态链接库(DLL)编程深入浅出(四)的更多相关文章

  1. VC++动态链接库(DLL)编程深入浅出(zz)

    VC++动态链接库(DLL)编程深入浅出(zz) 1.概论 先来阐述一下DLL(Dynamic Linkable Library)的概念,你可以简单的把DLL看成一种仓库,它提供给你一些可以直接拿来用 ...

  2. VC++动态链接库(DLL)编程深入浅出(转帖:基础班)

    1.概论 先来阐述一下DLL(Dynamic Linkable Library)的概念,你可以简单的把DLL看成一种仓库,它提供给你一些可以直接拿来用的变量.函数或类.在仓库的发展史上经历了“无库-静 ...

  3. VC-基础:VC++动态链接库(DLL)编程深入浅出

    1.概论 先来阐述一下DLL(Dynamic Linkable Library)的概念,你可以简单的把DLL看成一种仓库,它提供给你一些可以直接拿来用的变量.函数或类.在仓库的发展史上经历了“无库-静 ...

  4. VC++动态链接库(DLL)编程深入浅出

    1.概论 先来阐述一下DLL(Dynamic Linkable Library)的概念,你可以简单的把DLL看成一种仓库,它提供给你一些可以直接拿来用的变量.函数或类.在仓库的发展史上经历了“无库-静 ...

  5. VC++动态链接库(DLL)编程深入浅出(一)

    1.概论 先来阐述一下DLL(Dynamic Linkable Library)的概念,你可以简单的把DLL看成一种仓库,它提供给你一些可以直接拿来用的变量.函数或类.在仓库的发展史上经历了“无库-静 ...

  6. VC++动态链接库(DLL)编程深入浅出(二)

    好,让我们正式进入动态链接库的世界,先来看看最一般的DLL,即非MFC DLL 上节给大家介绍了静态链接库与库的调试与查看,本节主要介绍非MFC DLL. 4.非MFC DLL 4.1一个简单的DLL ...

  7. VC++动态链接库(DLL)编程深入浅出(三)

    前面我们对非MFC DLL进行了介绍,这一节将详细地讲述MFC规则DLL的创建与使用技巧. 另外,自从本文开始连载后,收到了一些读者的e-mail.有的读者提出了一些问题,笔者将在本文的最后一次连载中 ...

  8. VC++动态链接库(DLL)编程深入浅出:Q&A(原创)

    Q1:extern “C” 是做什么用的? A1:一种情况是多个文件中,变量声明或者函数声明,需要extern “C”,这种情况在这里不做讨论. 在dll工程中,被extern "C&quo ...

  9. VC++动态链接库(DLL)编程

    一.概论 1:http://www.pconline.com.cn/pcedu/empolder/gj/vc/0509/698632.html 2:http://pcedu.pconline.com. ...

随机推荐

  1. 菜鸟之路——机器学习之KNN算法个人理解及Python实现

    KNN(K Nearest Neighbor) 还是先记几个关键公式 距离:一般用Euclidean distance   E(x,y)√∑(xi-yi)2 .名字这么高大上,就是初中学的两点间的距离 ...

  2. Map 中的EntrySet() ,Map的遍历

      我们循环Map时一般用到EntrySet(),EntrySet() 返回的时Set集合(Set<Map.Entry<K, V>>). 那么这里的有Map.Entry< ...

  3. MFC录制音频和播放音频

    一.录制音频 在windows中提供了相应的API函数(waveIn这个族的函数)实现录音功能:在使用这些函数时,一定要引入相应的头文件 #include <windows.h> #inc ...

  4. ALPHA(四)

    目录 组员情况 组员1(组长):胡绪佩 组员2:胡青元 组员3:庄卉 组员4:家灿 组员5:凯琳 组员6:丹丹 组员7:何家伟 组员8:政演 组员9:鸿杰 组员10:刘一好 组员:何宇恒 展示组内最新 ...

  5. preg_replace_callback 正则替换回调方法用法,

    Example #1 preg_replace_callback() 和 匿名函数 <?php /* 一个unix样式的命令行过滤器,用于将段落开始部分的大写字母转换为小写. */ $fp = ...

  6. 使用xcache加速PHP运行

    XCache 是一个开源的 opcode 缓存器/优化器, 这意味着他能够提高您服务器上的 PHP 性能. 他通过把编译 PHP 后的数据缓冲到共享内存从而避免重复的编译过程, 能够直接使用缓冲区已编 ...

  7. 【APIO 练习题】Lock Puzzle

    题意 你有一个长度为 $n$ 的字符串,你需要经过若干次操作将其变成目标串 $n'$. 一次操作:选择串 $n$ 的一个后缀,将其翻转,并放到串 $n$ 的最前面. 请你输出任意一种方案.当然,你达到 ...

  8. [ARC082F] Sandglass(线段树)

    Description 有一个沙漏由两个上下相通玻璃球 \(A\) 和 \(B\) 构成,这两个玻璃球都含有一定量的沙子,我们暂且假定 \(AB\) 中位于上方的玻璃球的为 \(U\),下方的玻璃球为 ...

  9. 页面get post等查看

    原文发布时间为:2010-03-08 -- 来源于本人的百度文章 [由搬家工具导入] http://www.fiddler2.com/Fiddler2/firstrun.asp

  10. 图片定位 css

    原文发布时间为:2009-07-14 -- 来源于本人的百度文章 [由搬家工具导入] 原图片:http://cache.soso.com/wenwen/i/w_icon.gif 从这图片定位几张图片出 ...