我有一个文本框控件在我的WPF应用程序由WindowsFormsHost控件托管。窗体控件是ScintillaNET。但我怀疑问题不存在(它在我的旧WinForms项目中工作正常)。WindowsFormsHost力量焦点
问题是,当我将文本字段聚焦并且我尝试将焦点放在另一个窗口时,窗口紧随其后聚焦。
我已经通过将焦点切换到另一个控件(通过点击)然后切换窗口来追踪到焦点所在的文本字段。
有没有解决方法?我正在使用MVVM,因此只需将另一个控件设置为代码中的焦点不是一种选择。
我有一个文本框控件在我的WPF应用程序由WindowsFormsHost控件托管。窗体控件是ScintillaNET。但我怀疑问题不存在(它在我的旧WinForms项目中工作正常)。WindowsFormsHost力量焦点
问题是,当我将文本字段聚焦并且我尝试将焦点放在另一个窗口时,窗口紧随其后聚焦。
我已经通过将焦点切换到另一个控件(通过点击)然后切换窗口来追踪到焦点所在的文本字段。
有没有解决方法?我正在使用MVVM,因此只需将另一个控件设置为代码中的焦点不是一种选择。
以下代码按预期工作。也许你可以发表一个例子来重现你的问题。
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);
}
}
}
这种“焦点”盗取问题在当前版本的.Net Framework中仍然存在。问题似乎与WindowsFormsHost控制有关,该控件一旦获取就会永久性地窃取焦点(例如通过单击其中的TextBox控件)。问题可能开始出现在.Net 4.0中,并可能在4.5中部分修复,但在不同情况下仍然存在。我们发现通过Windows API解决问题的唯一方法就是通过Windows API(因为WPF窗口与WindowsFormsHost控件分开的hWnd在窗口内呈现为窗口)。添加下列2种方法来窗口的类(并调用它,当需要进行恢复焦点的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(使用DispatcherTimer)。
注:此代码仅使用x86(32位)建设进行了测试,但同样的解决方案应该使用x64(64位)的构建工作。如果您需要相同的DLL/EXE代码才能在两个平台上工作,请改进此代码以加载适当的(32位或64位)非托管DLL。
因此,当第一个窗口上的文本框打开并且您已经打开了另一个窗口时,是否可以直接在任务栏上打开或打开该窗口(而WinForms文本框具有焦点) ?这可能是因为ScintillaNET做了一些我的情况所揭示的黑客行为。 – 2014-09-05 05:37:34
是的,ALT +选项卡和任务栏都正常工作。 – Loathing 2014-09-05 05:47:29
必须只是ScintillaNET做一些主机无法正确处理的奇怪东西。 – 2014-09-06 08:01:57