【问题标题】:FindWindow by class name not working?按类名查找窗口不起作用?
【发布时间】:2011-08-26 19:31:23
【问题描述】:

作为序言,我们有一个奇怪的要求,即所有对话框对于 MFC 应用程序都必须是无模式的。有一个特定的对话框使用区域绘图和一些自定义控件来选择日期和时间,以查看每个视图的过去和未来数据。当它失去焦点、主应用程序获取系统命令等时,我需要能够关闭此窗口。

我认为最简单的方法是像这样注册类:

    // for CWnd::FindWindow
    WNDCLASS wndcls;
    SecureZeroMemory(&wndcls, sizeof(WNDCLASS));
    wndcls.lpszClassName    = L"CTransactionDialog";
    wndcls.style            = CS_HREDRAW | CS_VREDRAW;
    wndcls.lpfnWndProc      = AfxWndProc;
    wndcls.cbClsExtra       = wndcls.cbWndExtra = 0;
    wndcls.hInstance        = AfxGetInstanceHandle();
    wndcls.hIcon            = NULL;
#ifndef _WIN32_WCE_NO_CURSOR
    wndcls.hCursor          = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
#else
    wndcls.hCursor          = 0;
#endif
    wndcls.hbrBackground    = (HBRUSH) (COLOR_BACKGROUND + 1);
    wndcls.lpszMenuName     = NULL;

    BOOL retVal = AfxRegisterClass(&wndcls);
    if (!retVal)
        AfxMessageBox(L"AfxRegisterClass(CTransactionDialog) Failed");

然后在响应各种事件处理程序和消息时,我希望关闭这些无模式窗口或窗口以执行类似这样的简单操作:

CWnd* pFound = NULL;
while ((pFound = CWnd::FindWindow(L"CTransactionDialog", NULL)) != NULL)
    pFound->DestroyWindow();

然而,尽管类注册成功并在调试中查看相关对话框的 GetRuntimeClass 并看到它与预期的匹配,FindWindow 似乎永远不会按预期找到或关闭这些无模式对话框。

我做错了什么还是有更好的方法来解决这个问题?

更新:这是通过对话框类上的静态方法创建对话框的方式。 create 中指定的 id 的对话框资源具有 Popup 属性集,该属性集应解析为 MFC 覆盖下的WS_POPUP 样式。据我所知,该对话框不应该也没有父级。

CTransactionDialog* CTransactionDialog::ShowTransactionDialog(const CRect& crCtrlToFloatAbove, UINT dialogID, Itime defaultTime, Itime initialTime)
{
    CTransactionDialog* pCTDialog = new CTransactionDialog(crCtrlToFloatAbove, dialogID, defaultTime, initialTime);
    pCTDialog->Create(CTransactionDialog::IDD);
    pCTDialog->ShowWindow(SW_SHOW);

    return pCTDialog;
}

更新: 哇! FindWindowEx 也没有找到任何东西。

CWnd::FindWindowEx(AfxGetMainWnd()->GetSafeHwnd(), NULL, L"CTransactionDialog", NULL);

但是我有一个新计划。我只是要制作自己的窗口消息并在主框架上处理它。我想我可以将指向对话框的指针作为消息的 lParam 传递,然后将其转换为 CWnd*,然后调用 DestroyWindow。它将以非常全面的方式适用于大多数情况。我可能会在最小化和最大化对话框的主框架窗口时遇到问题,但我们会看到。

【问题讨论】:

    标签: c++ winapi user-interface mfc


    【解决方案1】:

    FindWindow 不适用于子窗口。要查找子窗口,可以使用FindWindowEx,将父窗口的HWND作为第一个参数传递。

    【讨论】:

    • WS_POPUP 创建对话框时的样式否定 WS_CHILD。我还需要在课程注册中指定吗?
    • 你只是在使用Create()吗?如果是这样,那么这些窗口会将您的主应用程序窗口作为其父窗口。
    • 真的吗?即使我使用的资源在创建时映射到WS_POPUP 样式的属性中指定了弹出窗口?我将发布我的代码 sn-p 以供创建。
    • 是的,这绝对是问题所在。来自CDialog::Create() 的文档:“pParentWnd:指向对话框对象所属的父窗口对象(CWnd 类型)。如果为 NULL,则对话框对象的父窗口为设置为主应用程序窗口。"
    • 如果您需要在失去焦点时关闭窗口,请为相应的窗口消息实现处理程序并调用EndDialog()
    【解决方案2】:

    类名表示不是 c++ 类名 - 它表示窗口类名。这个名字是操作系统用来注册窗口的,与c++类无关。

    MSDN点亮你...

    【讨论】:

    • 正在使用窗口类名。
    • 我正在使用我的类名注册窗口类。我可能可以让它更独特,但我认为这会奏效。
    • 我明白了 - 抱歉 - 令人困惑。
    【解决方案3】:

    CWnd::FindWindow 不搜索子窗口。

    您正在创建的无模式窗口是否有可能有一个父集,这就是 FindWindow 找不到它的原因?

    【讨论】:

    • 窗口可以是没有WS_CHILD标志的子窗口或其他任何东西吗?他的窗口类没有。
    • WS_CHILD 与提供给 WNDCLASS 的样式正交
    【解决方案4】:

    以下是我能想到的最简单、最干净的解决方案:

    BOOL CTransactionDialog::OnNcActivate(BOOL bActive)
    {
        if (!bActive)
            PostMessage(WM_CLOSE);
    
        return CDialog::OnNcActivate(bActive);
    }
    

    【讨论】:

      【解决方案5】:

      对此不是 100% 确定,但我认为您需要在资源文件中设置您的类名。您正在定义一个 windows 类并创建一个对话框类,但您没有链接它们。在 WNDCLASS 结构中设置类名将无济于事,除非您确实有办法将其链接到对话框。如果您使用资源文件并在其中定义对话框和类名,那么它应该可以工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-01-06
        • 1970-01-01
        • 2021-09-20
        • 2021-10-17
        • 1970-01-01
        • 1970-01-01
        • 2018-12-06
        • 1970-01-01
        相关资源
        最近更新 更多