C# 关闭承载Windows窗体控件的WPF UserControl的WinForm时,窗口句柄无效

C# 关闭承载Windows窗体控件的WPF UserControl的WinForm时,窗口句柄无效,c#,.net,wpf,winforms,C#,.net,Wpf,Winforms,我有一个程序,是由一群不同的人在许多不同的年。有些应用程序是用Winforms编写的,有些是用WPF编写的。我有一个在某些窗口(WPF)中使用的WPF用户控件,我正试图将其放入程序的一个Winforms窗口中。我有这个控件的WPF和WinForms版本,WinForms版本非常复杂,与我的新WPF版本相比有点缺陷,这就是为什么我将它放在旧的WinForms窗口中 此WPF Usercontrol内部有一个WinForms控件,因为我找不到所需控件的WPF版本(hexbox)。在我的winform

我有一个程序,是由一群不同的人在许多不同的年。有些应用程序是用Winforms编写的,有些是用WPF编写的。我有一个在某些窗口(WPF)中使用的WPF用户控件,我正试图将其放入程序的一个Winforms窗口中。我有这个控件的WPF和WinForms版本,WinForms版本非常复杂,与我的新WPF版本相比有点缺陷,这就是为什么我将它放在旧的WinForms窗口中

此WPF Usercontrol内部有一个WinForms控件,因为我找不到所需控件的WPF版本(hexbox)。在我的winforms表单中,我放置了一个ElementHost来承载这个UserControl(WPF)。在我关闭窗口之前,它工作得很好,当我得到一个Win32Exception时,它说InvalidWindowHandle。没有有用的堆栈跟踪

当我关闭表单时,我会处理它的elementhost TranslatorWPF。在处理解释器RWPF时,它依次处理hexbox及其WinFormHostedControl

  • 解释器rwpf:WPF用户控件
  • 解释器元素主机:WinFormsElementHost
  • PathfindingEditor:承载所有这些内容的WinForms窗体
当我关闭PathfindingEditor时,我会处理许多事情来防止内存泄漏

(pathfindingeditor.cs)
私有无效路径查找编辑器\u FormClosing(对象发送方,FormClosingEventArgs e)
{
//取消设置以防止内存泄漏
Dispose();
解释器wfpelementhost.Child=null;
解释器wfpelementhost.Dispose();
...
(translatorwpf.xaml.cs)
公共覆盖无效处置()
{
解释器\u Hexbox=null;
解释器_Hexbox_Host.Child.Dispose();
解释器\u Hexbox\u Host.Dispose();
}
现在我不知道还能做些什么。取代winforms控件的新WPF控件更简单,故障也小得多。将旧表单改为WPF会很好,但我还没有找到一个适合它需要执行的复杂任务的库,WPF中winforms托管的元素有很多缺点,这就是这就是为什么我不会走得比六角盒子更远


我已经阅读了Dispatcher.InvokeShutdown()的相关内容,但这似乎完全关闭了WPF UI线程。我怀疑这是我想要的。请尝试将ElementHost的WPF根元素的AutomationProperties.NameProperty设置为某个有效字符串,例如:

elementHost.HandleCreated += delegate(object sender, EventArgs e)
                             {
                                 HwndSource source = (HwndSource)HwndSource.FromVisual(elementHost.Child);
                                 AutomationProperties.SetName(source.RootVisual, "elementHost");
                             };
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;
    }
当连接Visual Studio调试器时,我收到了以下异常,非常短的调用堆栈:

源“WindowsBase”
StackTrace“在MS.Win32.unsafentiveMethods.GetWindowText(HandleRef hWnd、StringBuilder lpString、Int32 nMaxCount)”中使用“

没有调试器,异常不可见

异常是从WPF framwork方法
System.Windows.Automation.Peers.GenericRootAutomationPeer.GetNameCore
中引发的,因为ElementHost的WPF部分的已释放窗口句柄
base.Hwnd
在方法中使用,如下所示:

elementHost.HandleCreated += delegate(object sender, EventArgs e)
                             {
                                 HwndSource source = (HwndSource)HwndSource.FromVisual(elementHost.Child);
                                 AutomationProperties.SetName(source.RootVisual, "elementHost");
                             };
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()
返回一个有效字符串,这会导致跳过有问题的代码。

不要将任何设置为
null
。只需
Dispose
。我并不是说这会解决问题,但这本身就是个问题。谢谢Roland。我真的不喜欢这个解决方案,但它解决了问题。你找到了更平滑的解决方案吗?