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

  1. extern "C" int APIENTRY
  2. DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
  3. {
  4. // Remove this if you use lpReserved
  5. UNREFERENCED_PARAMETER(lpReserved);
  6. if (dwReason == DLL_PROCESS_ATTACH)
  7. {
  8.   TRACE0("MFCEXPENDDLL.DLL Initializing! ");
  9.   // Extension DLL one-time initialization
  10.   if (!AfxInitExtensionModule(MfcexpenddllDLL, hInstance))
  11.   return ;
  12.   // Insert this DLL into the resource chain
  13.   // NOTE: If this Extension DLL is being implicitly linked to by
  14.   // an MFC Regular DLL (such as an ActiveX Control)
  15.   // instead of an MFC application, then you will want to
  16.   // remove this line from DllMain and put it in a separate
  17.   // function exported from this Extension DLL. The Regular DLL
  18.   // that uses this Extension DLL should then explicitly call that
  19.   // function to initialize this Extension DLL. Otherwise,
  20.   // the CDynLinkLibrary object will not be attached to the
  21.   // Regular DLL's resource chain, and serious problems will
  22.   // result.
  23.   new CDynLinkLibrary(MfcexpenddllDLL);
  24. }
  25. else if (dwReason == DLL_PROCESS_DETACH)
  26. {
  27.   TRACE0("MFCEXPENDDLL.DLL Terminating! ");
  28.   // Terminate the library before destructors are called
  29.   AfxTermExtensionModule(MfcexpenddllDLL);
  30. }
  31. return ;  // ok
  32. }

  由于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和应用程序中,使用统一的一个宏就可以表示出输出和输入的不同意思:

  1. // for data
  2. #ifndef AFX_DATA_EXPORT
  3. #define AFX_DATA_EXPORT __declspec(dllexport)
  4. #endif
  5. #ifndef AFX_DATA_IMPORT
  6. #define AFX_DATA_IMPORT __declspec(dllimport)
  7. #endif
  8. // for classes
  9. #ifndef AFX_CLASS_EXPORT
  10. #define AFX_CLASS_EXPORT __declspec(dllexport)
  11. #endif
  12. #ifndef AFX_CLASS_IMPORT
  13. #define AFX_CLASS_IMPORT __declspec(dllimport)
  14. #endif
  15. // for global APIs
  16. #ifndef AFX_API_EXPORT
  17. #define AFX_API_EXPORT __declspec(dllexport)
  18. #endif
  19. #ifndef AFX_API_IMPORT
  20. #define AFX_API_IMPORT __declspec(dllimport)
  21. #endif
  22. #ifndef AFX_EXT_DATA
  23. #ifdef _AFXEXT
  24.   #define AFX_EXT_CLASS    AFX_CLASS_EXPORT
  25.   #define AFX_EXT_API     AFX_API_EXPORT
  26.   #define AFX_EXT_DATA    AFX_DATA_EXPORT
  27.   #define AFX_EXT_DATADEF
  28. #else
  29.   #define AFX_EXT_CLASS    AFX_CLASS_IMPORT
  30.   #define AFX_EXT_API     AFX_API_IMPORT
  31.   #define AFX_EXT_DATA    AFX_DATA_IMPORT
  32.   #define AFX_EXT_DATADEF
  33. #endif
  34. #endif

