📄 在dll中使用资源(1).htm
字号:
</span> <span lang=EN-US>switch(message) <br>
<br>
</span> <span lang=EN-US>{ <br>
<br>
</span> <span lang=EN-US> case WM_INITDIALOG: <br>
<br>
</span> <span lang=EN-US> return TRUE; <br>
<br>
</span> <span lang=EN-US> <br>
<br>
</span> <span lang=EN-US> case WM_COMMAND: <br>
<br>
</span> <span lang=EN-US> if(LOWORD(wParam)==IDOK) <br>
<br>
DialogBox(hinst,MAKEINTRESOURCE(IDD_ABOUTBOX), <br>
<br>
hDlg,(DLGPROC)AboutProc); <br>
<br>
</span> <span lang=EN-US> return TRUE;</span> <span lang=EN-US> <br>
<br>
</span> <span lang=EN-US> case WM_CLOSE: <br>
<br>
</span> <span lang=EN-US> DestroyWindow(hDlg); <br>
<br>
</span> <span lang=EN-US> hwndDLG = NULL; <br>
<br>
</span> <span lang=EN-US> return TRUE; <br>
<br>
</span> <span lang=EN-US>} <br>
<br>
</span> <span lang=EN-US>return FALSE; <br>
<br>
} <br>
<br>
<br>
<br>
BOOL CALLBACK AboutProc(HWND hDlg, UINT message, <br>
<br>
WPARAM wParam, LPARAM lParam) <br>
<br>
{ <br>
<br>
</span> <span lang=EN-US> switch(message) <br>
<br>
</span> <span lang=EN-US>{ <br>
<br>
</span> <span lang=EN-US> case WM_CLOSE: <br>
<br>
</span> <span lang=EN-US> EndDialog(hDlg,NULL); <br>
<br>
</span> <span lang=EN-US> hwndDLG = NULL; <br>
<br>
</span> <span lang=EN-US> return TRUE; <br>
<br>
</span> <span lang=EN-US>} <br>
<br>
</span> <span lang=EN-US>return FALSE; <br>
<br>
} <br>
<br>
<br>
<br>
4</span>)编译生成<span lang=EN-US>UseDlg.dll</span>和<span lang=EN-US>UseDlg.lib</span>。<span
lang=EN-US> <br>
<br>
<br>
<br>
</span>接下来我们建立调用此<span lang=EN-US>DLL</span>的应用程序,其步骤如下:<span lang=EN-US> <br>
<br>
<br>
<br>
1</span>)在<span lang=EN-US>VC</span>菜单中<span lang=EN-US>File->New</span>新建一个命名为<span
lang=EN-US>Use</span>的<span lang=EN-US>MFC AppWizard(exe)</span>工程,下一步选择<span
lang=EN-US>Dialog Based</span>之后点击<span lang=EN-US>Finish</span>按钮。<span
lang=EN-US> <br>
<br>
<br>
<br>
2</span>)在主对话框上面添加一个按钮,之后双击此按钮,会弹出<span lang=EN-US>Add Member Function</span>的对话框,直接点击<span
lang=EN-US>OK</span>进入<span lang=EN-US>void CUseDlg::OnButton1()</span>函数。并在此函数内添加一个函数调用:<span
lang=EN-US>ShowDlg();</span>。<span lang=EN-US> <br>
<br>
<br>
<br>
3</span>)紧跟在<span lang=EN-US>#include</span>语句后面加上如下代码:<span lang=EN-US> <br>
<br>
<br>
<br>
extern "C" __declspec(dllexport) void ShowDlg(); <br>
<br>
#pragma comment(lib,"debug/UseDlg") <br>
<br>
<br>
<br>
4</span>)将上面<span lang=EN-US>UseDlg</span>工程中生成的<span lang=EN-US>UseDlg.dll</span>和<span
lang=EN-US>UseDlg.lib</span>两个文件复制到<span lang=EN-US>Use</span>工程的<span
lang=EN-US>Debug</span>目录内。<span lang=EN-US> <br>
<br>
<br>
<br>
5</span>)编译生成<span lang=EN-US>Use.exe</span>。<span lang=EN-US> <br>
<br>
<br>
<br>
</span> 运行<span lang=EN-US>Use.exe</span>,点击<span lang=EN-US>Button1</span>按钮,可以看到一个名称为<span
lang=EN-US>Dialog</span>的非模态对话框弹出。点击上面的按钮,可以弹出模态对话框<span lang=EN-US>About</span>。运行成功。<span
lang=EN-US> <br>
<br>
<br>
<br>
</span> 让我们来回顾一下在<span lang=EN-US>Win32 DLL</span>中使用对话框的过程。<span
lang=EN-US> <br>
<br>
<br>
<br>
</span>在<span lang=EN-US>DLL</span>中,我们定义了两个对话框资源:<span lang=EN-US>IDD_DLG_SHOW</span>和<span
lang=EN-US>IDD_ABOUTBOX</span>,并且导出了函数<span lang=EN-US>ShowDlg</span>。在函数<span
lang=EN-US>ShowDlg</span>之中使用<span lang=EN-US>CreateDialog</span>函数创建了非模态对话框<span
lang=EN-US>IDD_DLG_SHOW</span>,并指定了该对话框的回调函数<span lang=EN-US>DlgProc</span>。在<span
lang=EN-US>DlgProc</span>之中处理了<span lang=EN-US>WM_INITDIALOG</span>、<span
lang=EN-US>WM_COMMAND</span>和<span lang=EN-US>WM_CLOSE</span>消息,以响应用户对对话框所做的动作。在处理按钮动作的时候,使用<span
lang=EN-US>DialogBox</span>函数创建<span lang=EN-US>IDD_ABOUTBOX</span>这个模态对话框,指定其回调函数为<span
lang=EN-US>AboutProc</span>,并且在<span lang=EN-US>AboutProc</span>中处理其相应消息。<span
lang=EN-US> <br>
<br>
<br>
<br>
</span>在<span lang=EN-US>EXE</span>中,我们使用隐式链接的方法来调用<span lang=EN-US>DLL</span>,并使用<span
lang=EN-US>DLL</span>中导出的<span lang=EN-US>ShowDlg</span>函数来调用<span
lang=EN-US>DLL</span>中的对话框。<span lang=EN-US> <br>
<br>
<br>
<br>
</span> 在<span lang=EN-US>Win32 DLL</span>中使用对话框就是这么简单,下面让我们来看一下在<span
lang=EN-US>MFC DLL</span>中如何使用对话框。<span lang=EN-US> <br>
<br>
2</span>.<span lang=EN-US>MFC DLL <br>
</span> 在<span lang=EN-US>MFC DLL</span>中使用对话框不像<span lang=EN-US>Win32 DLL</span>中那么简单,主要是因为<span
lang=EN-US>MFC</span>程序中存在一个模块状态(<span lang=EN-US>Module State</span>)的问题,也就是资源重复的问题。(此处的术语模块是指一个可执行程序,或指其操作不依赖于应用程序的其余部分但使用<span
lang=EN-US>MFC</span>运行库的共享副本的一个<span lang=EN-US>DLL</span>(或一组<span
lang=EN-US>DLL</span>)。我们所创建的<span lang=EN-US>MFC DLL</span>就是这种模块的一个典型实例。)<span
lang=EN-US> <br>
<br>
<br>
<br>
</span> 在每个模块(<span lang=EN-US>EXE</span>或<span lang=EN-US>DLL</span>)中,都存在一种全局的状态数据,<span
lang=EN-US>MFC</span>依靠这种全局的状态数据来区分不同的模块,以执行正确的操作。这种数据包括:<span lang=EN-US>Windows</span>实例句柄(用于加载资源),指向应用程序当前的<span
lang=EN-US>CWinApp</span>和<span lang=EN-US>CWinThread</span>对象的指针,<span
lang=EN-US>OLE</span>模块引用计数,以及维护<span lang=EN-US>Windows</span>对象句柄与相应的<span
lang=EN-US>MFC</span>对象实例之间连接的各种映射等。但当应用程序使用多个模块时,每个模块的状态数据不是应用程序范围的。相反,每个模块具有自已的<span
lang=EN-US>MFC</span>状态数据的私有副本。这种全局的状态数据就叫做<span lang=EN-US>MFC</span>模块状态。<span
lang=EN-US> <br>
<br>
<br>
<br>
</span>模块的状态数据包含在结构中,并且总是可以通过指向该结构的指针使用。当代码在执行时进入了某一个模块时,只有此模块的状态为<span
lang=EN-US>“</span>当前<span lang=EN-US>”</span>或<span lang=EN-US>“</span>有效<span
lang=EN-US>”</span>状态时,<span lang=EN-US>MFC</span>才能正确的区分此模块并执行正确的操作。<span
lang=EN-US> <br>
<br>
<br>
<br>
</span>例如,<span lang=EN-US>MFC</span>应用程序可以使用下面代码从资源文件中加载字符串:<span
lang=EN-US> <br>
<br>
<br>
<br>
CString str; <br>
<br>
str.LoadString(IDS_MYSTRING); <br>
<br>
<br>
<br>
</span>使用这种代码非常方便,但它掩盖了这样一个事实:即此程序中<span lang=EN-US>IDS_MYSTRING</span>可能不是唯一的标识符。一个程序可以加载多个<span
lang=EN-US>DLL</span>,某些<span lang=EN-US>DLL</span>可能也用<span lang=EN-US>IDS_MYSTRING</span>标识符定义了一个资源。<span
lang=EN-US>MFC</span>怎样知道应该加载哪个资源呢?<span lang=EN-US>MFC</span>使用当前模块状态查找资源句柄。如果当前模块不是我们要使用的正确模块,那么就会产生不正确的调用或者错误。<span
lang=EN-US> <br>
<br>
<br>
<br>
</span>按照<span lang=EN-US>MFC</span>库的链接方法,一个<span lang=EN-US>MFC DLL</span>有两种使用<span
lang=EN-US>MFC</span>库的方法:静态链接到<span lang=EN-US>MFC</span>的<span lang=EN-US>DLL</span>和动态链接到<span
lang=EN-US>MFC</span>的<span lang=EN-US>DLL</span>。下面我们就按照这两种类型的<span
lang=EN-US>MFC DLL</span>来介绍如何切换当前模块状态以正确的在<span lang=EN-US>MFC DLL</span>中使用资源。<span
lang=EN-US> <br>
<br>
1</span>、静态链接到<span lang=EN-US>MFC</span>的<span lang=EN-US>DLL <br>
<br>
</span>静态链接到<span lang=EN-US>MFC</span>的规则<span lang=EN-US>DLL</span>与<span
lang=EN-US>MFC</span>库静态链接,则此时<span lang=EN-US>MFC</span>库不能共享,所以<span
lang=EN-US>MFC</span>总是使用它所链接的<span lang=EN-US>DLL</span>的模块状态。这样也就不存在管理模块状态的问题。但使用这种方法的缺点是<span
lang=EN-US>DLL</span>程序将会变大,而且会在程序中留下重复代码。下面给出的例子验证了这一点。本例可以按照以下步骤来完成:<span
lang=EN-US> <br>
<br>
<br>
<br>
1</span>)在<span lang=EN-US>VC</span>菜单中<span lang=EN-US>File->New</span>新建一个命名为<span
lang=EN-US>DLLStatic</span>的<span lang=EN-US>MFC AppWizard</span>的工程,下一步选择<span
lang=EN-US>Regular DLL with MFC statically linked</span>。<span lang=EN-US> <br>
<br>
<br>
<br>
2</span>)在工程中添加一个对话框资源,其<span lang=EN-US>ID</span>为:<span lang=EN-US>IDD_ABOUTBOX</span>。并在<span
lang=EN-US>resource.h</span>之中将<span lang=EN-US>IDD_ABOUTBOX </span>的数值改为<span
lang=EN-US>100</span>。<span lang=EN-US> <br>
<br>
<br>
<br>
3</span>)在<span lang=EN-US>DLLStatic.cpp</span>中定义如下函数:<span lang=EN-US> <br>
<br>
<br>
<br>
void ShowDlg() <br>
<br>
{ <br>
<br>
</span> <span lang=EN-US> CDialog dlg(IDD_ABOUTBOX); <br>
<br>
</span> <span lang=EN-US> dlg.DoModal(); <br>
<br>
} <br>
<br>
<br>
<br>
4</span>)在<span lang=EN-US>DLLStatic.def</span>文件中的<span lang=EN-US>EXPORTS</span>语句中添加一行:<span
lang=EN-US>ShowDlg</span>,以导出<span lang=EN-US>ShowDlg</span>函数。<span
lang=EN-US> <br>
<br>
<br>
<br>
5</span>)编译生成<span lang=EN-US>DLLStatic.dll</span>和<span lang=EN-US>DLLStatic.lib</span>。<span
lang=EN-US> <br>
<br>
<br>
<br>
</span>继续使用上一节中的<span lang=EN-US>Use</span>工程,将前面生成的<span lang=EN-US>DLLStatic.dll</span>和<span
lang=EN-US>DLLStatic.lib</span>两个文件复制到工程的<span lang=EN-US>Debug</span>目录内,并将<span
lang=EN-US> <br>
<br>
<br>
<br>
extern "C" __declspec(dllexport) void ShowDlg(); <br>
<br>
#pragma comment(lib,"debug/UseDlg") <br>
<br>
<br>
<br>
</span>这两行改为:<span lang=EN-US> <br>
<br>
<br>
<br>
void ShowDlg(); <br>
<br>
#pragma comment(lib,"debug/DLLStatic") <br>
<br>
<br>
<br>
</span>编译并运行<span lang=EN-US>Use.exe</span>。点击按钮,可以看到<span lang=EN-US>DLLStatic</span>中的模态对话框弹出。<span
lang=EN-US> <br>
<br>
<br>
<br>
</span>本例中,可以注意到<span lang=EN-US>DLL</span>中所定义的<span lang=EN-US>About</span>对话框资源与<span
lang=EN-US>EXE</span>中所定义的<span lang=EN-US>About</span>对话框资源<span lang=EN-US>ID</span>完全相同,但是当我们点击<span
lang=EN-US>Use.exe</span>上面的按钮时,弹出的是<span lang=EN-US>DLL</span>中的模态对话框。说明,当使用静态链接到<span
lang=EN-US>MFC</span>的规则<span lang=EN-US>DLL</span>时,不存在管理模块状态的问题。<span
lang=EN-US><o:p></o:p></span></span></p>
</td>
<td style='padding:0cm 0cm 0cm 0cm'>
<p class=MsoNormal align=left style='text-align:left;mso-pagination:widow-orphan'><span
lang=EN-US style='font-size:10.0pt;mso-font-kerning:0pt'><o:p> </o:p></span></p>
</td>
<td style='padding:0cm 0cm 0cm 0cm'>
<p class=MsoNormal align=left style='text-align:left;mso-pagination:widow-orphan'><span
lang=EN-US style='font-size:10.0pt;mso-font-kerning:0pt'><o:p> </o:p></span></p>
</td>
</tr>
</table>
</div>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
</div>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -