⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vc++动态链接库(dll)编程深入浅出(四).htm

📁 VC++动态链接库编程之基础慨念-与编程讲解深入浅出 对原理不清的同学有一定的帮助
💻 HTM
📖 第 1 页 / 共 4 页
字号:
            href="http://www.study888.com/User/User_Favorite.asp?Action=Add&ChannelID=25&InfoID=125868" 
            target=_blank>加入收藏</A>】【<A 
            href="http://www.study888.com/computer/SendMail.asp?ArticleID=125868" 
            target=_blank>告诉好友</A>】【<A 
            href="http://www.study888.com/computer/Print.asp?ArticleID=125868" 
            target=_blank>打印此文</A>】【<A 
            href="javascript:window.close();">关闭窗口</A>】 </TD></TR><!--文章标题下部广告代码开始-->
        <TR>
          <TD align=middle colSpan=2>
            <SCRIPT src=""></SCRIPT>
          </TD></TR><!--文章标题下部广告代码结束-->
        <TR>
          <TD background=VC++动态链接库(DLL)编程深入浅出(四).files/ad_bx1.gif colSpan=2 
          height=6></TD></TR>
        <TR>
          <TD colSpan=6></TD></TR>
        <TR>
          <TD id=fontzoom style="WORD-BREAK: break-all" vAlign=top colSpan=2 
          height=600>
            <SCRIPT src="VC++动态链接库(DLL)编程深入浅出(四).files/wen-ad-300.js"></SCRIPT>
            MFC扩展DLL的内涵为MFC的扩展,用户使用MFC扩展DLL就像使用MFC本身的DLL一样。除了可以在MFC扩展DLL的内部使用MFC以外,MFC扩展DLL与应用程序的接口部分也可以是MFC。我们一般使用MFC扩展DLL来包含一些MFC的增强功能,譬如扩展MFC的CStatic、CButton等类使之具备更强大的能力。 

            <P>  使用Visual C++向导生产MFC扩展DLL时,MFC向导会自动增加DLL的入口函数DllMain:</P>
            <P class=code clear=both>extern "C" int 
            APIENTRY<BR>DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID 
            lpReserved)<BR>{<BR>&nbsp;// Remove this if you use 
            lpReserved<BR>&nbsp;UNREFERENCED_PARAMETER(lpReserved);<BR><BR>&nbsp;if 
            (dwReason == 
            DLL_PROCESS_ATTACH)<BR>&nbsp;{<BR>&nbsp;&nbsp;TRACE0("MFCEXPENDDLL.DLL 
            Initializing!\n");<BR><BR>&nbsp;&nbsp;// Extension DLL one-time 
            initialization<BR>&nbsp;&nbsp;if 
            (!AfxInitExtensionModule(MfcexpenddllDLL, 
            hInstance))<BR>&nbsp;&nbsp;&nbsp;return 0;<BR><BR>&nbsp;&nbsp;// 
            Insert this DLL into the resource chain<BR>&nbsp;&nbsp;// NOTE: If 
            this Extension DLL is being implicitly linked to 
            by<BR>&nbsp;&nbsp;//&nbsp; an MFC Regular DLL (such as an ActiveX 
            Control)<BR>&nbsp;&nbsp;//&nbsp; instead of an MFC application, then 
            you will want to<BR>&nbsp;&nbsp;//&nbsp; remove this line from 
            DllMain and put it in a separate<BR>&nbsp;&nbsp;//&nbsp; function 
            exported from this Extension DLL.&nbsp; The Regular 
            DLL<BR>&nbsp;&nbsp;//&nbsp; that uses this Extension DLL should then 
            explicitly call that<BR>&nbsp;&nbsp;//&nbsp; function to initialize 
            this Extension DLL.&nbsp; Otherwise,<BR>&nbsp;&nbsp;//&nbsp; the 
            CDynLinkLibrary object will not be attached to 
            the<BR>&nbsp;&nbsp;//&nbsp; Regular DLL's resource chain, and 
            serious problems will<BR>&nbsp;&nbsp;//&nbsp; 
            result.<BR><BR>&nbsp;&nbsp;new 
            CDynLinkLibrary(MfcexpenddllDLL);<BR>&nbsp;}<BR>&nbsp;else if 
            (dwReason == 
            DLL_PROCESS_DETACH)<BR>&nbsp;{<BR>&nbsp;&nbsp;TRACE0("MFCEXPENDDLL.DLL 
            Terminating!\n");<BR>&nbsp;&nbsp;// Terminate the library before 
            destructors are 
            called<BR>&nbsp;&nbsp;AfxTermExtensionModule(MfcexpenddllDLL);<BR>&nbsp;}<BR>&nbsp;return 
            1;&nbsp;&nbsp; // ok<BR>}</P>
            <P>  上述代码完成MFC扩展DLL的初始化和终止处理。</P>
            <P>  由于MFC扩展DLL导出函数和变量的方式与其它DLL没有什么区别,我们不再细致讲解。下面直接给出一个MFC扩展DLL的创建及在应用程序中调用它的例子。</P>
            <P>
            <TABLE cellSpacing=0 cellPadding=6 width="100%" border=0>
              <TBODY>
              <TR>
                <TD>
                  <P align=left><STRONG>6.1 MFC扩展DLL的创建</STRONG></P>
                  <P>  下面我们将在MFC扩展DLL中导出一个按钮类CSXButton(扩展自MFC的CButton类),类CSXButton是一个用以取代 
                  CButton的类,它使你能在同一个按钮上显示位图和文字,而MFC的按钮仅可显示二者之一。类CSXbutton的源代码在Internet上广泛流传,有很好的“群众基础”,因此用这个类来讲解MFC扩展DLL有其特殊的功效。</P>
                  <P>  MFC中包含一些宏,这些宏在DLL和调用DLL的应用程序中被以不同的方式展开,这使得在DLL和应用程序中,使用统一的一个宏就可以表示出输出和输入的不同意思:</P>
                  <P class=code>// for data<BR>#ifndef 
                  AFX_DATA_EXPORT<BR>&nbsp;#define AFX_DATA_EXPORT 
                  __declspec(dllexport)<BR>#endif<BR>#ifndef 
                  AFX_DATA_IMPORT<BR>&nbsp;#define AFX_DATA_IMPORT 
                  __declspec(dllimport)<BR>#endif<BR><BR>// for 
                  classes<BR>#ifndef AFX_CLASS_EXPORT<BR>&nbsp;#define 
                  AFX_CLASS_EXPORT __declspec(dllexport)<BR>#endif<BR>#ifndef 
                  AFX_CLASS_IMPORT<BR>&nbsp;#define AFX_CLASS_IMPORT 
                  __declspec(dllimport)<BR>#endif<BR><BR>// for global 
                  APIs<BR>#ifndef AFX_API_EXPORT<BR>&nbsp;#define AFX_API_EXPORT 
                  __declspec(dllexport)<BR>#endif<BR>#ifndef 
                  AFX_API_IMPORT<BR>&nbsp;#define AFX_API_IMPORT 
                  __declspec(dllimport)<BR>#endif<BR><BR>#ifndef 
                  AFX_EXT_DATA<BR>&nbsp;#ifdef _AFXEXT<BR>&nbsp;&nbsp;#define 
                  AFX_EXT_CLASS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
                  AFX_CLASS_EXPORT<BR>&nbsp;&nbsp;#define 
                  AFX_EXT_API&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
                  AFX_API_EXPORT<BR>&nbsp;&nbsp;#define 
                  AFX_EXT_DATA&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
                  AFX_DATA_EXPORT<BR>&nbsp;&nbsp;#define 
                  AFX_EXT_DATADEF<BR>&nbsp;#else<BR>&nbsp;&nbsp;#define 
                  AFX_EXT_CLASS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
                  AFX_CLASS_IMPORT<BR>&nbsp;&nbsp;#define 
                  AFX_EXT_API&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
                  AFX_API_IMPORT<BR>&nbsp;&nbsp;#define 
                  AFX_EXT_DATA&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
                  AFX_DATA_IMPORT<BR>&nbsp;&nbsp;#define 
                  AFX_EXT_DATADEF<BR>&nbsp;#endif<BR>#endif</P>
                  <P>  导出一个类,直接在类声明头文件中使用AFX_EXT_CLASS即可,以下是导出CSXButton类的例子:</P>
                  <P class=code>#ifndef _SXBUTTON_H<BR>#define 
                  _SXBUTTON_H<BR><BR>#define&nbsp;SXBUTTON_CENTER&nbsp;-1<BR><BR>class 
                  AFX_EXT_CLASS CSXButton : public CButton<BR>{<BR>// 
                  Construction<BR>public:<BR>&nbsp;CSXButton();<BR><BR>// 
                  Attributes<BR>private:<BR>&nbsp;//&nbsp;Positioning<BR>&nbsp;BOOL&nbsp;&nbsp;m_bUseOffset;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;CPoint&nbsp;&nbsp;m_pointImage;<BR>&nbsp;CPoint&nbsp;&nbsp;m_pointText;<BR>&nbsp;int&nbsp;&nbsp;&nbsp;m_nImageOffsetFromBorder;<BR>&nbsp;int&nbsp;&nbsp;&nbsp;m_nTextOffsetFromImage;<BR><BR>&nbsp;//&nbsp;Image<BR>&nbsp;HICON&nbsp;&nbsp;m_hIcon;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;HBITMAP&nbsp;&nbsp;m_hBitmap;<BR>&nbsp;HBITMAP&nbsp;&nbsp;m_hBitmapDisabled;<BR>&nbsp;int&nbsp;&nbsp;&nbsp;m_nImageWidth, 
                  m_nImageHeight;<BR><BR>&nbsp;//&nbsp;Color 
                  Tab<BR>&nbsp;char&nbsp;&nbsp;m_bColorTab;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;COLORREF&nbsp;m_crColorTab;<BR><BR>&nbsp;//&nbsp;State<BR>&nbsp;BOOL&nbsp;&nbsp;m_bDefault;<BR>&nbsp;UINT&nbsp;&nbsp;m_nOldAction;<BR>&nbsp;UINT&nbsp;&nbsp;m_nOldState;<BR>&nbsp;<BR>// 
                  Operations<BR>public:<BR>&nbsp;//&nbsp;Positioning<BR>&nbsp;int&nbsp;&nbsp;SetImageOffset( 
                  int nPixels ); <BR>&nbsp;int&nbsp;&nbsp;SetTextOffset( int 
                  nPixels );<BR>&nbsp;CPoint&nbsp;SetImagePos( CPoint p 
                  );<BR>&nbsp;CPoint&nbsp;SetTextPos( CPoint p 
                  );<BR><BR>&nbsp;//&nbsp;Image<BR>&nbsp;BOOL&nbsp;SetIcon( UINT 
                  nID, int nWidth, int nHeight );<BR>&nbsp;BOOL&nbsp;SetBitmap( 
                  UINT nID, int nWidth, int nHeight 
                  );<BR>&nbsp;BOOL&nbsp;SetMaskedBitmap( UINT nID, int nWidth, 
                  int nHeight, COLORREF crTransparentMask 
                  );<BR>&nbsp;BOOL&nbsp;HasImage() { return (BOOL)( m_hIcon != 
                  0&nbsp; | m_hBitmap != 0 ); }<BR><BR>&nbsp;//&nbsp;Color 
                  Tab<BR>&nbsp;void&nbsp;SetColorTab(COLORREF 
                  crTab);<BR><BR>&nbsp;//&nbsp;State<BR>&nbsp;BOOL&nbsp;SetDefaultButton( 
                  BOOL bState = TRUE 
                  );<BR>private:<BR>&nbsp;BOOL&nbsp;SetBitmapCommon( UINT nID, 
                  int nWidth, int nHeight, COLORREF crTransparentMask, BOOL 
                  bUseMask );<BR>&nbsp;void&nbsp;CheckPointForCentering( CPoint 
                  &amp;p, int nWidth, int nHeight 
                  );<BR>&nbsp;void&nbsp;Redraw();<BR><BR>// 
                  Overrides<BR>&nbsp;// ClassWizard generated virtual function 
                  overrides<BR>&nbsp;//{{AFX_VIRTUAL(CSXButton)<BR>&nbsp;public:<BR>&nbsp;virtual 
                  void DrawItem(LPDRAWITEMSTRUCT 
                  lpDrawItemStruct);<BR>&nbsp;//}}AFX_VIRTUAL<BR><BR>// 
                  Implementation<BR>public:<BR>&nbsp;virtual 
                  ~CSXButton();<BR><BR>&nbsp;// Generated message map 
                  functions<BR>protected:<BR>&nbsp;//{{AFX_MSG(CSXButton)<BR>&nbsp;afx_msg 
                  LRESULT OnGetText(WPARAM wParam, LPARAM 
                  lParam);<BR>&nbsp;//}}AFX_MSG<BR><BR>&nbsp;DECLARE_MESSAGE_MAP()<BR>};<BR><BR>#endif</P>
                  <P>  把SXBUTTON.CPP文件直接添加到工程,编译工程,得到“mfcexpenddll.lib”和“mfcexpenddll.dll”两个文件。我们用Visual 
                  Studio自带的Depends工具可以查看这个.dll,发现其导出了众多符号(见图15)。</P>
                  <P align=center><IMG alt="" 
                  src="VC++动态链接库(DLL)编程深入浅出(四).files/20051121084533447.gif" 
                  border=0><BR>&nbsp;<BR><FONT color=#888888>图15 导出类时导出的大量符号 
                  (+<A 
                  href="http://www.study888.com/computer/UploadFiles/200511/20051121084537189.gif&amp;namecode=pcedu&amp;subnamecode=pcedu_index" 
                  target=_blank><FONT color=#3366cc>放大该图片</FONT></A>)</FONT></P>
                  <P>  这些都是类的构造函数、析构函数及其它成员函数和变量经编译器处理过的符号,我们直接用__declspec(dllexport)语句声明类就导出了这些符号。</P>
                  <P>  如果我们想用.lib文件导出这些符号,是非常困难的,我们需要在工程中生成.map文件,查询.map文件的符号,然后将其一一导出。如图16,打开DLL工程的settings选项,再选择Link,勾选其中的产生MAP文件(Generate 
                  mapfile)就可以产生.map文件了。</P>
                  <P>  &nbsp;打开mfcexpenddll工程生成的.map文件,我们发现其中包含了图15中所示的符号(symbol)</P>
                  <P class=code>&nbsp;0001:00000380&nbsp; 
                  ?HasImage@CSXButton@@QAEHXZ 10001380 f i 
                  SXBUTTON.OBJ<BR>&nbsp;0001:000003d0&nbsp; 
                  ??0CSXButton@@QAE@XZ&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
                  100013d0 f&nbsp;&nbsp; 
                  SXBUTTON.OBJ<BR>&nbsp;0001:00000500&nbsp; 
                  ??_GCSXButton@@UAEPAXI@Z&nbsp;&nbsp; 10001500 f i 
                  SXBUTTON.OBJ<BR>&nbsp;0001:00000570&nbsp; 
                  ??_ECSXButton@@UAEPAXI@Z&nbsp;&nbsp; 10001570 f i 
                  SXBUTTON.OBJ<BR>&nbsp;0001:00000630&nbsp; 
                  ??1CSXButton@@UAE@XZ&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
                  10001630 f&nbsp;&nbsp; SXBUTTON.OBJ<BR>0001:00000700 
                  ?_GetBaseMessageMap@CSXButton@@KGPBUAFX_MSGMAP@@XZ 10001700 
                  f&nbsp;&nbsp; SXBUTTON.OBJ<BR>&nbsp;0001:00000730 
                  ?GetMessageMap@CSXButton@@MBEPBUAFX_MSGMAP@@XZ 10001730 
                  f&nbsp;&nbsp; 
                  SXBUTTON.OBJ<BR>&nbsp;0001:00000770&nbsp;&nbsp;&nbsp; 
                  ?Redraw@CSXButton@@AAEXXZ&nbsp; 10001770 f i 
                  SXBUTTON.OBJ<BR>&nbsp;0001:000007d0&nbsp;&nbsp;&nbsp; 
                  ?SetIcon@CSXButton@@QAEHIHH@Z 100017d0 f&nbsp;&nbsp; 
                  SXBUTTON.OBJ<BR>……………………………………………………………………..//省略<BR>&nbsp;<BR></P>
                  <P align=center><IMG alt="" 
                  src="VC++动态链接库(DLL)编程深入浅出(四).files/20051121084537423.gif" 
                  border=0></P>
                  <P align=center><FONT color=#888888>图16 产生.map文件</FONT><FONT 
                  color=#888888> (+</FONT><A 
                  href="http://www.study888.com/computer/UploadFiles/200511/20051121084537218.gif&amp;namecode=pcedu&amp;subnamecode=pcedu_index" 
                  target=_blank><FONT color=#3366cc>放大该图片</FONT></A><FONT 
                  color=#888888>)</FONT></P>
                  <P>  所以,对于MFC扩展DLL,我们不宜以.lib文件导出类。</P>
                  <P><STRONG>6.2 MFC扩展DLL的调用</STRONG></P>
                  <P>  在DLL所在工作区新增一个dllcall工程,它是一个基于对话框的MFC 
                  EXE程序。在其中增加两个按钮SXBUTTON1、SXBUTTON2,并设置其属性为“Owner 
                  draw”,如图17。</P>
                  <P align=center><IMG alt="" 
                  src="VC++动态链接库(DLL)编程深入浅出(四).files/20051121084537503.gif" 
                  border=0></P>
                  <P align=center><FONT color=#888888>图17 设置按钮属性为“Owner 
                  draw”</FONT></P>
                  <P>  在工程中添加两个ICON资源:IDI_MSN_ICON(MSN的图标)、IDI_REFBAR_ICON(Windows的系统图标)。</P>
                  <P>  修改工程的“calldllDlg.h”头文件为:</P>
                  <P class=code>#include "..\..\mfcexpenddll\SXBUTTON.h"&nbsp; 
                  //包含dll的导出类头文件<BR>#pragma 
                  comment(lib,"mfcexpenddll.lib")&nbsp;&nbsp;&nbsp; 
                  //隐式链接dll<BR>/////////////////////////////////////////////////////////////////////////////<BR>// 
                  CCalldllDlg dialog<BR><BR>class CCalldllDlg : public 
                  CDialog<BR>{<BR>// 
                  Construction<BR>public:<BR>&nbsp;CCalldllDlg(CWnd* pParent = 
                  NULL);&nbsp;// standard constructor<BR><BR>// Dialog 
                  Data<BR>&nbsp;//{{AFX_DATA(CCalldllDlg)<BR>&nbsp;enum { IDD = 
                  IDD_CALLDLL_DIALOG 
                  };<BR>//增加与两个按钮对应的成员变量<BR>&nbsp;CSXButton&nbsp;m_button1;&nbsp;&nbsp; 
                  <BR>&nbsp;CSXButton&nbsp;m_button2;<BR>…<BR>}</P>
                  <P>  同时,修改“calldllDlg.cpp”文件,使得m_button1、m_button2成员变量与对话框上的按钮控件建立关联:</P>
                  <P class=code>void CCalldllDlg::DoDataExchange(CDataExchange* 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -