dll中显示对话框(比较难噢)

ChangeMyHead 2004-07-27 06:05:31
我在Dll中写了一个对话框,并且在dll中导出一个函数(函数一)来显示对话框。

我在SDK的WinMain中调用该函数(函数一),结果异常退出。

该对话框用MFC的工程正常调用和显示。请大家指教噢

dll导出函数一(该函数已经正确导出):
void __declspec(dllexport) TestDlg(){

MessageBox( NULL , "TEST" , "Test" , 0 ); //该语句正常显示

CTestDlg oTest; //此处对话框完全正确,在MFC的exe工程里正确调用
oTest.DoModal();

return ;
}


exe调用语句
#include "export.h" //定义函数TestDlg();
#pragma comment( lib , "TestDll.lib" ) //对应lib库

int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
TestDlg();
...全文
1151 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
ChangeMyHead 2005-06-16
  • 打赏
  • 举报
回复
//为了不出现滚动条,FormView对应的窗口对话框一定要小

//设置启动窗口为最大
http://community.csdn.net/Expert/topic/3589/3589204.xml?temp=.8776667

//初始化窗口大小和位置
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs

//居中设置,先取得屏幕属性
int nFullWidth = GetSystemMetrics( SM_CXSCREEN );
int nFullHeight = GetSystemMetrics( SM_CYSCREEN );

//设置框架的大小和位置
cs.cx = 800;
cs.cy = 600;
cs.y = ( nFullHeight - 600 ) / 3;
cs.x = ( nFullWidth - 800 ) / 2;

return TRUE;
}

//下面函数设置控件的位置和大小(该事件在窗口变化时被触发)(所有FormView中的控件都可以这样设置)
void CTestFormVIewView::OnSize(UINT nType, int cx, int cy)
{
CFormView::OnSize(nType, cx, cy);

// TODO: Add your message handler code here
//SetWindowPos( NULL, 10, 20, 300, 300 ,SWP_DRAWFRAME);

//CString str_Out = "";
//str_Out.Format( "参数 CX=%d CY=%d" , cx , cy );
//MessageBox( str_Out );

//这是一个按钮
if( m_PPP.m_hWnd!=NULL ){
CRect oRect;
m_PPP.GetClientRect( &oRect );//oRect.Width(),oRect.Height()
m_PPP.SetWindowPos( NULL, cx-300, cy-300, oRect.Width(),oRect.Height(),SWP_DRAWFRAME);
}
}

显示View后要进行如下操作:
int iLow = 800;
int iHigh = 600;
LPARAM lParam = ( 801 << 16 ) | 601; //(iHigh*65536) + iLow; //计算窗口大小

::SendMessage(AfxGetApp()->m_pMainWnd->m_hWnd, WM_COMMAND, ID_FILE_NEW, 0);//新建一个文档
::SendMessage( pNewActView->m_hWnd, WM_SIZE , 100 , lParam ); //通知对方改变大小
bravexiaoy 2004-07-28
  • 打赏
  • 举报
回复
好像是 MFc 得 动态链接库 得 问题 , 再 Project->Settings.... 中的 设置问题
以前 我碰到 是 Debug 和 Realese 出现的问题
alphapiao 2004-07-28
  • 打赏
  • 举报
回复
前几天我遇到类似问题,
我没有办法调用出dll中的对话框.
结果我把我的exe工程settings改成share mfc就可以显示了.
你参考一下.
ChangeMyHead 2004-07-28
  • 打赏
  • 举报
回复
不行啊,exe工程是别人写的,我只能在别人的基础上继续写阿
rivershan 2004-07-28
  • 打赏
  • 举报
回复
改成MFC的咯。。。
ChangeMyHead 2004-07-28
  • 打赏
  • 举报
回复
并且我在exe中使用如下语句也不行
HINSTANCE dll=LoadLibrary("TestDll.dll");
if (dll)
AfxSetResourceHandle(dll);
ChangeMyHead 2004-07-28
  • 打赏
  • 举报
