C# 检查键盘是否唤醒到桌面上显示

大概需要的win32函数

public static extern IntPtr FindWindow(string lpClassName, string lpWindowName)
//返回值为具有指定类名和窗体名的窗体句柄
//软键盘的类名有很多,以IPTIP_Main_Window为例子
public static extern int GetWindowLong(IntPtr window, int index);
//用这个函数能够获得指定窗口的信息
//这里使用GWL_STYLE==-16, 得到窗口风格
public static extern IntPtr FindWindowEx(
            IntPtr hwndParent,
            IntPtr hwndChildAfter,
            string lpszClass,
            string lpszWindow);
//FindWindowEx是在窗口列表中寻找与指定条件相符的第一个子窗口

大概用到的常量

private const string CoreWindowClassName = "Windows.UI.Core.CoreWindow";
private const string ApplicationFrameHostClassName = "ApplicationFrameWindow";
private const string TextInputApplicationCaption = "Microsoft Text Input Application";
//最后一个是微软文本输入应用,其他不知道额
WS_EX_NOACTIVATE = 0x08000000;
WS_VISIBLE = 0x10000000;
//窗口不会变成前台窗口(Win2000)以上
//窗口可见(感觉这个才是重点)

具体细节

以下是本来判断是32还是64位的函数,但现在是判断这个句柄是否存在

private static bool IsValidHandle(IntPtr handle)
{
  return (IntPtr.Size == 4)
          ? (handle.ToInt32() > 0)
          : (handle.ToInt64() > 0);
 }

到这里,流程大概是完整了,也就是说判断软件键盘是否是窗口可见状态。

当然为了防止意外,在最后面也用以下的函数,不断的去询问窗口列表

private static IntPtr FindTextInputWindow()
{
    IntPtr lastProbed = IntPtr.Zero;
    do
    {
        lastProbed = Win32.FindWindowEx(IntPtr.Zero, lastProbed, ApplicationFrameHostClassName, null);
        if (IsValidHandle(lastProbed))
        {
            var textInput = Win32.FindWindowEx(lastProbed, IntPtr.Zero, CoreWindowClassName, TextInputApplicationCaption);
            return textInput;
        }
    } while (IsValidHandle(lastProbed));

    return IntPtr.Zero;
}

实际运用

有时候我们不知道键盘为什么起不来,但又想让它起来,这样通过以上的判断去发现键盘有没有显示在,没有就主动就唤醒

主要的代码,部分参数在另外的文件,需要自己添加哦

private static bool IsOpened()
{
    return IsWin10OnScreenKeyboardVisible();
}

private static bool IsWin10OnScreenKeyboardVisible()
{
    IntPtr handle = Win32.FindWindow(TabTipWindowClassName, "");
    if (!IsValidHandle(handle))
    {
        return false;
    }

    var isVisible = IsWindowVisibleByHandle(handle);
    if (isVisible.HasValue)
    {
        return isVisible.Value;
    }

    var textInputHandle = FindTextInputWindow();
    return IsValidHandle(textInputHandle);
}

private static bool IsValidHandle(IntPtr handle)
{
    return (IntPtr.Size == 4)
        ? (handle.ToInt32() > 0)
        : (handle.ToInt64() > 0);
}

private static bool? IsWindowVisibleByHandle(IntPtr handle)
{
    var style = Win32.GetWindowLong(handle, GwlStyle);

    if ((style & Win32.WS_EX_NOACTIVATE) != 0)
    {
        return false;
    }

    if ((style & Win32.WS_VISIBLE) != 0)
    {
        return true;
    }

    // DWM Window can be cloaked
    // see https://social.msdn.microsoft.com/Forums/vstudio/en-US/f8341376-6015-4796-8273-31e0be91da62/difference-between-actually-visible-and-not-visiblewhich-are-there-but-we-cant-see-windows-of?forum=vcgeneral
    if (Win32.DwmGetWindowAttribute(handle, DwmwaCloaked, out var cloaked, 4) == 0)
    {
        if (cloaked != 0)
        {
            return false;
        }
    }

    return null;
}

private static IntPtr FindTextInputWindow()
{
    IntPtr lastProbed = IntPtr.Zero;
    do
    {
        lastProbed = Win32.FindWindowEx(IntPtr.Zero, lastProbed, ApplicationFrameHostClassName, null);
        if (IsValidHandle(lastProbed))
        {
            var textInput = Win32.FindWindowEx(lastProbed, IntPtr.Zero, CoreWindowClassName, TextInputApplicationCaption);
            return textInput;
        }
    } while (IsValidHandle(lastProbed));

    return IntPtr.Zero;
}
原文地址:https://www.cnblogs.com/yinghualuowu/p/10167379.html