检测屏幕键盘是否打开(TabTip.exe)

我正在开发一个WPF / C#应用程序来填写表单。 我试图找到一种方法来确定TapTip键盘(用于Windows 8桌面的TabTip.exe /类似地铁的键盘)是否在Windows 8中最小化/不可见。

我已经能够检测到osk键盘(osk.exe / windows可访问性屏幕键盘)是否被最小化,但是相同的过程似乎不适用于TabTip键盘。

要检测键盘是否最小化,我:
1.找到键盘的过程
2.获取MainWindowHandle
3.使用WINDOWPLACEMENT的showCmd属性(使用MainWindowHandle找到)
4.使用showCmd值确定窗口是否最小化

我遇到的问题是:
– TabTip进程的MainWindowHandle为0(因此我无法使用它来查找WINDOWPLACEMENT信息)
– 当TabTip打开并最小化时,WINDOWPLACEMENT.showCmd的值相同

为了找到TabTip窗口的句柄,我使用ENUMWINDOWS来获取所有窗口句柄,使用GETWINDOWTHREADPROCESSID来获取进程ID,然后将id与TabTip进程id进行比较。

任何帮助都将不胜感激。 这也是我的第一篇文章。 我想我做对了,但如果没有,请让我知道如何解决它。

在找到一个有效的方法之前,我尝试了几种不同的方法 使用IsWindowVisible()不起作用,我对GetWindowPlacement()GetIconic()也没有任何乐趣。 最后我使用了GetWindowLong()并检查了WS_VISIBLE返回。 一个快速的控制台应用程序演示如下:

 using System; using System.Diagnostics; using Microsoft.Win32; using System.Runtime.InteropServices; using System.Threading; namespace CSharpTesting { class Program { ///  /// The window is initially visible. See http://msdn.microsoft.com/en-gb/library/windows/desktop/ms632600(v=vs.85).aspx. ///  public const UInt32 WS_VISIBLE = 0X94000000; ///  /// Specifies we wish to retrieve window styles. ///  public const int GWL_STYLE = -16; [DllImport("user32.dll")] public static extern IntPtr FindWindow(String sClassName, String sAppName); [DllImport("user32.dll", SetLastError = true)] static extern UInt32 GetWindowLong(IntPtr hWnd, int nIndex); static void Main(string[] args) { // Crappy loop to poll window state. while (true) { if (IsKeyboardVisible()) { Console.WriteLine("keyboard is visible"); } else { Console.WriteLine("keyboard is NOT visible"); } Thread.Sleep(1000); } } ///  /// Gets the window handler for the virtual keyboard. ///  /// The handle. public static IntPtr GetKeyboardWindowHandle() { return FindWindow("IPTip_Main_Window", null); } ///  /// Checks to see if the virtual keyboard is visible. ///  /// True if visible. public static bool IsKeyboardVisible() { IntPtr keyboardHandle = GetKeyboardWindowHandle(); bool visible = false; if (keyboardHandle != IntPtr.Zero) { UInt32 style = GetWindowLong(keyboardHandle, GWL_STYLE); visible = (style == WS_VISIBLE); } return visible; } } } 

这完全有效!

 // // BOOL IsVirtualKeyboardVisible() // // Returns TRUE if Virtual Keyboard/Input Pane is visible // Returns FALSE if Virtual Keyboard/Input Pane is not visible __declspec(dllexport) BOOL __cdecl IsVirtualKeyboardVisible() { BOOL bRet = FALSE; RECT InputPaneScreenLocation = { 0, 0, 0, 0 }; __try { HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); IFrameworkInputPane *IinputPane = NULL; if (SUCCEEDED(hr)) { // // http://msdn.microsoft.com/en-us/library/windows/desktop/hh706967(v=vs.85).aspx // hr = CoCreateInstance(__uuidof(FrameworkInputPane), 0, CLSCTX_ALL, __uuidof(IFrameworkInputPane), (LPVOID*)&IinputPane); IinputPane->Location(&InputPaneScreenLocation); if (InputPaneScreenLocation.bottom == 0 && InputPaneScreenLocation.left == 0 && InputPaneScreenLocation.right == 0 && InputPaneScreenLocation.top == 0) { // VKB is not visible bRet = FALSE; } else { // VKB is visible bRet = TRUE; } } } // try __finally { CoUninitialize(); } return bRet; } 

如果我没记错的话, TabTip.exe的窗口类名是IPTip_Main_Window 。 您可以使用Win32 API FindWindow来获取TabTip.exeHWND 。 这比使用窗口标题更可靠,并建议使用,因为某些窗口可以有空标题(或标题可以更改)。

使用EnumWindows当前方法可能存在缺陷,因为单个进程具有许多窗口(或具有子窗口的窗口)。 您可以使用Spy++类的工具来查找所需的实际窗口以及相应的类名。

您仍然可以使用GetWindowHandleThreadProcessId来检索此时的processID ,但我认为您不需要它来进行简单的窗口状态监视。

此外,尝试使用Win32 API而不是CLR中内置的任何API。 例如GetWindowPlacement

来自MSDN的说明:

此函数检索的WINDOWPLACEMENT标志成员始终为零。 如果hWnd参数标识的窗口最大化,则showCmd成员为SW_SHOWMAXIMIZED。 如果窗口最小化,showCmd为SW_SHOWMINIMIZED。 否则,它是SW_SHOWNORMAL。

希望有帮助,如果你还需要进一步的帮助,请留下评论,一旦我回到我的Win8机器,我将进行编辑。