消息循环与全局变量控制线程结束的问题?

bearnedzq 2004-12-28 03:51:03
消息循环与全局变量控制线程结束的问题?
我新建了一个MFC regular dll工程。在工程中插入了一个对话框资源,并且为它生成了一个类CMyDlg。接着写了两个导出函数如下所示:
CMyDlg *pDlg; //pDlg为全局变量
extern "C" __declspec(dllexport) void Dlg_Open(){
AFX_MANAGE_STATE(AfxGetStaticModuleState());
pDlg = new CMyDlg;
pDlg->Create(IDD_MY_DIALOG);
pDlg->ShowWindow(SW_SHOW);
}

extern “C” __declspec(dllexport) void Dlg_Close(){
AFX_MANAGE_STATE(AfxGetStaticModuleState());
::SendMessage( pDlg->m_hWnd, WM_CLOSE, 0, 0 );
delete pDlg;
}

在CMyDlg类中有对WM_CLOSE消息的处理:
void CCats_keyDlg::OnClose(){
this->DestroyWindow();
CDialog::OnClose();
}

到此如果是Windows程序来调用这个dll的导出函数,它会工作的非常好。但是现在调用着不是Windows程序,而是普通的C Dos程序。如下所示:
#include “stdio.h”

_declspec(dllimport) void Dlg_Open();
_declspec(dllimport) void Dlg_Close();

void main(){
char command;
while(1){
scanf(“%c”, &command);
if(command == ‘o’){
Dlg_Open();
}
else if(command == ‘c’){
Dlg_Close();
}
else if(command == ‘q’){
break;
}
}
}

当然这里没考虑按错键的处理,也没考虑如果没有先创建Dialog就执行了Dlg_Close()而发生的错误,为了逻辑清晰,我将代码简化了。
这里有个问题,当对话框创建了以后,可以看到在任务栏上有它缩小的图标,的确是创建出来了,可是,它就像个害羞的小姑娘一样,即使用鼠标点它,也不露面,只是在任务栏中占块地方而已,关闭对话框也能正常工作。如何使对话框显示出来,以便对她进行相关的操作呢,如果是Windows程序来调用它的话,当然没有什么问题,现在估计是scanf()的原因让她不敢正常显示。我试了别的方法,如 getchar()
,也不起作用。于是就想办法改变dll。
我这次在一个单独的线程中创建对话框,并且还增加了消息循环,代码如下:
CMyDlg *pDlg = NULL;
bool bIsCreated = false;
bool bOutOfMessageLoop = false;//全局变量用来控制消息循环的跳出

