WindowsFormsHost强制Focus

时间:2014-09-05 04:13:56

标签: c# wpf mvvm windowsformshost

我有一个类似于文本框的控件由WindowsFormsHost控件托管在我的WPF应用程序中。 Windows窗体控件是ScintillaNET。但我怀疑问题不存在(它在我的旧WinForms项目中工作正常)。

问题在于,当我将文本字段聚焦并尝试聚焦另一个窗口时,窗口会立即抓取焦点。

通过将焦点切换到另一个控件(通过单击)然后切换窗口,我已将此跟踪到文本字段处于焦点。

这有什么解决方法吗?我正在使用MVVM,因此只需将另一个控件设置为代码中的焦点就不是一种选择。

2 个答案:

答案 0 :(得分:0)

以下代码按预期工作。也许您可以发布一个示例来重现您的问题。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms.Integration;
using F=System.Windows.Forms;

namespace SimpleForm {

class Window1 : Window {

    F.TextBox tb = new F.TextBox();
    WindowsFormsHost host = new WindowsFormsHost();

    public Window1() {
        this.Width = 500;
        this.Height = 500;
        this.Title = "Title";

        host.Child = tb;

        Button btn = new Button { Content = "Button" };
        StackPanel panel = new StackPanel();
        panel.Orientation = Orientation.Vertical;
        panel.Children.Add(host);
        panel.Children.Add(btn);
        this.Content = panel;

        btn.Click += delegate {
            Window w2 = new Window { Width = 400, Height = 400 };
            w2.Content = new TextBox();
            w2.Show();
        };
    }

    [STAThread]
    static void Main(String[] args) {
        F.Application.EnableVisualStyles();
        F.Application.SetCompatibleTextRenderingDefault(false);
        var w1 = new Window1();
        System.Windows.Application app = new System.Windows.Application();
        app.Run(w1);
    }
}
}

答案 1 :(得分:0)

当前版本的.Net Framework中仍然存在这种“焦点”窃取问题。问题似乎与WindowsFormsHost控件有关,它一旦获得就会永久地窃取焦点(例如,通过点击其中的TextBox控件)。问题可能开始出现在.Net 4.0中,并且可能在4.5中部分修复,但在不同情况下仍然存在。我们发现解决问题的唯一方法是通过Windows API(因为WPF窗口具有与WindowsFormsHost控件分开的hWnd,该控件在窗口中呈现为窗口)。将以下两种方法添加到Window的类中(并在需要重新获取WPF窗口时调用它)有助于解决问题(通过将焦点返回到WPF窗口及其控件)

    /// <summary>
    /// Native Win32 API setFocus method.
    /// <param name="hWnd"></param>
    /// <returns></returns>
    [System.Runtime.InteropServices.DllImport("user32.dll")]
    static extern IntPtr SetFocus(IntPtr hWnd);        

    /// <summary>
    /// Win32 API call to set focus (workaround for WindowsFormsHost permanently stealing focus).
    /// </summary>
    public void Win32SetFocus()
    {
        var wih = new WindowInteropHelper(this); // "this" being class that inherits from WPF Window
        IntPtr windowHandle = wih.Handle;

        SetFocus(windowHandle);
    }

当从具有WindowsFormsHost控件的页面导航到另一个没有控件的页面时,这也会有所帮助,尽管您很可能需要延迟调用Win32SetFocus(使用{{3 }})。

  

注意:此代码仅使用x86(32位)版本进行测试,但相同的解决方案应与x64(64位)版本一起使用。如果您需要相同的DLL / EXE代码在两个平台上工作,请改进此代码以加载正确的(32位或64位)非托管DLL。