您面临的问题与 WM_INPUTLANGCHANGE 消息的工作方式有关。此消息由操作系统发送给程序,以通知它们有关语言的更改。但是,根据文档,此消息仅发送到“最受影响的窗口”。这意味着您甚至可以调用本机方法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);
}
}
}