导出一个类,直接在类声明头文件中使用AFX_EXT_CLASS即可,以下是导出CSXButton类的例子:

  1. #ifndef _SXBUTTON_H
  2. #define _SXBUTTON_H
  3. #defineSXBUTTON_CENTER-
  4. class AFX_EXT_CLASS CSXButton : public CButton
  5. {
  6. // Construction
  7. public:
  8. CSXButton();
  9. // Attributes
  10. private:
  11. //Positioning
  12. BOOL m_bUseOffset;  
  13. CPoint m_pointImage;
  14. CPoint m_pointText;
  15. int m_nImageOffsetFromBorder;
  16. int m_nTextOffsetFromImage;
  17. //Image
  18. HICON m_hIcon;  
  19. HBITMAP m_hBitmap;
  20. HBITMAP m_hBitmapDisabled;
  21. int m_nImageWidth, m_nImageHeight;
  22. //Color Tab
  23. char m_bColorTab;  
  24. COLORREFm_crColorTab;
  25. //State
  26. BOOL m_bDefault;
  27. UINT m_nOldAction;
  28. UINT m_nOldState;
  29. // Operations
  30. public:
  31. //Positioning
  32. int SetImageOffset( int nPixels );
  33. int SetTextOffset( int nPixels );
  34. CPointSetImagePos( CPoint p );
  35. CPointSetTextPos( CPoint p );
  36. //Image
  37. BOOLSetIcon( UINT nID, int nWidth, int nHeight );
  38. BOOLSetBitmap( UINT nID, int nWidth, int nHeight );
  39. BOOLSetMaskedBitmap( UINT nID, int nWidth, int nHeight, COLORREF crTransparentMask );
  40. BOOLHasImage() { return (BOOL)( m_hIcon !=  | m_hBitmap != ); }
  41. //Color Tab
  42. voidSetColorTab(COLORREF crTab);
  43. //State
  44. BOOLSetDefaultButton( BOOL bState = TRUE );
  45. private:
  46. BOOLSetBitmapCommon( UINT nID, int nWidth, int nHeight, COLORREF crTransparentMask, BOOL bUseMask );
  47. voidCheckPointForCentering( CPoint &p, int nWidth, int nHeight );
  48. voidRedraw();
  49. // Overrides
  50. // ClassWizard generated virtual function overrides
  51. //{{AFX_VIRTUAL(CSXButton)
  52. public:
  53. virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
  54. //}}AFX_VIRTUAL
  55. // Implementation
  56. public:
  57. virtual ~CSXButton();
  58. // Generated message map functions
  59. protected:
  60. //{{AFX_MSG(CSXButton)
  61. afx_msg LRESULT OnGetText(WPARAM wParam, LPARAM lParam);
  62. //}}AFX_MSG
  63. DECLARE_MESSAGE_MAP()
  64. };
  65. #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. 【转】UGUI文本字体颜色和大小等代码修改

    http://blog.csdn.net/alayeshi/article/details/51842195 由于项目需求用UGUI在同个文本中显示出颜色和大小都不同的文字,我上网找个很久并没有见到相 ...

  2. 【转】Unity摄像机的使用二:摄像机的切换

    http://blog.csdn.net/liujunjie612/article/details/45847877 我们接着上一篇博文继续研究摄像机,这篇我们说下Unity中摄像机的切换,说到切换, ...

  3. linux系统负载状态检查脚本

    为了便于分析问题,编写了一个linux状态检查脚本,脚本可放置任意目录,脚本执行检测后会输出日志记录到当前目录下.直接执行脚本可用于一次检测,可通过日志进行分析.如果需要长时间监测,可执行-x参数,脚 ...

  4. C#中找不到MouseWheel事件的解决办法

    在.....Designer.cs中加入 this.pictureBox1.MouseWheel += new System.Windows.Forms.MouseEventHandler(this. ...

  5. [ZJOI2010][bzoj1834] 网络扩容 [费用流]

    题面 传送门 思路 第一问:无脑网络流跑一波 第二问: 先考虑一个贪心的结论:扩容出来的扩容流量一定要跑满 证明显然 因此我们可以把扩容费用可以换个角度思考,变成增加一点流量,花费W的费用 这样,我们 ...

  6. xctf --Hctf2014 Quals write up

    描述 猫流大大发现一个女神,你能告诉我女神的名字么(名字即是flag) nvshen.zip Solution: Extract the file and we could find a txt wh ...

  7. 刷题总结——Genghis Khan the Conqueror (hdu4126)

    题目: Genghis Khan(成吉思汗)(1162-1227), also known by his birth name Temujin(铁木真) and temple name Taizu(元 ...

  8. inner join和left join 、right join 的区别?

    left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录 right join(右联接) 返回包括右表中的所有记录和左表中联结字段相等的记录inner join(等值连接) 只 ...

  9. C++ Contest Code preprocessor

    大概可以拿来方便拉模板 变量名.语法都是瞎整的你感觉有用随便用好了.. #include<bits/stdc++.h> using namespace std; map<string ...

  10. Treblecross(uva 10561)

    题意:一个 1 × n 的棋盘,有 X 和 :,当棋盘上出现三个连续的X 时游戏结束,两人轮流操作,每次能把一个 : 变成 X,问先手必胜方案数以及先手可以放的位置. /* 对于先手,当有一个'X'时 ...