MFC托管的WPF用户控件如何在按下按钮时关闭父窗口

时间:2012-02-23 14:03:20

标签: c# wpf mfc interop c++-cli

我试图获取旧版MFC应用程序和新的WPF用户控件,以根据WPF用户控件中的按钮按下关闭对话框窗口。从本质上讲,我想了解如何获得MFC返回的DoModal()功能。

由于各种原因,对话框是通过CDialog启动的MFC DoModal,它承载单个WPF组件而没有其他内容。然后该组件有一个按钮,在执行一些不同的任务后需要关闭CDialog。这个应用程序是一个遗留下来的遗留案例,很难跟踪控制流程以及驱动这个东西的实际消息泵所处的位置。它也充满了#defines,使得一切都变得难以应对。我认为我已经确定了消息泵,所以我认为我可以在其中插入一些东西以使其接近 - 如果我可以从WPF控件获得它。

我不知道如何将windows消息从usercontrol发送到主机,或者如何从usercontrol获取主机的HWND。我确定有办法实现这一目标,或者是另一种更好的沟通方式吗?

向父WM_CLOSE发送HWND邮件的正确方法是什么?或者也许我可以向对话泵发送WM_USER并处理那里的实际关闭?

3 个答案:

答案 0 :(得分:4)

试试这个。它应该适用于任何WPF元素(如果它是一个Visual),通过查找它包含HWND,跟踪HWND树直到它找到根父,然后发送WM_CLOSE消息。

   [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
    static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

   [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
    private static extern IntPtr GetParent(IntPtr hWnd);

    //I'd double check this constant, just in case
    static uint WM_CLOSE = 0x10;

    private void CloseContainingWindow(Visual visual)
    {
        // Find the containing HWND for the Visual in question
        HwndSource wpfHandle = PresentationSource.FromVisual(this) as HwndSource;
        if (wpfHandle == null)
        {
            throw new Exception("Could not find Window handle");
        }

        // Trace up the window chain, to find the ultimate parent
        IntPtr hWindow = wpfHandle.Handle;
        while (true)
        {
            IntPtr parentHWindow = GetParent(hWindow);
            if (parentHWindow == (IntPtr)0) break;
            hWindow = parentHWindow;
        }

        // Now send the containing window a close message
        SendMessage(hWindow, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
    }

答案 1 :(得分:2)

在控件中声明一个close事件。关闭关闭按钮时提升事件。

在您的CDialog派生类中,订阅该事件,然后在事件处理程序中调用EngDialog。

答案 2 :(得分:0)

WM_CLOSE应该可以使用,但你必须尝试一下。 另一种方法是将WM_COMMAND消息发布到父对话框。 发送WM_USER看起来太复杂了。