有没有办法检测即使我的应用程序不在焦点时windows / os语言是否也发生了变化?
到目前为止,只有在应用程序集中使用时,我才能实现我想要的目标:
string language = "";
System.Windows.Input.InputLanguageManager.Current.InputLanguageChanged +=
new System.Windows.Input.InputLanguageEventHandler((sender, e) =>
{
language = e.NewLanguage.DisplayName;
MessageBox.Show(language);
});
但是你可以理解,这不是我想要的......
我正在考虑其他解决方案,例如挂钩更改语言的键(例如alt + shift)但我无法知道当前使用的是哪种语言,用户可以更改默认热键... < / p>
非常感谢您的帮助。
答案 0 :(得分:9)
您遇到的问题与WM_INPUTLANGCHANGE消息的工作方式有关。此消息由操作系统发送到程序,以通知它们语言更改。但是,根据documentation,此消息仅发送到“最受影响的窗口”。这意味着您甚至可以调用本机方法 GetKeyboardLayout (顺便使用 InputLanguageManager )但是如果应用程序不活动 GetKeyboardLayout 将永远返回最后已知的,过时的语言。
考虑到这一点,使用@VDohnal指向的解决方案可能是一个好主意,即找到当前最顶层的窗口并读取它的键盘布局。以下是如何在WPF应用程序中执行此操作的概念的快速证明。我使用了一个额外的线程,周期性地找到它的最顶层窗口和就绪键盘布局。代码远非完美,但它可以工作,它可以帮助您实现自己的解决方案。
public partial class MainWindow : Window
{
[DllImport("user32.dll")]
static extern IntPtr GetKeyboardLayout(uint idThread);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr processId);
private CultureInfo _currentLanaguge;
public MainWindow()
{
InitializeComponent();
Task.Factory.StartNew(() =>
{
while (true)
{
HandleCurrentLanguage();
Thread.Sleep(500);
}
});
}
private static CultureInfo GetCurrentCulture()
{
var l = GetKeyboardLayout(GetWindowThreadProcessId(GetForegroundWindow(), IntPtr.Zero));
return new CultureInfo((short)l.ToInt64());
}
private void HandleCurrentLanguage()
{
var currentCulture = GetCurrentCulture();
if (_currentLanaguge == null || _currentLanaguge.LCID != currentCulture.LCID)
{
_currentLanaguge = currentCulture;
MessageBox.Show(_currentLanaguge.Name);
}
}
}