项目中使用了Duilib和Chrome中抽离的base线程模型来进行开发,
在使用我简单封装的仿MFC CMessageBox时,发现偶尔会出现DoDodal的返回值并非用户的点击项,
跟踪后发现,base自己的消息循环(MessageLoop)处理时会有概率处理掉原生的消息队列消息WM_CLOSE,造成返回值是默认值,而非用户点击时传递进wParam.
这个发生的情况是,WM_CLOSE消息恰好被base的MessageLoop来处理,而非原生消息队列来GetMessage
void CWindowWnd::Close(UINT nRet)
{
ASSERT(::IsWindow(m_hWnd));
if( !::IsWindow(m_hWnd) ) return;
PostMessage(WM_CLOSE, (WPARAM)nRet, 0L);
}
进一步跟踪发现,base线程模型的库中已经考虑到这种设计,保留了os_modal_loop的set与get接口,当我们置os_modal_loop_为true时,base线程中处理时会使用原生的消息队列来处理
#if defined(OS_WIN)
void set_os_modal_loop(bool os_modal_loop) {
os_modal_loop_ = os_modal_loop;
}
bool os_modal_loop() const {
return os_modal_loop_;
}
#endif // OS_WIN
解决方案是:
CMessageBoxDlg dlg(m_hWnd, MsgBoxInfo::kCancelDownloadUpdate.c_str(), STRING_ID_MESSAGEBOX_TITLE, MB_OKCANCEL);
bool os_modal = base::MessageLoop::current()->os_modal_loop();
base::MessageLoop::current()->set_os_modal_loop(true);
UINT uresult = dlg.DoModal();
base::MessageLoop::current()->set_os_modal_loop(os_modal);
if (IDCANCEL == uresult || IDCLOSE == uresult) {
return;
}