我有一個文本框控件在我的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