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

use*_*ser 10 c# keyboard touch on-screen-keyboard windows-8

我正在开发一个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进行比较.

任何帮助都将不胜感激.这也是我的第一篇文章.我想我做得对,但如果没有,请告诉我如何解决它.

Bar*_*rie 12

在找到一个有效的方法之前我尝试了几种不同的方法.使用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
    {
        /// <summary>
        /// The window is initially visible. See http://msdn.microsoft.com/en-gb/library/windows/desktop/ms632600(v=vs.85).aspx.
        /// </summary>
        public const UInt32 WS_VISIBLE  = 0X94000000;
        /// <summary>
        /// Specifies we wish to retrieve window styles.
        /// </summary>
        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);
            }
        }

        /// <summary>
        /// Gets the window handler for the virtual keyboard.
        /// </summary>
        /// <returns>The handle.</returns>
        public static IntPtr GetKeyboardWindowHandle()
        {
            return FindWindow("IPTip_Main_Window", null);
        }

        /// <summary>
        /// Checks to see if the virtual keyboard is visible.
        /// </summary>
        /// <returns>True if visible.</returns>
        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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • style是一个长类型位模式,用于保存N个样式设置标志,因此如果您想知道是否设置了WS_VISIBLE标志,请使用&bit运算符:"style&WS_VISIBLE" (2认同)

Eri*_*rik 1

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

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

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

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

MSDN 注释:

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

希望对您有所帮助,如果您仍然需要进一步的帮助,请发表评论,我会在回到我的 Win8 机器后进行编辑。