回复
我跟踪的结果是:
资源使用不对,每当涉及到资源(如对话框资源IDD_DIALOG_TEST)使用时必然异常(断言错误)

找到如下两篇文章,看了一下,问题还是没有解决http://dev.csdn.net/develop/article/25/25358.shtm
http://dev.csdn.net/develop/article/25/25359.shtm

因为我是用SDK的工程调用MFC扩展DLL的,所以在如下语句时没有办法使用theApp变量
HINSTANCE save_hInstance = AfxGetResourceHandle();
AfxSetResourceHandle(theApp.m_hInstance);
rivershan 2004-07-28
  • 打赏
  • 举报
回复
。。。。。。。。
我的文章
taianmonkey 2004-07-28
  • 打赏
  • 举报
回复
BOOL CALLBACK AboutProc(HWND hDlg, UINT message,

WPARAM wParam, LPARAM lParam)

{

switch(message)

{

case WM_CLOSE:

EndDialog(hDlg,NULL);

hwndDLG = NULL;

return TRUE;

}

return FALSE;

}



4)编译生成UseDlg.dll和UseDlg.lib。



接下来我们建立调用此DLL的应用程序,其步骤如下:



1)在VC菜单中File->New新建一个命名为Use的MFC AppWizard(exe)工程,下一步选择Dialog Based之后点击Finish按钮。



2)在主对话框上面添加一个按钮,之后双击此按钮,会弹出Add Member Function的对话框,直接点击OK进入void CUseDlg::OnButton1()函数。并在此函数内添加一个函数调用:ShowDlg();。



3)紧跟在#include语句后面加上如下代码:



extern "C" __declspec(dllexport) void ShowDlg();

#pragma comment(lib,"debug/UseDlg")



4)将上面UseDlg工程中生成的UseDlg.dll和UseDlg.lib两个文件复制到Use工程的Debug目录内。



5)编译生成Use.exe。



运行Use.exe,点击Button1按钮,可以看到一个名称为Dialog的非模态对话框弹出。点击上面的按钮,可以弹出模态对话框About。运行成功。



让我们来回顾一下在Win32 DLL中使用对话框的过程。



在DLL中,我们定义了两个对话框资源:IDD_DLG_SHOW和IDD_ABOUTBOX,并且导出了函数ShowDlg。在函数ShowDlg之中使用CreateDialog函数创建了非模态对话框IDD_DLG_SHOW,并指定了该对话框的回调函数DlgProc。在DlgProc之中处理了WM_INITDIALOG、WM_COMMAND和WM_CLOSE消息,以响应用户对对话框所做的动作。在处理按钮动作的时候,使用DialogBox函数创建IDD_ABOUTBOX这个模态对话框,指定其回调函数为AboutProc,并且在AboutProc中处理其相应消息。



在EXE中,我们使用隐式链接的方法来调用DLL,并使用DLL中导出的ShowDlg函数来调用DLL中的对话框。



在Win32 DLL中使用对话框就是这么简单,下面让我们来看一下在MFC DLL中如何使用对话框。

2.MFC DLL
在MFC DLL中使用对话框不像Win32 DLL中那么简单,主要是因为MFC程序中存在一个模块状态(Module State)的问题,也就是资源重复的问题。(此处的术语模块是指一个可执行程序,或指其操作不依赖于应用程序的其余部分但使用MFC运行库的共享副本的一个DLL(或一组DLL)。我们所创建的MFC DLL就是这种模块的一个典型实例。)



在每个模块(EXE或DLL)中,都存在一种全局的状态数据,MFC依靠这种全局的状态数据来区分不同的模块,以执行正确的操作。这种数据包括:Windows实例句柄(用于加载资源),指向应用程序当前的CWinApp和CWinThread对象的指针,OLE模块引用计数,以及维护Windows对象句柄与相应的MFC对象实例之间连接的各种映射等。但当应用程序使用多个模块时,每个模块的状态数据不是应用程序范围的。相反,每个模块具有自已的MFC状态数据的私有副本。这种全局的状态数据就叫做MFC模块状态。



模块的状态数据包含在结构中,并且总是可以通过指向该结构的指针使用。当代码在执行时进入了某一个模块时,只有此模块的状态为“当前”或“有效”状态时,MFC才能正确的区分此模块并执行正确的操作。



例如,MFC应用程序可以使用下面代码从资源文件中加载字符串:



CString str;

str.LoadString(IDS_MYSTRING);



使用这种代码非常方便,但它掩盖了这样一个事实:即此程序中IDS_MYSTRING可能不是唯一的标识符。一个程序可以加载多个DLL,某些DLL可能也用IDS_MYSTRING标识符定义了一个资源。MFC怎样知道应该加载哪个资源呢?MFC使用当前模块状态查找资源句柄。如果当前模块不是我们要使用的正确模块,那么就会产生不正确的调用或者错误。



按照MFC库的链接方法,一个MFC DLL有两种使用MFC库的方法:静态链接到MFC的DLL和动态链接到MFC的DLL。下面我们就按照这两种类型的MFC DLL来介绍如何切换当前模块状态以正确的在MFC DLL中使用资源。

1、静态链接到MFC的DLL

静态链接到MFC的规则DLL与MFC库静态链接,则此时MFC库不能共享,所以MFC总是使用它所链接的DLL的模块状态。这样也就不存在管理模块状态的问题。但使用这种方法的缺点是DLL程序将会变大,而且会在程序中留下重复代码。下面给出的例子验证了这一点。本例可以按照以下步骤来完成:



1)在VC菜单中File->New新建一个命名为DLLStatic的MFC AppWizard的工程,下一步选择Regular DLL with MFC statically linked。



2)在工程中添加一个对话框资源,其ID为:IDD_ABOUTBOX。并在resource.h之中将IDD_ABOUTBOX 的数值改为100。



3)在DLLStatic.cpp中定义如下函数:



void ShowDlg()

{

CDialog dlg(IDD_ABOUTBOX);

dlg.DoModal();

}



4)在DLLStatic.def文件中的EXPORTS语句中添加一行:ShowDlg,以导出ShowDlg函数。



5)编译生成DLLStatic.dll和DLLStatic.lib。



继续使用上一节中的Use工程,将前面生成的DLLStatic.dll和DLLStatic.lib两个文件复制到工程的Debug目录内,并将



extern "C" __declspec(dllexport) void ShowDlg();

#pragma comment(lib,"debug/UseDlg")



这两行改为:



void ShowDlg();

#pragma comment(lib,"debug/DLLStatic")



编译并运行Use.exe。点击按钮,可以看到DLLStatic中的模态对话框弹出。



本例中,可以注意到DLL中所定义的About对话框资源与EXE中所定义的About对话框资源ID完全相同,但是当我们点击Use.exe上面的按钮时,弹出的是DLL中的模态对话框。说明,当使用静态链接到MFC的规则DLL时,不存在管理模块状态的问题。
taianmonkey 2004-07-28
  • 打赏
  • 举报
回复
转载:
在DLL中使用资源(一)
在CSDN论坛上最常看见的关于DLL的问题就是如何在DLL中使用对话框,这是一个很普遍的关于如何在DLL中使用资源的问题。这里我们从Win32 DLL和MFC DLL两个方面来分析并解决这个问题。

1.Win32 DLL
在Win32 DLL中使用对话框很简单,你只需要在你的DLL中添加对话框资源,而且可以在对话框上面设置你所需要的控件。然后使用DialogBox或者CreateDialog这两个函数(或相同作用的其它函数)来创建对话框,并定义你自己的对话框回调函数处理对话框收到的消息。下面通过一个具体实例来学习如何在Win32 DLL中使用对话框,可以按照以下步骤来完成这个例子:



1)在VC菜单中File->New新建一个命名为UseDlg的Win32 Dynamic-Link Library工程,下一步选择A simple DLL project。



