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

C# 检测屏幕键盘是否打开(TabTip.exe),c#,windows-8,keyboard,touch,on-screen-keyboard,C#,Windows 8,Keyboard,Touch,On Screen Keyboard,我正在准备一份WPF/C申请表以完成表格。我正在试图找到一种方法来确定TapTip键盘(TabTip.exe/metro-like keyboard for windows 8 desktop)在windows 8中是否最小化/不可见 我已经能够检测到osk键盘(osk.exe/windows可访问性屏幕键盘)是否最小化,但TabTip键盘似乎无法执行相同的过程 要检测键盘是否最小化,请执行以下操作: 1.查找键盘的进程 2.获取主窗口句柄 3.使用WINDOWPLACEMENT的showCmd

我正在准备一份WPF/C申请表以完成表格。我正在试图找到一种方法来确定TapTip键盘(TabTip.exe/metro-like keyboard for windows 8 desktop)在windows 8中是否最小化/不可见

我已经能够检测到osk键盘(osk.exe/windows可访问性屏幕键盘)是否最小化,但TabTip键盘似乎无法执行相同的过程

要检测键盘是否最小化,请执行以下操作:
1.查找键盘的进程
2.获取主窗口句柄
3.使用WINDOWPLACEMENT的showCmd属性(使用MainWindowHandle找到)
4.使用showCmd值确定窗口是否最小化

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

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


在此方面的任何帮助都将不胜感激。这也是我的第一篇文章。我认为我做得对,但如果没有,请告诉我如何修复它。

如果我没记错的话,
TabTip.exe
的窗口类名是
IPTip\u Main\u window
。您可以使用Win32 API获取
TabTip.exe的
HWND
。这比使用窗口标题更可靠,建议使用,因为某些窗口的标题可能为空(或者标题可能会更改)

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

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

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

来自MSDN的注释:

此函数检索到的WINDOWPLACEMENT的flags成员为 总是零。如果hWnd参数标识的窗口为 最大化,showCmd成员为SW_showmized。如果窗户是 最小化,showCmd为SW_showcmdimized。否则就是 SW_SHOWNORMAL

希望这对您有所帮助,如果您还需要进一步的帮助,请留下评论,我将在回到Win8机器后进行编辑。

这完全有效

//
// 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;
}

在找到一种有效的方法之前,我尝试了几种不同的方法。使用
IsWindowVisible()。最后,我使用了
GetWindowLong()
并检查了返回的
WS\u 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;
        }
    }
}
使用系统;
使用系统诊断;
使用Microsoft.Win32;
使用System.Runtime.InteropServices;
使用系统线程;
命名空间测试
{
班级计划
{
/// 
///窗口最初可见。请参见http://msdn.microsoft.com/en-gb/library/windows/desktop/ms632600(v=vs.85)。
/// 
公共警察32 WS_可见=0X94000000;
/// 
///指定要检索的窗口样式。
/// 
公共const int GWL_STYLE=-16;
[DllImport(“user32.dll”)]
公共静态外部IntPtr FindWindow(字符串sClassName,字符串sAppName);
[DllImport(“user32.dll”,SetLastError=true)]
静态外部UInt32 GetWindowLong(IntPtr hWnd、int nIndex);
静态void Main(字符串[]参数)
{
//轮询窗口状态的糟糕循环。
while(true)
{
如果(IsKeyboardVisible())
{
Console.WriteLine(“键盘可见”);
}
其他的
{
Console.WriteLine(“键盘不可见”);
}
睡眠(1000);
}
}
/// 
///获取虚拟键盘的窗口处理程序。
/// 
///把手。
公共静态IntPtr GetKeyboardWindowHandle()
{
返回FindWindow(“IPTip_主窗口”,null);
}
/// 
///检查虚拟键盘是否可见。
/// 
///如果可见,则为True。
公共静态bool IsKeyboardVisible()
{
IntPtr keyboardHandle=GetKeyboardWindowHandle();
bool可见=错误;
if(键盘手柄!=IntPtr.Zero)
{
UInt32样式=GetWindowLong(键盘手柄,GWL_样式);
可见=(样式==WS_可见);
}
返回可见;
}
}
}

感谢您的快速回复。我按照你的建议改用了FindWindow。然后,我使用Spy++验证是否找到了正确的窗口。不幸的是,在使用GetWindowPlacement时,当键盘进程被终止时,showCmd的值只有0(SW_HIDE)。其余时间showCmd的值为1(SW_NORMAL),无论它是否可见。我还尝试使用GetWindowRect查看窗口是否在屏幕外被“隐藏”。当不可见时,返回的坐标与屏幕上最后一个可见的位置相同。你知道吗?两种方法我都试过,但似乎都不管用。我认为TabTip.exe是一个与服务相结合的特殊进程,因此检测hwnd是否最小化/关闭的标准方法似乎不起作用。我从来没有机会进一步研究它,对不起!好的,我可以确认您可以使用FindWindow来确定TabTip是否已经在运行。但是如果它正在运行并且