簡體   English   中英

WindowsFormsHost失去了對激活應用程序的關注,甚至通過應用程序的其他wpf形式進行激活

[英]WindowsFormsHost steals focus on activating application even activating by application's other wpf form

重現我的案子(.net 4.0)

  1. 創建一個WPF應用程序(MainWindow.xaml)
  2. 添加一個包含文本框的Winform用戶控件(UserConrol1.cs-Winform)
  3. 使用Windowsformshost將UserControl1放入MainWindow.xaml
  4. 將另一個包含文本框(wpf)的WPF窗口添加到項目(Window1.xaml)
  5. 在MainWindow InitializeComponent之后創建並顯示Window1

您的項目已准備就緒,

  1. 運行Project並在MainWindow.xaml(在WindowsFormsHost中)集中設置文本框
  2. 通過打開一個窗口(Windows文件瀏覽器,記事本,winamp等)來停用您的應用程序
  3. 通過用鼠標單擊文本框,嘗試在Window1窗口中的文本框中編寫文本

而且您會看到您無法將焦點設置在Window1中的文本框上,因為MainWindow Texbox(在winformshost中將使您的焦點轉移到已激活的應用程序上)

任何想法?

MainWindow.xaml

<Window x:Class="WinFormsHostFocusProblem.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WinFormsHostFocusProblem"
        xmlns:my="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
      <my:WindowsFormsHost  Focusable="False"  >
         <local:UserControl1>

         </local:UserControl1>
      </my:WindowsFormsHost>

   </Grid>
</Window>

MainWindow.xaml.cs

namespace WinFormsHostFocusProblem
{
   public partial class MainWindow : Window
   {
      public MainWindow()
      {
         InitializeComponent();
         Window1 window1 = new Window1();
         window1.Show();
      }
   }
}

Window1.xaml

<Window x:Class="WinFormsHostFocusProblem.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WinFormsHostFocusProblem"
        xmlns:my="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
        SizeToContent="WidthAndHeight" 
        ResizeMode="NoResize"

        Topmost="True"
        Title="Window1" Height="300" Width="300" Background="Red">
    <Grid>
      <TextBox Height="25">asd</TextBox>
   </Grid>
</Window>

Window1.xaml.cs

namespace WinFormsHostFocusProblem
{
   public partial class Window1 : Window
   {
      public Window1()
      {
         InitializeComponent();
      }
   }
}

我使用了MSDN支持合同來獲取此問題的答案。 工程師能夠從yunusayd的示例進行復制,並確認幾乎可以肯定這是WindowsFormsHost中的錯誤。

感謝yunus提供了最少的repro示例,並感謝Microsoft的Keith解決了該問題並在不到一天的時間內提供了解決方法。

解決方法代碼如下。 它通過使用.NET反射來更改WindowsFormsHost中使用的私有變量並禁用該錯誤的觸發器,從而起作用。 根據我與之合作的工程師的說法,這依賴於WPF內部,但是他與產品團隊成員進行了交談,並且應該安全使用。 當然,不能保證沒有副作用,但是到目前為止,在多個WPF窗口中使用多個WindowsFormsHosts進行測試時,我還沒有發現任何問題(嵌套可能會更棘手)。 我修改了原始的解決方法,以與多個窗口通用。 您可以輕松地在Application_Deactivated事件中對特定窗口和命名的WindowsFormsHost控件進行硬編碼引用,並跳過整個“ LastActive”方案和擴展方法。

// App.xaml.cs: you must hook up to Application.Deactivated
void Application_Deactivated(object sender, EventArgs e)
{
    foreach (Window w in windows)
    {
        foreach (var host in UI.DependencyObjectExtension.AllLogicalChildren(w).
                     Where(c => c is WindowsFormsHost))
        {
            FIELD_FOCUSED_CHILD.SetValue(host, null);
        }
    }
}


public readonly static FieldInfo FIELD_FOCUSED_CHILD = typeof(System.Windows.Forms.Integration.WindowsFormsHost).
    GetField("_focusedChild", BindingFlags.NonPublic | BindingFlags.Instance);

public static class DependencyObjectExtension
{
    /// <summary>
    /// Returns a collection of o's logical children, recursively.
    /// </summary>
    /// <param name="o"></param>
    /// <returns></returns>
    public static IEnumerable<DependencyObject> AllLogicalChildren(this DependencyObject o)
    {
        foreach (var child in LogicalTreeHelper.GetChildren(o))
        {
            if (child is DependencyObject)
            {
                yield return (DependencyObject)child;

                if (child is DependencyObject)
                {
                    foreach (var innerChild in AllLogicalChildren((DependencyObject)child))
                    {
                        yield return innerChild;
                    }
                }
            }
        }
    }
}

我們在一個應用程序中遇到了類似的問題,發現升級到.net 4.5似乎已解決了我們應用程序的WPF / WinForms焦點問題的很大一部分,包括與此類似的問題。

此外,_netedChild字段在WindowsFormsHost的.net 4.5版本中不再存在

暫無
暫無

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

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