2)在VC菜单中Insert->Resource添加一个ID为IDD_DLG_SHOW的Dialog资源,将此Dialog上的Cancel按钮去掉,仅保留OK按钮。再添加一个ID为IDD_ABOUTBOX的对话框,其Caption为About。保存此资源,将资源文件命名为UseDlg.rc。并将resource.h和UseDlg.rc加入到工程里面。



3)在UseDlg.app中包含resource.h,并添加如下代码:



HINSTANCE hinst = NULL;

HWND hwndDLG = NULL;



BOOL CALLBACK DlgProc(HWND hDlg, UINT message,

WPARAM wParam, LPARAM lParam);

BOOL CALLBACK AboutProc(HWND hDlg, UINT message,

WPARAM wParam, LPARAM lParam);

extern "C" __declspec(dllexport) void ShowDlg();



BOOL APIENTRY DllMain( HANDLE hModule,

DWORD ul_reason_for_call,

LPVOID lpReserved

)

{

switch(ul_reason_for_call)

{

case DLL_PROCESS_ATTACH:

hinst = (HINSTANCE)hModule;

case DLL_PROCESS_DETACH:

break;

}

return TRUE;

}



extern "C" __declspec(dllexport) void ShowDlg()

{

hwndDLG = CreateDialog(hinst,MAKEINTRESOURCE(IDD_DLG_SHOW),

NULL,(DLGPROC)DlgProc);

ShowWindow(hwndDLG, SW_SHOW);

}



BOOL CALLBACK DlgProc(HWND hDlg, UINT message,

WPARAM wParam, LPARAM lParam)

{

switch(message)

{

case WM_INITDIALOG:

return TRUE;



case WM_COMMAND:

if(LOWORD(wParam)==IDOK)

DialogBox(hinst,MAKEINTRESOURCE(IDD_ABOUTBOX),

hDlg,(DLGPROC)AboutProc);

return TRUE;

case WM_CLOSE:

DestroyWindow(hDlg);

hwndDLG = NULL;

return TRUE;

}

return FALSE;

}
msvbvm60 2004-07-28
  • 打赏
  • 举报
回复
用 MFC 扩展 DLL最简单。。。
cpmax 2004-07-28
  • 打赏
  • 举报
回复
#define FM_Def _declspec(dllexport)

CScrollNewsApp theApp;

FM_Def BOOL FM_CreateDlg(CWnd *pParent)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());

//创建对话框
theApp.m_bCreated=theApp.m_WordDlg.Create(IDD_WordDlg,pParent);
//设置消息窗口
theApp.m_WordDlg.SetParentWnd(pParent);

return theApp.m_bCreated;
}

用的时候如下:
FM_CreateDlg(this);
showwindow(SW_SHOW);
syy64 2004-07-27
  • 打赏
  • 举报
回复
http://community.csdn.net/Expert/topic/3081/3081869.xml?temp=.9518244
rivershan 2004-07-27
  • 打赏
  • 举报
回复
DllMain重定义了。。。
http://community.csdn.net/Expert/topic/3155/3155545.xml?temp=7.217044E-02
看这个
holyeagle 2004-07-27
  • 打赏
  • 举报
回复
单步跟踪一下,看看oTest.DoModal();后有什么异常。
dll是否已经被释放?
ChangeMyHead 2004-07-27
  • 打赏
  • 举报
回复
我家上AFX_MANAGE_STATE(AfxGetStaticModuleState());后

在链接时出现如下错误
mfcs42.lib(dllmodul.obj) : error LNK2005: _DllMain@12 already defined in CLogIn.obj
mfcs42.lib(dllmodul.obj) : error LNK2005: __pRawDllMain already defined in CLogIn.obj

于是,我将上诉语句替换为:
AFX_MANAGE_STATE(AfxGetAppModuleState());
替换后,不出异常,但对话框界面一闪就关闭了
zhucde 2004-07-27
  • 打赏
  • 举报
回复
同一楼,在导出函数里必须加入:

AFX_MANAGE_STATE(AfxGetStaticModuleState());
gracezhu 2004-07-27
  • 打赏
  • 举报
回复
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
CTestDlg oTest;

15,465

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