多次重复DoModal失效是为何?

中才德创 2011-11-11 10:19:00
发现,在Ctest1App::InitInstance()函数里面,想多次重复DoModal,可结果却是第一次是可行的。后来的再也不行。这是为什么?如何改进呢?

BOOL Ctest1App::InitInstance()
{
// 如果一个运行在 Windows XP 上的应用程序清单指定要
// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
//则需要 InitCommonControls()。否则,将无法创建窗口。
InitCommonControls();

CWinApp::InitInstance();

AfxEnableControlContainer();

// 标准初始化
// 如果未使用这些功能并希望减小
// 最终可执行文件的大小,则应移除下列
// 不需要的特定初始化例程
// 更改用于存储设置的注册表项
// TODO: 应适当修改该字符串,
// 例如修改为公司或组织名
SetRegistryKey(_T("应用程序向导生成的本地应用程序"));

Ctest1Dlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
INT_PTR nResponseAgain = dlg.DoModal(); //DoModal无效

if (nResponse == IDOK)
{
// TODO: 在此放置处理何时用“确定”来关闭
//对话框的代码
//新增个CMyDlg,DoModal无效
CMyDlg dlg2;
m_pMainWnd = &dlg2;
INT_PTR nResponse2 = dlg2.DoModal();
}
else if (nResponse == IDCANCEL)
{
// TODO: 在此放置处理何时用“取消”来关闭
//对话框的代码
}

// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
// 而不是启动应用程序的消息泵。
return FALSE;
}
...全文
292 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
中才德创 2011-11-26
  • 打赏
  • 举报
回复
//m_pMainWnd = &dlg;
这样就OK了
中才德创 2011-11-13
  • 打赏
  • 举报
回复
看不懂“初始化只进行1次”
bazzi2011 2011-11-11
  • 打赏
  • 举报
回复
你在InitInstance()这个初始化函数中调用Domodal()怎么可能重复调用呢?
初始化只进行1次啊!换地方写吧!

模态对话框点了OK/Cancel钮肯定会销毁的,但你不可能在InitInstance()再次把它Domodal()出来!
gameslq 2011-11-11
  • 打赏
  • 举报
回复
原因出在两次对m_pMainWnd进行了赋值
m_pMainWnd关闭主对话框,系统会向线程发送WM_QUIT,使得Ctest1Dlg 之后的对话框都显示一下就消失了,因为系统要关闭应用程序具体原因是

Use this data member to store a pointer to your thread’s main window object.
The Microsoft Foundation Class Library will automatically terminate your thread when
the window referred to by m_pMainWnd is closed. If this thread is the primary thread
for an application, the application will also be terminated. If this data member is NULL,
the main window for the application’s CWinApp object will be used to determine when to
terminate the thread. m_pMainWnd is a public variable of type CWnd*.

改进方法
常用方法是把第一个m_pMainWnd赋值 去掉

Ctest1Dlg dlg;
m_pMainWnd = &dlg; //去掉改行

或者新建一个界面线程。
中才德创 2011-11-11
  • 打赏
  • 举报
回复
DoModal是模态,必须等待点了OK/Cancel钮才能结束,这点我知道。

我的情况是,点了OK/Cancel钮结束一个模态对话框。为什么再次DoModal(同一dlg或不同的dlg),窗口不再弹出来了?

代码是跟踪了的。
中才德创 2011-11-11
  • 打赏
  • 举报
回复
我就想两个窗口DoModal结束后,能来回再次显示。如何做呢?
XNightSky 2011-11-11
  • 打赏
  • 举报
回复
口误 LS 的“窗口”应该是“对话框”
或者你可以在Ctest1Dlg对话框里再打开一个非模式子对话框,就没这情况了
XNightSky 2011-11-11
  • 打赏
  • 举报
回复

INT_PTR CDialog::DoModal()
{
//......省略

TRY
{
// create modeless dialog
AfxHookWindowCreate(this);
if (CreateDlgIndirect(lpDialogTemplate,
CWnd::FromHandle(hWndParent), hInst))
{
if (m_nFlags & WF_CONTINUEMODAL)
{
// enter modal loop
DWORD dwFlags = MLF_SHOWONIDLE;
if (GetStyle() & DS_NOIDLEMSG)
dwFlags |= MLF_NOIDLEMSG;
VERIFY(RunModalLoop(dwFlags) == m_nModalResult);
}

// hide the window before enabling the parent, etc.
if (m_hWnd != NULL)
SetWindowPos(NULL, 0, 0, 0, 0, SWP_HIDEWINDOW|
SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
}
}
CATCH_ALL(e)
{
DELETE_EXCEPTION(e);
m_nModalResult = -1;
}
END_CATCH_ALL
//......省略
return m_nModalResult;
}


DoModal()函数若干代码,可以看到RunModalLoop开启一个消息循环

INT_PTR nResponse = dlg.DoModal();//窗口打开,在函数中消息循环,等待接收到退出消息以后才会结束函数,跳到下一行代码
DoModal不是无效,而是上一行代码中的消息循环在一直迭代。。DoModal()模式窗口不退出,代码根本不往下走
zxfwizard 2011-11-11
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 bazzi2011 的回复:]

你在InitInstance()这个初始化函数中调用Domodal()怎么可能重复调用呢?
初始化只进行1次啊!换地方写吧!

模态对话框点了OK/Cancel钮肯定会销毁的,但你不可能在InitInstance()再次把它Domodal()出来!
[/Quote]
应该就是这个
XNightSky 2011-11-11
  • 打赏
  • 举报
回复
#5楼 是对的,厉害!

15,979

社区成员

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

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