1.陷阱表现:
使用MFC进行GUI设计时,有时并不能完全抛开底层,以下举一个例子。这是我在实际开发中遇到的一个棘手问题,折磨了很久,呵呵。
由于代码是移管的,所以当时的界面式样与一般的Windows界面程序有所不同。一般的Windows程序,当模态对话框弹出后,其他的画面都会被锁定, 但这个GUI并没有将其它画面锁定:其他画面还可以动作,甚至关闭整个例程。
初看,虽然很别扭,但似乎很难说出它的问题。
但是,实际调试时发现这样一个问题:
CDialgA::OnButton1()
{
...
CDialogB dlg1;
dlg1.DoModal(); 此时dlg1接管了消息循环
...
}
CDialogB::OnButton1()
{
...
CDialogC dlg2;
dlg2.DoModal(); 此时dlg2接管了消息循环
...
}
按照一般的Windows界面式样,此时dlg1应当是不能够动作的,如果按照上面移管代码的式样呢?
此时,如果关闭dlg1,在调试过程中发现:实际dlg1.DoModal()函数并没有返回!它必须等到dlg2关闭后才能返回。这样,在同一线程内部出现了异步,从而导致了一系列问题。
2.陷阱剖析:
MFC的模态对话框的原理是这样的:
# 生成对话框,设一个标志为假
# 开始接管消息循环,收发消息,每次循环时检查标志是否为真
# 标志为真,退出,否则继续收发消息
上述陷阱情况下,过程是这样的:
# dlg1接管了消息循环
# dlg2接管了消息循环
# dlg1标志设为真,但是由于dlg1此时收发消息已经被dlg2阻塞,它不会退出消息收发循环
# dlg2标志设为真,同时紧接着退出消息循环
# dlg1得以继续消息收发循环,判断标志为真,从而退出循环,dlg1.DoModal()返回
3.设计回避:
上述陷阱应当回避,最简单的就是当模态对话框弹出时,锁定其它画面。如果不会出现上述陷阱,才可以考虑不锁定其它画面。
作者:donysk
E-Mail:donysk@gmail.com