我的应用程序需要在 InitInstance()
中创建一些昂贵的东西。我想通知用户进度,所以我决定在 InitInstance()
方法中创建一个无模式对话框。
我的问题是,对话框没有绘制。它在
之后更新CStartStopDlg dlg(_T("Start"));
dlg.Create(IDD_START_STOP_DLG);
dlg.ShowWindow(SW_SHOW);
// expensive stuff
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
即使我在这行之后休眠,它也会更新对话框。问题是,MainFrame 使用了我创建的资源,所以我无法重新排列这些行。
如何解决这个问题?
编辑: 昂贵的东西是与相机的连接、与 io 硬件的连接、与数据库的连接和创建工作线程。应用程序对象拥有所有这些东西,大型机及其 View 等使用它。由于这些内容与应用程序中的文档无关。
根据以太网负载,连接需要不同的时间。
模态对话框不需要响应。我只想要类似 adobe reader 的启动对话框的东西。
UpdateWindow()
的提示是正确的方向,我在更新状态时添加了对此函数的调用。这解决了我的问题。
最佳答案
CStartStopDlg dlg(_T("Start"));
创建一个 owned对话框,因为 pParentWnd 隐式设置为 NULL
(参见 CDialog::CDialog)。此对话框归主应用程序窗口所有。
自有窗口的一个特点是,当它们的所有者被隐藏时,它们也会被隐藏。因此,在您调用 m_pMainWnd->ShowWindow(SW_SHOW);
之前,您拥有的对话框也不会显示。
有很多方法可以解决这个问题。
- 显而易见的解决方案是立即显示主应用程序窗口。但是,这可能不切实际(并且不能解决阻塞 UI 线程的问题)。
- 将昂贵的初始化工作卸载到工作线程:
这是必需的,以便 UI 线程可以服务传入的消息,例如作为用户交互的结果。您需要在工作线程和 GUI 线程之间实现某种通信。将自定义消息 (WM_APP + x
) 发布到主应用程序窗口通常就足够了。 - 推迟昂贵的初始化:
InitInstance
不应做任何比启动此应用程序实例所需的更多的事情。任何类型的高成本操作都应推迟到用户可以看到 UI(并可能取消该操作)的时间点。
一种常见的方法是为此创建一个一次性计时器。由于WM_TIMER
消息是低优先级的,这些消息只有在所有其他消息都已处理并且应用程序处于可操作状态后才会到达。此时,您可以将昂贵的初始化卸载到工作线程,并显示一个模态对话框,直到它完成。
关于c++ - App::InitInstance() 中的无模式对话框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39977480/