C# 关闭承载Windows窗体控件的WPF UserControl的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及其WinFormHostedControlC# 关闭承载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
- 解释器rwpf:WPF用户控件
- 解释器元素主机:WinFormsElementHost
- PathfindingEditor:承载所有这些内容的WinForms窗体
(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。我真的不喜欢这个解决方案,但它解决了问题。你找到了更平滑的解决方案吗?