UINT CreateDlg(LPVOID pParam){
AFX_MANAGE_STATE(AfxGetStaticModuleState());
bOutOfMessageLoop = false;
pDlg = new CMyDlg;
pDlg->Create(IDD_MY_DIALOG);
pDlg->ShowWindow(SW_SHOW);

MSG msg;
BOOL bRet;
while( true ) {
//AfxMessageBox("begin");
if( bOutOfMessageLoop ){
AfxMessageBox("In the if …");
break;
}
//AfxMessageBox("end ");
bRet = GetMessage( &msg, NULL, 0, 0 );
if (bRet == -1) {
//some error happened
//AfxMessageBox("Some error happened in Display module");
break;
}
else if( bRet != 0) {
//normal message process
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else{
//WM_QUIT
AfxMessageBox("WM_QUIT");
break;
}
}
//delete pDlg;
AfxMessageBox("Out of message loop");
return 0;
}

extern "C" __declspec(dllexport) void Dlg_Open(){
AfxBeginThread( CreateDlg, 0 );
}

extern "C" __declspec(dllexport) void Dlg_Close(){
AFX_MANAGE_STATE(AfxGetStaticModuleState());
::SendMessage( pDlg->m_hWnd, WM_CLOSE, 0, 0 ); bOutOfMessageLoop = true;
delete pDlg;
}

让人高兴的是,这样竟然能工作。羞答答的对话框这下竟然露出来了。但我还是有疑问:如 pDlg 在线程中分配了内存 pDlg = new CMyDlg; 但是没有在这个线程中执行相应的 delete pDlg;而是在另一个线程中执行了这句话,有作用吗?我觉得最好在消息循环退出时执行delete pDlg;于是我对源代码稍加改变,这次当消息循环退出时执行 delete pDlg; 即将Dlg_Close()中的 delete pDlg;注释掉,然后将
CreateDlg()中 return 0;前面的 delete pDlg;的注释去掉,不幸的是这句话不会被执行到,因为AfxMessageBox("Out of message loop");这个消息框我从没见他弹出过,不仅它没有弹出过,while循环中的AfxMessageBox("In the if …");这个消息框也从没出现过。按照设计,在关闭对话框后,应该能见到她们两个的。可是就是见不到。实在令人费解,更让我觉得不可思议的是我将CreateDlg()中的if语句前后的两个消息框的注释去掉,即
while( true ) {
AfxMessageBox("begin");
if( bOutOfMessageLoop ){
AfxMessageBox("In the if …");
break;
}
AfxMessageBox("end ");

那么在关闭对话框时就能看见if语句中的AfxMessageBox("In the if …");消息框和消息循环结束后的AfxMessageBox("Out of message loop");消息框。
这段代码虽然能工作,但还是有不少疑点,希望CSDN的兄弟姐妹们瞧瞧后给些意见,小弟洗耳恭听啦J

...全文
212 11 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
wang_bluebird 2005-03-31
  • 打赏
  • 举报
回复
mark
bearnedzq 2004-12-30
  • 打赏
  • 举报
回复
To: skfox(sky)
我已经调用成功了呀,只是不知如何释放 pDlg 指针而已。
bearnedzq 2004-12-30
  • 打赏
  • 举报
回复
Anikan 2004-12-30
  • 打赏
  • 举报
回复
请问c-dos程序能加载动态库吗?
skfox 2004-12-29
  • 打赏
  • 举报
回复
控制台程序没有能力去使用Windows GUI库,而windows应用程序是加载了GUI库的
bearnedzq 2004-12-28
  • 打赏
  • 举报
回复
非常感谢诸位高手对我的提示,明天试一下^_^。
bearnedzq 2004-12-28
  • 打赏
  • 举报
回复
由于我事先是在Word中写好的,直接粘贴的,以致部分代码非常混乱,而且忙中出错,还有一些小毛病,现在改正如下:

UINT CreateDlg(LPVOID pParam){
AFX_MANAGE_STATE(AfxGetStaticModuleState());
bOutOfMessageLoop = false;
pDlg = new CMyDlg;
pDlg->Create(IDD_MY_DIALOG);
pDlg->ShowWindow(SW_SHOW);

MSG msg;
BOOL bRet;
while( true ){
//AfxMessageBox("begin");
if( bOutOfMessageLoop ){
AfxMessageBox("In the if …");
break;
}
//AfxMessageBox("end ");

bRet = GetMessage( &msg, NULL, 0, 0 );
if (bRet == -1){
//some error happened
AfxMessageBox("Some error happened");
break;
}
else if( bRet != 0){
//normal message process
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else{
//WM_QUIT Message
AfxMessageBox("WM_QUIT");
break;
}
}
//delete pDlg;
AfxMessageBox("Out of message loop");
return 0;
}

在CMyDlg类中有对WM_CLOSE消息的处理:
void CMyDlg::OnClose(){
this->DestroyWindow();
CDialog::OnClose();
}

DentistryDoctor 2004-12-28
  • 打赏
  • 举报
回复
::SendMessage( pDlg->m_hWnd, WM_CLOSE, 0, 0 );
bOutOfMessageLoop = true;
delete pDlg;
=>
::PostMessage(pDlg->m_hWnd,WM_NCDESTROY,0,0);
老夏Max 2004-12-28
  • 打赏
  • 举报
回复
如果可以的话,可以将程序源代码发到:xia_qingqi@broadxent.com.cn
我帮你看看!注明帖子的URL!
DentistryDoctor 2004-12-28
  • 打赏
  • 举报
回复
PostNcDestroy就行了。
flyelf 2004-12-28
  • 打赏
  • 举报
回复
由于你是一个无模式对话框,可以在对话框的PostNcDestroy中delete this来释放自己

15,473

社区成员

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

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