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:
C++代码
- extern "C" int APIENTRY   
 
- DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)   
 
- {   
 
-    
 
-    UNREFERENCED_PARAMETER(lpReserved);   
 
-   
 
-    if (dwReason == DLL_PROCESS_ATTACH)   
 
-    {   
 
-       TRACE0("MFCEXPENDDLL.DLL Initializing!\n");   
 
-   
 
-       
 
-       if (!AfxInitExtensionModule(MfcexpenddllDLL, hInstance))   
 
-         return 0;   
 
-   
 
-       
 
-       
 
-       
 
-       
 
-       
 
-       
 
-       
 
-       
 
-       
 
-       
 
-       
 
-   
 
-       new CDynLinkLibrary(MfcexpenddllDLL);   
 
-    }   
 
-    else if (dwReason == DLL_PROCESS_DETACH)   
 
-    {   
 
-       TRACE0("MFCEXPENDDLL.DLL Terminating!\n");   
 
-       
 
-       AfxTermExtensionModule(MfcexpenddllDLL);   
 
-    }   
 
-    return 1;   
 
- }  
 
 
       上述代码完成MFC扩展DLL的初始化和终止处理。
  由于MFC扩展DLL导出函数和变量的方式与其它DLL没有什么区别,我们不再细致讲解。下面直接给出一个MFC扩展DLL的创建及在应用程序中调用它的例子。
       1、MFC扩展DLL的创建
  下面我们将在MFC扩展DLL中导出一个按钮类CSXButton(扩展自MFC的CButton类),类CSXButton是一个用以取代 CButton的类,它使你能在同一个按钮上显示位图和文字,而MFC的按钮仅可显示二者之一。类CSXbutton的源代码在Internet上广泛流传,有很好的“群众基础”,因此用这个类来讲解MFC扩展DLL有其特殊的功效。
  MFC中包含一些宏,这些宏在DLL和调用DLL的应用程序中被以不同的方式展开,这使得在DLL和应用程序中,使用统一的一个宏就可以表示出输出和输入的不同意思:
C++代码
- #ifndef AFX_DATA_EXPORT   
 
-  #define AFX_DATA_EXPORT __declspec(dllexport)   
 
- #endif   
 
- #ifndef AFX_DATA_IMPORT   
 
-  #define AFX_DATA_IMPORT __declspec(dllimport)   
 
- #endif   
 
-   
 
- #ifndef AFX_CLASS_EXPORT   
 
-  #define AFX_CLASS_EXPORT __declspec(dllexport)   
 
- #endif   
 
- #ifndef AFX_CLASS_IMPORT   
 
-  #define AFX_CLASS_IMPORT __declspec(dllimport)   
 
- #endif   
 
-   
 
- #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类的例子:
C++代码
- #ifndef _SXBUTTON_H   
 
- #define _SXBUTTON_H   
 
-   
 
- #define SXBUTTON_CENTER -1   
 
-   
 
- class AFX_EXT_CLASS CSXButton : public CButton   
 
- {   
 
- public:   
 
-  CSXButton();   
 
-   
 
- private:   
 
-  
 
-  BOOL  m_bUseOffset;       
 
-  CPoint  m_pointImage;   
 
-  CPoint  m_pointText;   
 
-  int   m_nImageOffsetFromBorder;   
 
-  int   m_nTextOffsetFromImage;   
 
-   
 
-  
 
-  HICON  m_hIcon;        
 
-  HBITMAP  m_hBitmap;   
 
-  HBITMAP  m_hBitmapDisabled;   
 
-  int   m_nImageWidth, m_nImageHeight;   
 
-   
 
-  
 
-  char  m_bColorTab;       
 
-  COLORREF m_crColorTab;   
 
-   
 
-  
 
-  BOOL  m_bDefault;   
 
-  UINT  m_nOldAction;   
 
-  UINT  m_nOldState;   
 
-     
 
- public:   
 
-  
 
-  int  SetImageOffset( int nPixels );    
 
-  int  SetTextOffset( int nPixels );   
 
-  CPoint SetImagePos( CPoint p );   
 
-  CPoint SetTextPos( CPoint p );   
 
-   
 
-  
 
-  BOOL SetIcon( UINT nID, int nWidth, int nHeight );   
 
-  BOOL SetBitmap( UINT nID, int nWidth, int nHeight );   
 
-  BOOL SetMaskedBitmap( UINT nID, int nWidth, int nHeight, COLORREF crTransparentMask );   
 
-  BOOL HasImage() { return (BOOL)( m_hIcon != 0  | m_hBitmap != 0 ); }   
 
-   
 
-  
 
-  void SetColorTab(COLORREF crTab);   
 
-   
 
-  
 
-  BOOL SetDefaultButton( BOOL bState = TRUE );   
 
- private:   
 
-  BOOL SetBitmapCommon( UINT nID, int nWidth, int nHeight, COLORREF crTransparentMask, BOOL bUseMask );   
 
-  void CheckPointForCentering( CPoint &p, int nWidth, int nHeight );   
 
-  void Redraw();   
 
-   
 
-  
 
-  
 
-  public:   
 
-  virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);   
 
-  
 
-   
 
- public:   
 
-  virtual ~CSXButton();   
 
-   
 
-  
 
- protected:   
 
-  
 
-  afx_msg LRESULT OnGetText(WPARAM wParam, LPARAM lParam);   
 
-  
 
-   
 
-  DECLARE_MESSAGE_MAP()   
 
- };   
 
-   
 
- #endif  
 
 
       把SXBUTTON.CPP文件直接添加到工程,编译工程,得到“mfcexpenddll.lib”和“mfcexpenddll.dll”两个文件。我们用Visual Studio自带的Depends工具可以查看这个.dll,发现其导出了众多符号(见图1)。

图1 导出类时导出的大量符号
  这些都是类的构造函数、析构函数及其它成员函数和变量经编译器处理过的符号,我们直接用__declspec(dllexport)语句声明类就导出了这些符号。
  如果我们想用.lib文件导出这些符号,是非常困难的,我们需要在工程中生成.map文件,查询.map文件的符号,然后将其一一导出。如图2,打开DLL工程的settings选项,再选择Link,勾选其中的产生MAP文件(Generate mapfile)就可以产生.map文件了。
  打开mfcexpenddll工程生成的.map文件,我们发现其中包含了图1中所示的符号(symbol)。
C++代码
- 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   
 
- ……………………………………………………………………..
 
 

图2 产生.map文件
  所以,对于MFC扩展DLL,我们不宜以.lib文件导出类。
       2、MFC扩展DLL的调用
  在DLL所在工作区新增一个dllcall工程,它是一个基于对话框的MFC EXE程序。在其中增加两个按钮SXBUTTON1、SXBUTTON2,并设置其属性为“Owner draw”,如图3。

图3 设置按钮属性为“Owner draw”
       在工程中添加两个ICON资源:IDI_MSN_ICON(MSN的图标)、IDI_REFBAR_ICON(Windows的系统图标)。
  修改工程的“calldllDlg.h”头文件为:
C++代码
- #include "..\..\mfcexpenddll\SXBUTTON.h"  //包含dll的导出类头文件   
 
- #pragma comment(lib,"mfcexpenddll.lib")    //隐式链接dll   
 
-   
 
- class CCalldllDlg : public CDialog   
 
- {   
 
- public:   
 
-  CCalldllDlg(CWnd* pParent = NULL); 
 
-   
 
-  
 
-  enum { IDD = IDD_CALLDLL_DIALOG };   
 
-  CSXButton m_button1;      
 
-  CSXButton m_button2;   
 
- …   
 
- }  
 
 
       同时,修改“calldllDlg.cpp”文件,使得m_button1、m_button2成员变量与对话框上的按钮控件建立关联:
C++代码
- void CCalldllDlg::DoDataExchange(CDataExchange* pDX)   
 
- {   
 
-  CDialog::DoDataExchange(pDX);   
 
-  
 
-  DDX_Control(pDX, IDC_BUTTON2, m_button2);   
 
-  DDX_Control(pDX, IDC_BUTTON1, m_button1);   
 
-  
 
- }  
 
 
       修改BOOL CCalldllDlg::OnInitDialog()函数,在其中增加对两个按钮设置ICON的代码:
C++代码
- BOOL CCalldllDlg::OnInitDialog()   
 
- {   
 
-  CDialog::OnInitDialog();   
 
-   
 
-  
 
-   
 
-  
 
-  ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);   
 
-  ASSERT(IDM_ABOUTBOX < 0xF000);   
 
-   
 
-  CMenu* pSysMenu = GetSystemMenu(FALSE);   
 
-  if (pSysMenu != NULL)   
 
-  {   
 
-   CString strAboutMenu;   
 
-   strAboutMenu.LoadString(IDS_ABOUTBOX);   
 
-   if (!strAboutMenu.IsEmpty())   
 
-   {   
 
-    pSysMenu->AppendMenu(MF_SEPARATOR);   
 
-    pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);   
 
-   }   
 
-  }   
 
-   
 
-  
 
-  
 
-  SetIcon(m_hIcon, TRUE);   
 
-  SetIcon(m_hIcon, FALSE);  
 
-   
 
-  
 
-  m_button1.SetIcon(IDI_MSN_ICON,16,16);   
 
-  m_button2.SetIcon(IDI_REFBAR_ICON,16,16);   
 
-   
 
-  return TRUE;  
 
- }  
 
 
       运行程序,将出现如图4的对话框,图形和文字同时出现在按钮上,这说明我们正确地调用了MFC扩展DLL。

图4 DLL扩展的按钮被显示
  如果我们不修改void CCalldllDlg::DoDataExchange(CDataExchange* pDX),即不增加下列代码:
C++代码
- DDX_Control(pDX, IDC_BUTTON2,  m_button2);   
 
- DDX_Control(pDX, IDC_BUTTON1,  m_button1);  
 
 
       我们也可以在BOOL CCalldllDlg::OnInitDialog()函数中添加如下代码实现m_button1、m_button2与IDC_BUTTON1、IDC_BUTTON2的关联:
C++代码
- m_button1.SubclassDlgItem(IDC_BUTTON1, this);   
 
- m_button2.SubclassDlgItem(IDC_BUTTON2, this);  
 
 
  但是,DDX_Control与按钮类的SubclassDlgItem成员函数不能同时存在,否则程序会出错。
       3、总结
  由以上分析可知,MFC扩展DLL的导出与引用方式与前几节所讲述的方式没有太大的差别,MFC扩展DLL主要强调对MFC进行功能扩展。因此,如果DLL的目标不是增强MFC的功能,其与应用程序的接口也不是MFC,请不要将DLL建立为MFC扩展DLL。
 
原文地址:http://www.jizhuomi.com/software/301.html
(转载)DLL动态链接库编程入门之五:MFC扩展DLL
原文:http://www.cnblogs.com/wodehao0808/p/6759095.html