关闭承载Windows窗体控件的WPF用户控件的WinForm时,无效的窗口句柄

时间:2019-04-07 03:59:53

标签: c# .net wpf winforms

我有一个程序,由许多不同的人在不同的年份编写。有些应用程序是用Winforms编写的,有些应用程序是用WPF编写的。我有一个在某些窗口(WPF)中使用的WPF用户控件,并且我试图将其放置到程序的Winforms窗口之一中。我同时拥有该控件的WPF和WinForms版本,与新的WPF版本相比,WinForms控件非常复杂且存在一些错误,这就是为什么我将其放置在较旧的WinForms窗口中。

此WPF用户控件内部有一个WinForms控件,因为我找不到所需的WPF版本的控件(十六进制框)。在我的winforms表单内部,我放置了一个承载此UserControl(WPF)的ElementHost。直到关闭窗口(直到我收到一个说InvalidWindowHandle的Win32Exception),它都可以正常工作。没有有用的堆栈跟踪。

Exceptionthrown

当我关闭表单时,我将处理explorerWPF(它的元素宿主)。部署解释器WPF时,它将依次部署十六进制框和WinFormHostedControl。

  • interpreterWPF:WPF用户控件
  • interpreterWPFElementHost:WinFormsElementHost
  • PathfindingEditor:承载所有这些的WinForms表单

当我关闭PathfindingEditor时,我正在处理很多事情以防止内存泄漏。

(pathfindingeditor.cs)
private void PathfindingEditor_FormClosing(object sender, FormClosingEventArgs e)
        {
            //Nullify things to prevent memory leaks
            interpreterWPF.Dispose();
            interpreterWPFElementHost.Child = null;
            interpreterWPFElementHost.Dispose();
            ...
(interpreterwpf.xaml.cs)
public override void Dispose()
        {
            Interpreter_Hexbox = null;
            Interpreter_Hexbox_Host.Child.Dispose();
            Interpreter_Hexbox_Host.Dispose();
        }

目前还不确定该怎么办。取代winforms控件的新WPF控件要简单得多,而且故障少得多。将旧表单更改为WPF会很棒,但是我没有找到合适的库来执行它需要执行的复杂任务,WPF中Winforms托管的元素有很多缺点,这就是为什么我不会比hexbox更深入

我已经阅读了Dispatcher.InvokeShutdown(),但这似乎完全关闭了WPF UI线程。我怀疑这就是我想要的。

1 个答案:

答案 0 :(得分:1)

尝试将ElementHost的WPF根元素的AutomationProperties.NameProperty设置为一些有效的字符串,例如如下:

elementHost.HandleCreated += delegate(object sender, EventArgs e)
                             {
                                 HwndSource source = (HwndSource)HwndSource.FromVisual(elementHost.Child);
                                 AutomationProperties.SetName(source.RootVisual, "elementHost");
                             };

在附加Visual Studio调试器时,我收到了以下异常且很短的调用栈的异常:

Source "WindowsBase" StackTrace "at MS.Win32.UnsafeNativeMethods.GetWindowText(HandleRef hWnd, StringBuilder lpString, Int32 nMaxCount)"

没有调试器,则异常不可见。

在WPF框架方法System.Windows.Automation.Peers.GenericRootAutomationPeer.GetNameCore中引发异常,因为在该方法中使用ElementHost WPF部分的已放置的窗口句柄base.Hwnd的方法如下:

namespace System.Windows.Automation.Peers // from PresentationCore.dll
{
public class GenericRootAutomationPeer : UIElementAutomationPeer
{
    ...
    protected override string GetNameCore()
    {
        string text = base.GetNameCore();
        if (text == string.Empty)
        {
            IntPtr hwnd = base.Hwnd;
            if (hwnd != IntPtr.Zero)
            {
                try
                {
                    StringBuilder stringBuilder = new StringBuilder(512);
Throws  ======>     MS.Win32.UnsafeNativeMethods.GetWindowText(new HandleRef(null, hwnd), stringBuilder, stringBuilder.Capacity);
                    text = stringBuilder.ToString();
                }
                catch (Win32Exception)
                {
                }
                if (text == null)
                {
                    text = string.Empty;
                }
            }
        }
        return text;
    }

设置AutomationProperties.NameProperty可确保base.GetNameCore()返回一个有效的字符串,从而导致有问题的代码被跳过。