📄 vc++动态链接库(dll)编程深入浅出(四).htm
字号:
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> // Remove this if you use
lpReserved<BR> UNREFERENCED_PARAMETER(lpReserved);<BR><BR> if
(dwReason ==
DLL_PROCESS_ATTACH)<BR> {<BR> TRACE0("MFCEXPENDDLL.DLL
Initializing!\n");<BR><BR> // Extension DLL one-time
initialization<BR> if
(!AfxInitExtensionModule(MfcexpenddllDLL,
hInstance))<BR> return 0;<BR><BR> //
Insert this DLL into the resource chain<BR> // NOTE: If
this Extension DLL is being implicitly linked to
by<BR> // an MFC Regular DLL (such as an ActiveX
Control)<BR> // instead of an MFC application, then
you will want to<BR> // remove this line from
DllMain and put it in a separate<BR> // function
exported from this Extension DLL. The Regular
DLL<BR> // that uses this Extension DLL should then
explicitly call that<BR> // function to initialize
this Extension DLL. Otherwise,<BR> // the
CDynLinkLibrary object will not be attached to
the<BR> // Regular DLL's resource chain, and
serious problems will<BR> //
result.<BR><BR> new
CDynLinkLibrary(MfcexpenddllDLL);<BR> }<BR> else if
(dwReason ==
DLL_PROCESS_DETACH)<BR> {<BR> TRACE0("MFCEXPENDDLL.DLL
Terminating!\n");<BR> // Terminate the library before
destructors are
called<BR> AfxTermExtensionModule(MfcexpenddllDLL);<BR> }<BR> return
1; // 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> #define AFX_DATA_EXPORT
__declspec(dllexport)<BR>#endif<BR>#ifndef
AFX_DATA_IMPORT<BR> #define AFX_DATA_IMPORT
__declspec(dllimport)<BR>#endif<BR><BR>// for
classes<BR>#ifndef AFX_CLASS_EXPORT<BR> #define
AFX_CLASS_EXPORT __declspec(dllexport)<BR>#endif<BR>#ifndef
AFX_CLASS_IMPORT<BR> #define AFX_CLASS_IMPORT
__declspec(dllimport)<BR>#endif<BR><BR>// for global
APIs<BR>#ifndef AFX_API_EXPORT<BR> #define AFX_API_EXPORT
__declspec(dllexport)<BR>#endif<BR>#ifndef
AFX_API_IMPORT<BR> #define AFX_API_IMPORT
__declspec(dllimport)<BR>#endif<BR><BR>#ifndef
AFX_EXT_DATA<BR> #ifdef _AFXEXT<BR> #define
AFX_EXT_CLASS
AFX_CLASS_EXPORT<BR> #define
AFX_EXT_API
AFX_API_EXPORT<BR> #define
AFX_EXT_DATA
AFX_DATA_EXPORT<BR> #define
AFX_EXT_DATADEF<BR> #else<BR> #define
AFX_EXT_CLASS
AFX_CLASS_IMPORT<BR> #define
AFX_EXT_API
AFX_API_IMPORT<BR> #define
AFX_EXT_DATA
AFX_DATA_IMPORT<BR> #define
AFX_EXT_DATADEF<BR> #endif<BR>#endif</P>
<P> 导出一个类,直接在类声明头文件中使用AFX_EXT_CLASS即可,以下是导出CSXButton类的例子:</P>
<P class=code>#ifndef _SXBUTTON_H<BR>#define
_SXBUTTON_H<BR><BR>#define SXBUTTON_CENTER -1<BR><BR>class
AFX_EXT_CLASS CSXButton : public CButton<BR>{<BR>//
Construction<BR>public:<BR> CSXButton();<BR><BR>//
Attributes<BR>private:<BR> // Positioning<BR> BOOL m_bUseOffset; <BR> CPoint m_pointImage;<BR> CPoint m_pointText;<BR> int m_nImageOffsetFromBorder;<BR> int m_nTextOffsetFromImage;<BR><BR> // Image<BR> HICON m_hIcon; <BR> HBITMAP m_hBitmap;<BR> HBITMAP m_hBitmapDisabled;<BR> int m_nImageWidth,
m_nImageHeight;<BR><BR> // Color
Tab<BR> char m_bColorTab; <BR> COLORREF m_crColorTab;<BR><BR> // State<BR> BOOL m_bDefault;<BR> UINT m_nOldAction;<BR> UINT m_nOldState;<BR> <BR>//
Operations<BR>public:<BR> // Positioning<BR> int SetImageOffset(
int nPixels ); <BR> int SetTextOffset( int
nPixels );<BR> CPoint SetImagePos( CPoint p
);<BR> CPoint SetTextPos( CPoint p
);<BR><BR> // Image<BR> BOOL SetIcon( UINT
nID, int nWidth, int nHeight );<BR> BOOL SetBitmap(
UINT nID, int nWidth, int nHeight
);<BR> BOOL SetMaskedBitmap( UINT nID, int nWidth,
int nHeight, COLORREF crTransparentMask
);<BR> BOOL HasImage() { return (BOOL)( m_hIcon !=
0 | m_hBitmap != 0 ); }<BR><BR> // Color
Tab<BR> void SetColorTab(COLORREF
crTab);<BR><BR> // State<BR> BOOL SetDefaultButton(
BOOL bState = TRUE
);<BR>private:<BR> BOOL SetBitmapCommon( UINT nID,
int nWidth, int nHeight, COLORREF crTransparentMask, BOOL
bUseMask );<BR> void CheckPointForCentering( CPoint
&p, int nWidth, int nHeight
);<BR> void Redraw();<BR><BR>//
Overrides<BR> // ClassWizard generated virtual function
overrides<BR> //{{AFX_VIRTUAL(CSXButton)<BR> public:<BR> virtual
void DrawItem(LPDRAWITEMSTRUCT
lpDrawItemStruct);<BR> //}}AFX_VIRTUAL<BR><BR>//
Implementation<BR>public:<BR> virtual
~CSXButton();<BR><BR> // Generated message map
functions<BR>protected:<BR> //{{AFX_MSG(CSXButton)<BR> afx_msg
LRESULT OnGetText(WPARAM wParam, LPARAM
lParam);<BR> //}}AFX_MSG<BR><BR> 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> <BR><FONT color=#888888>图15 导出类时导出的大量符号
(+<A
href="http://www.study888.com/computer/UploadFiles/200511/20051121084537189.gif&namecode=pcedu&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> 打开mfcexpenddll工程生成的.map文件,我们发现其中包含了图15中所示的符号(symbol)</P>
<P class=code> 0001:00000380
?HasImage@CSXButton@@QAEHXZ 10001380 f i
SXBUTTON.OBJ<BR> 0001:000003d0
??0CSXButton@@QAE@XZ
100013d0 f
SXBUTTON.OBJ<BR> 0001:00000500
??_GCSXButton@@UAEPAXI@Z 10001500 f i
SXBUTTON.OBJ<BR> 0001:00000570
??_ECSXButton@@UAEPAXI@Z 10001570 f i
SXBUTTON.OBJ<BR> 0001:00000630
??1CSXButton@@UAE@XZ
10001630 f SXBUTTON.OBJ<BR>0001:00000700
?_GetBaseMessageMap@CSXButton@@KGPBUAFX_MSGMAP@@XZ 10001700
f SXBUTTON.OBJ<BR> 0001:00000730
?GetMessageMap@CSXButton@@MBEPBUAFX_MSGMAP@@XZ 10001730
f
SXBUTTON.OBJ<BR> 0001:00000770
?Redraw@CSXButton@@AAEXXZ 10001770 f i
SXBUTTON.OBJ<BR> 0001:000007d0
?SetIcon@CSXButton@@QAEHIHH@Z 100017d0 f
SXBUTTON.OBJ<BR>……………………………………………………………………..//省略<BR> <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&namecode=pcedu&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"
//包含dll的导出类头文件<BR>#pragma
comment(lib,"mfcexpenddll.lib")
//隐式链接dll<BR>/////////////////////////////////////////////////////////////////////////////<BR>//
CCalldllDlg dialog<BR><BR>class CCalldllDlg : public
CDialog<BR>{<BR>//
Construction<BR>public:<BR> CCalldllDlg(CWnd* pParent =
NULL); // standard constructor<BR><BR>// Dialog
Data<BR> //{{AFX_DATA(CCalldllDlg)<BR> enum { IDD =
IDD_CALLDLL_DIALOG
};<BR>//增加与两个按钮对应的成员变量<BR> CSXButton m_button1;
<BR> CSXButton 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 + -