无法显示和隐藏Windows 10屏幕键盘(osk.exe)

时间:2018-05-18 12:04:08

标签: c++ c winapi on-screen-keyboard

我一直试图让屏幕键盘(osk.exe)在我的应用程序中出现(并消失)在Windows 10上。我的应用程序在Windows 7中正常运行。在ShellExecute()上调用osk.exe会在那里显示键盘,但尝试在Windows 10中获得相同的行为已经证明是一种痛苦。

尝试隐藏键盘,一旦可见,我就试过了:

HANDLE wHandle = FindWindowW(L"OSKMainClass", L"On-Screen Keyboard");
if (wHandle != NULL)
{
    long style = GetWindowLong(wHandle, GWL_STYLE);
    if (style & WS_VISIBLE)
    {
        return TRUE;
    }
    else
    {
        SetWindowLongPtr(wHandle, GWL_STYLE, WS_VISIBLE);
    }

但这没有效果。

我也尝试使用TabTip keyboard,但无法检测到它何时可见(我可以检测到它 不可见但是我无法获得当它可见时处理它!)。

对此问题的任何帮助都将不胜感激。

更新:osk最初未显示的原因是' nCmdShow parameter supplied to ShellExecute`,原始代码为此值提供了NULL,它在Windows上正常运行7所以我假设问题是搁置的。将它从NULL更改为SW_SHOWNORMAL修复了出现键盘的问题。

Paul Sanders的评论:在32位应用程序中,您还需要做一件事,请参阅:https://stackoverflow.com/a/50510526/5743288

3 个答案:

答案 0 :(得分:2)

您可以使用WinAPI中的IsWindowVisible函数来确定您的hwnd是否是可见窗口。你试过吗?直接为这样简单的任务检查和管理标志不是最好的主意

https://msdn.microsoft.com/en-us/library/windows/desktop/ms633530(v=vs.85).aspx

答案 1 :(得分:2)

我决定重写这个答案,因为原文包含了很多不相关的细节,其中大部分是错误的。现在我已经正确地理解它实际上是如何运作的,而且说的话要少得多,而且对未来的访问者来说应该说的更有用。

首先,OP问题的答案是here。这应该让他完全按照自己的意愿行事。感谢@ zett42指出WM_SYSCOMMAND技巧。现在是有趣的东西。

问题1:为什么在调用WM_SYSCOMMAND时向osk主窗口发布ShowWindow()消息,正如OP试图做的那样,不?

答案:好吧,撇开隐藏OSK而不是关闭或最小化它的事实可能不是一个好主意,答案在于UI Privilege Level Isolation(UIPI)。 OSK运行升级,这限制了常规应用操作的方式。您可以阅读有关UIPI here的更多信息。

为了将来参考,您可以使用SysInternals'来判断程序是否正在运行。 Process Explorer。如果查看Process Properties窗口的Security选项卡,那么对于OSK,您会看到:

标志:诚信组:强制性标签\ 强制性标签

而对于(例如)设置应用,您会看到:

标志:诚信组:强制性标签\ 中等强制性标签

问题2: OSK是否属于UWP应用程序会影响其中任何一项(请参阅@IInspectable下面的评论)?

答案:实际上,没有。 UWP应用程序的顶级HWND似乎只是普通的HWND,尽管是Microsoft don't want you to rely on that。您可以使用Spy++(和use the 64 bit version, lol)调查他们使用的确切窗口层次结构 - 它的含义。

旁白:

  1. OP,请尝试编写better questions。这个是一团糟,它造成了很多麻烦。我已经通过示例编辑了您的问题并为将来的访问者进行了清理,请查看。请投票给我。我已经获得了它。

  2. 发布回复的人:请先做一些研究。这个帖子中的其他答案没有用,部分(我会是第一个承认的),因为问题最初的措辞方式。我自己在最初的评论中犯了这个错误,所以我们都可以从中学习。

答案 2 :(得分:0)

你犯了一些错误:

  • 如果您使用作业而不是考试

  • {li>

    SetWindowLongPtr中只设置了一位,所有现有标志都丢失了。你应该使用:

       long style = GetWindowLong(wHandle, GWL_STYLE);
        if (style & WS_VISIBLE) // test
        {
            return TRUE;
        }
        else
        {
            style |= WS_VISIBLE; // set the bit
            SetWindowLongPtr(wHandle, GWL_STYLE, style); // set the new style
            ShowWindow(wHandle, SW_SHOWDEFAULT);
        }
    

注意:Windows文档说明您必须致电SetWindowPos,而不是ShowWindow