簡體   English   中英

關閉承載 Windows 窗體控件的 WPF 用戶控件的 WinForm 時無效的窗口句柄

[英]Invalid Window Handle when closing a WinForm that hosts a WPF UserControl that hosts a Windows Forms control

我有一個程序,它是由一群不同的人在不同的年份制作的。 有些應用程序是用 Winforms 編寫的,有些應用程序是用 WPF 編寫的。 我有一個在某些窗口 (WPF) 中使用的 WPF 用戶控件,我正試圖將其放入我程序的 Winforms 窗口之一中。 我有這個控件的 WPF 和 WinForms 版本,與我的新 WPF 版本相比,WinForms 的非常復雜且有些錯誤,這就是我將它放入舊 WinForms 窗口的原因。

這個 WPF 用戶控件里面有一個 WinForms 控件,因為我找不到我需要的控件的 WPF 版本(一個十六進制框)。 在我的 winforms 表單中,我放置了一個 ElementHost 來托管這個 UserControl(WPF)。 它工作得很好,直到我關閉窗口,也就是當我收到一個 Win32Exception 說 InvalidWindowHandle 時。 沒有有用的堆棧跟蹤。

異常拋出

當我關閉表單時,我處理了 interpreterWPF,它的 elementhost。 在處理 interpreterWPF 時,它會依次處理 hexbox 和 WinFormHostedControl。

  • 解釋器WPF:WPF用戶控件
  • 解釋器WPFElementHost: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 線程。 我懷疑這就是我要找的東西。

嘗試將 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()返回有效字符串,從而導致跳過有問題的代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM