我正在对 C++ MFC 项目进行一些小改动。我是 .NET 开发人员,所以 Windows 编程对我来说是新的。
我需要在 CDialog 第一次完全显示(绘制)后立即启动一些方法,但只有一次。
我怎样才能做到这一点?在 .NET 中,我将处理Form.Shown事件。
我需要处理一些消息吗?哪一个?我需要重写一些 CDialog 方法吗?还是没有简单的方法?我正在考虑处理 WM_ACTIVATE 然后使用一个标志来确保我只调用另一个方法一次。
在这里找到答案:等到对话框显示后再做某事
Short story:
INT_PTR CALLBACK
DlgProc(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
switch (uiMsg) {
case WM_INITDIALOG:
return TRUE;
case WM_WINDOWPOSCHANGED:
if ((((WINDOWPOS*)lParam)->flags & SWP_SHOWWINDOW) &&
!g_fShown) {
g_fShown = TRUE;
PostMessage(hwnd, WM_APP, 0, 0);
}
break;
case WM_APP:
MessageBox(hwnd,
IsWindowVisible(hwnd) ? TEXT("Visible")
: TEXT("Not Visible"),
TEXT("Title"), MB_OK);
break;
case WM_CLOSE:
EndDialog(hwnd, 0);
break;
}
return FALSE;
}
如果您像我一样使用 MFC,则需要映射 WM_WINDOWPOSCHANGED,然后使用 ON_MESSAGE 映射 WM_APP。有关更多详细信息,请参阅此 CodeProject 文章。
作为参考,您不需要重写 DlgProc 来拦截 WM_WINDOWPOSCHANGED。
ON_WM_WINDOWPOSCHANGED()
ON_MESSAGE(MyCDialog::MY_USER_MSG, OnDialogShown)
void MyCDialog::OnWindowPosChanged(WINDOWPOS *wndpos)
{
__super::OnWindowPosChanged(wndpos);
if (!mDialogShown && (wndpos->flags & SWP_SHOWWINDOW)) {
PostMessage(MY_USER_MSG);
mDialogShown = true;
}
}
LRESULT MyCDialog::OnDialogShown(WPARAM, LPARAM)
{
...
}
如果合适,您可以实现内联处理,而不是发布另一条消息。
我多次使用并取得巨大成功的另一种方法是使用计时器。设置为 10m0s。它只会在显示对话框后触发。
地狱将代码放在 OnPaint() 中,然后在您的班级中使用 bool m_fullyInitilized。我也喜欢计时器。虽然我通常用 100 毫秒。在这些情况下,我还将我的所有初始化代码移出 oninit。只是为了防止那里有太多的处理。