事情是这样的:
就是要实现一个登录窗口A(A是我的应用程序类以模式对话框方式创建的),如果密码和用户名输入正确的话,就显示出另个窗口B,另外A还要消失掉。
约定A对应的窗口类是CADlg,B对应的是CBDlg
开始是这样实现的,可是后来就发现了一些问题:
我在登陆按钮的事件的响应函数里面写了:
CBDlg bdlg;
if(Valid)
{
CDialog::OnOk();
bdlg.doModal();
}
else
{
AfxMessageBox(TEXT("Invalid Login!"));
}
这样是没有问题的,登录以后也完全OK。
但是由于后来学了多线程以后,发现登录服务器的时候,等待服务器返回时,界面会无响应,所以想到把这个登录的处理方在另外一个线程LoginThread里面。
我在CADlg里面定义了一个线程类对象CWinThread *m_t;
然后定义了这个线程的函数:
static void LoginThreadFunc(LPVOID);
调用这个函数的时候,传递this指针。再用这个指针操作A窗口即可。
问题于是出现了,一摸一样的代码。我这个放在线程里面的时候。运行起来B窗口就出不来了。只要一登陆,B窗口就一瞬即逝。
我不太确定是什么问题,但发现我的 CDialog::OnOk(); 执行在 bdlg.doModal();前面,会不会下面的来不及执行,整个窗口就结束了(但奇怪的是我放在原来的登录按钮响应函数里也这样写就可以完全成功运行)。但以防万一,我于是决定在登陆成功后不关闭A,而是隐藏它。
编译运行后,一切正常了。
但另一个问题又来了,这样一来,一旦我结束应用程序的时候,其实是关闭结束了B对话框,A还被我隐藏着,就无法结束了。这可以从进程里面看出来。
这样一来,一般的思路是,在B结束的时候,我们给A发送一个退出消息就可以了。
所以,我在B对应的析构函数里面写上了 GetParent()->PostMessage(WM_QUIT);
理由是,B一旦退出了,肯定会销毁对象,而销毁对象的时候必然会调用析构函数,所以能保证这个过程正确执行。
但是在我编译运行后,事实却出乎意料。
为了确认析构函数里面的这条语句确实执行,我在这条语句下面加了一条MessageBox语句。
但在我运行后,关闭B对话框的时候,这个messagebox却没执行,也就是说,析构函数没有被执行。
为什么,不得而知。
这个结果很让我意外,因为我以为就算不自己去响应WM_CLOSE消息,采用默认的,MFC也应该会回收B对话框的资源调用析构函数才对。但事实上却没有这样。
所以我索性自己响应了B对话框的WM_CLOSE的消息。
在void CBDlg::On_Close()函数里面,我写上了GetParent()->PostMessage(WM_QUIT);
结果正确完成任务,在我关闭B对话框的时候,进程也同时在任务管理器里面消失。
虽然这个小小的登陆框实现搞了半天终于搞好,但仍然有好多疑问没有搞清楚。
1.为什么一摸一样的东西,我放在线程函数里面就会出现B一出现马上消失的情况。
PS:
我最后做了一个实验:
我在应用程序类调用完A对话框后,紧接着,调用了B。结果问题和遇到的一样,B一出现就消失:
BOOL CTestApp::InitInstance()
{
CADlg dlg;
m_pMainWnd = &dlg;
dlg.DoModal();
CBDlg bdlg;
bdlg.DoModal();
}
2.为什么我在关闭B的时候,B的析构函数不被执行?
3.我这样的临时处理是最好的实现这样的登陆框的方案么?
若不是,还有其他什么办法?