MFC常规DLL和扩展DLL相同点在于在于在两种DLL的内部都可以使用MFC类库,FC扩展DLL的含义在于它是MFC的扩展,其主要功能是实现从现有MFC库类中派生出可重用的类。MFC扩展DLL必须使用MFC 动态链接库版本。
1.对于扩展DLL我们首先要了解系统提供的宏,先来看一下微软定义宏:
文件:AFXV_DLL.H
// default AFX_EXT_DATA and AFX_EXT_DATADEF macros for using or
// creating MFC extension DLLs, depending on _AFX_EXT_IMPL
// AFX_EXT_CLASS can be used to import or export entire classes
// in an extension DLL without the hassle of creating a .DEF file
// with decorated names.
...
#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
文件:AFXVER_.H
...
// The following macros are used to enable export/import
// 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
...
从文件AFXV_DLL.H的注释中可以看出微软给我们类 导出提供非常有用的 宏AFX_EXT_CLASS,它既可以是导出类的宏也可以是导入类的宏,更重要的是它自己能判断此时自己是导入或者导出。因为微软在EXE模块编译中没加入宏_AFXEXT,所以宏[AFX_EXT_CLASS]在被加载时是导入接口,而在扩展DLL编译中加入宏,这时宏[AFX_EXT_CLASS]是导出接口。
因此要用扩展DLL导出类,只需在CLASS和类名中间加入宏[AFX_EXT_CLASS]。
2.下面我用扩展DLL来导出MFC中CToolTipCtrl的派生类。
- 先创建扩展MFC(使用MFC动态链接库)。工程名:CToolTipCtrlEx
- 创建基于MFC类CToolTipCtrl的派生类CToolTipCtrlEx
- 想派生类 中增加扩展函数,代码如下:
/ // CToolTipCtrlEx message handlers //向指定控件添加Tip功能 BOOL CToolTipCtrlEx::AddTool(UINT nID, LPCTSTR lpszText) { TOOLINFO ti; memset(&ti, 0, sizeof(TOOLINFO)); //结构体大小,必须填 ti.cbSize = sizeof(TOOLINFO); //ToolTip显示的Flag ti.uFlags = TTF_IDISHWND|TTF_SUBCLASS; //ToolTip的宿主(控件的父窗口句柄) ti.hwnd = GetOwner() -> GetSafeHwnd(); //应该监视的控件句柄 ti.uId = ( UINT )((GetParent() -> GetDlgItem( nID )) -> m_hWnd); //Tip上的提示信息 ti.lpszText = (LPSTR)lpszText; //发送消息给控件 return ( BOOL )SendMessage( TTM_ADDTOOL, 0, ( LPARAM )&ti ); } //向指定区域添加Tip功能 BOOL CToolTipCtrlEx::AddArea(UINT nID, LPRECT lpRect, LPCTSTR lpszText) { //以下OOLINFO参数含义参考函数[AddTool] TOOLINFO ti; memset(&ti, 0, sizeof(TOOLINFO)); ti.cbSize = sizeof(TOOLINFO); ti.uFlags = TTF_SUBCLASS; ti.hwnd = GetOwner() -> GetSafeHwnd(); //自定义ID,以后修改ToolTip的内容 ti.uId = nID; ti.lpszText = (LPSTR)lpszText; memcpy( &ti.rect, lpRect, sizeof( RECT ) ); return ( BOOL )SendMessage( TTM_ADDTOOL, 0, ( LPARAM )&ti ); }
- 编译生成MFC扩展DLL,对于导出类接口一般我们提供三个文件:接口定义的头文件.H,记录接口位置文件LIB,动态库DLL;
- 项目工程中会把需要扩展的MFC类做成扩展动态库(经验);
3.接着 我们写例子程序去加载扩展DLL(CToolTipCtrlEx.dll);
- 创建简单的MFC对话框程序,工程名:TipTest;
- 一般对于扩展类导出我们都采用静态链接的方式,在 这需要三个文件(CToolTipCtrlEx.h,CToolTipCtrlEx.lib,CToolTipCtrlEx.dll);
- 对话框头文件TipTestDlg.h中定义CToolTipCtrlEx的对象m_toolTip;
- 利用对象m_toolTip去实现当鼠标移动到“确认”按钮上,提示“红色OK”信息;当鼠标移动到蓝色区域时,提示“红色Hello”;
- 主要代码:
/ // CTipTestDlg message handlers BOOL CTipTestDlg::OnInitDialog() { CDialog::OnInitDialog(); ... // TODO: Add extra initialization here m_toolTip.Create(this); m_toolTip.AddTool(IDOK, "OK"); CRect rect(0,0,100,20); m_toolTip.AddArea(0, &rect, "Hello"); m_toolTip.SetTipBkColor(RGB(255, 0, 0)); m_toolTip.Activate(TRUE); return TRUE; // return TRUE unless you set the focus to a control }
- 效果图:
有不合适的地方欢迎大家讨论。