消息循环与全局变量控制线程结束的问题?
消息循环与全局变量控制线程结束的问题?
我新建了一个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