分类: C/C++
2008-01-24 21:13:08
图8 设置动态/静态链接MFC DLL
5.2 MFC规则DLL的创建
我们来一步步讲述使用MFC向导创建MFC规则DLL的过程,首先新建一个project,如图9,选择project的类型为MFC AppWizard(dll)。点击OK进入如图10所示的对话框。
图9 MFC DLL工程的创建
图10所示对话框中的1区选择MFC DLL的类别。BOOL CRegularDllSocketApp::InitInstance()
{
if (!AfxSocketInit())
{
AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
return FALSE;
}
return TRUE;
}
图10 MFC DLL的创建选项
5.3 一个简单的MFC规则DLL
这个DLL的例子(属于静态链接到MFC 的规则DLL)中提供了一个如图11所示的对话框。
图11 MFC规则DLL例子
在DLL中添加对话框的方式与在MFC应用程序中是一样的。// RegularDll.h : main header file for the REGULARDLL DLL
#if !defined(AFX_REGULARDLL_H__3E9CB22B_588B_4388_B778_B3416ADB79B3__INCLUDED_)
#define AFX_REGULARDLL_H__3E9CB22B_588B_4388_B778_B3416ADB79B3__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#ifndef __AFXWIN_H__
#error include 'stdafx.h' before including this file for PCH
#endif
#include "resource.h" // main symbols
class CRegularDllApp : public CWinApp
{
public:
CRegularDllApp();
DECLARE_MESSAGE_MAP()
};
#endif
// RegularDll.cpp : Defines the initialization routines for the DLL.
#include "stdafx.h"
#include "RegularDll.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
BEGIN_MESSAGE_MAP(CRegularDllApp, CWinApp)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CRegularDllApp construction
CRegularDllApp::CRegularDllApp()
{
}
/////////////////////////////////////////////////////////////////////////////
// The one and only CRegularDllApp object
CRegularDllApp theApp;
virtual BOOL InitApplication( );
virtual BOOL InitInstance( );
virtual BOOL Run( ); //传说中MFC程序的“活水源头”
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by RegularDll.rc
//
#define IDD_DLL_DIALOG 1000
#define IDC_HELLO_BUTTON 1000
#include "StdAfx.h"
#include "DllDialog.h"
extern "C" __declspec(dllexport) void ShowDlg(void)
{
CDllDialog dllDialog;
dllDialog.DoModal();
}
图12 MFC规则DLL的调用例子
下面是“调用DLL”按钮单击事件的消息处理函数:
void CRegularDllCallDlg::OnCalldllButton()
{
typedef void (*lpFun)(void);
HINSTANCE hDll; //DLL句柄
hDll = LoadLibrary("RegularDll.dll");
if (NULL==hDll)
{
MessageBox("DLL加载失败");
}
lpFun addFun; //函数指针
lpFun pShowDlg = (lpFun)GetProcAddress(hDll,"ShowDlg");
if (NULL==pShowDlg)
{
MessageBox("DLL中函数寻找失败");
}
pShowDlg();
}
#pragma comment(lib,"RegularDll.lib")
void ShowDlg(void);
void CRegularDllCallDlg::OnCalldllButton()
{
ShowDlg();
}
图13 DLL中的对话框
另外,在与这个DLL相同的工作区中生成一个基于对话框的MFC程序,其对话框与图12完全一样。但是在此工程中我们另外添加了一个如图14的对话框。
图14 EXE中的对话框
图13和图14中的对话框除了caption不同(以示区别)以外,其它的都相同。//DLL中对话框的ID
#define IDD_DLL_DIALOG 2000
//EXE中对话框的ID
#define IDD_EXE_DIALOG 2000
#include "StdAfx.h"
#include "SharedDll.h"
void ShowDlg(void)
{
CDialog dlg(IDD_DLL_DIALOG); //打开ID为2000的对话框
dlg.DoModal();
}
void CSharedDllCallDlg::OnCalldllButton()
{
ShowDlg();
}
AFX_MANAGE_STATE(AfxGetStaticModuleState());
void ShowDlg(void)
{
//方法1:在函数开始处变更,在函数结束时恢复
//将AFX_MANAGE_STATE(AfxGetStaticModuleState());作为接口函数的第一//条语句进行模块状态切换
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CDialog dlg(IDD_DLL_DIALOG);//打开ID为2000的对话框
dlg.DoModal();
}
AFX_MODULE_STATE* AFXAPI AfxGetStaticModuleState( );
// AFX_MODULE_STATE (global data for a module)
class AFX_MODULE_STATE : public CNoTrackObject
{
public:
#ifdef _AFXDLL
AFX_MODULE_STATE(BOOL bDLL, WNDPROC pfnAfxWndProc, DWORD dwVersion);
AFX_MODULE_STATE(BOOL bDLL, WNDPROC pfnAfxWndProc, DWORD dwVersion,BOOL bSystem);
#else
AFX_MODULE_STATE(BOOL bDLL);
#endif
~AFX_MODULE_STATE();
CWinApp* m_pCurrentWinApp;
HINSTANCE m_hCurrentInstanceHandle;
HINSTANCE m_hCurrentResourceHandle;
LPCTSTR m_lpszCurrentAppName;
… //省略后面的部分
}
AFX_MANAGE_STATE( AFX_MODULE_STATE* pModuleState )
AfxGetResourceHandle();
AfxSetResourceHandle(HINSTANCE xxx);
void ShowDlg(void)
{
//方法2的状态变更
HINSTANCE save_hInstance = AfxGetResourceHandle();
AfxSetResourceHandle(theApp.m_hInstance);
CDialog dlg(IDD_DLL_DIALOG);//打开ID为2000的对话框
dlg.DoModal();
//方法2的状态还原
AfxSetResourceHandle(save_hInstance);
}
extern CSharedDllApp theApp; //需要声明theApp外部全局变量
void ShowDlg(void)
{
//方法2的状态变更
HINSTANCE save_hInstance = AfxGetResourceHandle();
AfxSetResourceHandle(theApp.m_hInstance);
CDialog dlg(IDD_DLL_DIALOG);//打开ID为2000的对话框
dlg.DoModal();
//方法2的状态还原
AfxSetResourceHandle(save_hInstance);
//使用方法2后在此处再进行操作针对的将是应用程序的资源
CDialog dlg1(IDD_DLL_DIALOG); //打开ID为2000的对话框
dlg1.DoModal();
}
void ShowDlg(void)
{
CDialog dlg(IDD_DLL_DIALOG); //打开ID为2000的对话框
dlg.DoModal();
}
void CSharedDllCallDlg::OnCalldllButton()
{
//方法3:由应用程序本身进行状态切换
//获取EXE模块句柄
HINSTANCE exe_hInstance = GetModuleHandle(NULL);
//或者HINSTANCE exe_hInstance = AfxGetResourceHandle();
//获取DLL模块句柄
HINSTANCE dll_hInstance = GetModuleHandle("SharedDll.dll");
AfxSetResourceHandle(dll_hInstance); //切换状态
ShowDlg(); //此时显示的是DLL的对话框
AfxSetResourceHandle(exe_hInstance); //恢复状态
//资源模块恢复后再调用ShowDlg
ShowDlg(); //此时显示的是EXE的对话框
}