【问题标题】:Having trouble showing and hiding the Windows 10 On Screen Keyboard (osk.exe)无法显示和隐藏 Windows 10 屏幕键盘 (osk.exe)
【发布时间】:2018-05-18 12:04:07
【问题描述】:

我一直在尝试让屏幕键盘 (osk.exe) 在我的应用程序中的 Windows 10 上出现(和消失)。我的应用程序在 Windows 7 中运行良好。在 osk.exe 上调用 ShellExecute() 会显示那里的键盘,但尝试在 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 最初没有显示的原因是“nCmdShowparameter supplied toShellExecute”,原始代码为此值提供了 NULL,它在 Windows 7 上运行良好,所以我认为问题出在其他软件上.将其从 NULL 更改为 SW_SHOWNORMAL 修复了键盘出现的问题。

Paul Sanders 的评论:在 32 位应用程序中,您还必须做一件事,看,看:https://stackoverflow.com/a/50510526/5743288

【问题讨论】:

  • style &= WS_VISIBLE 是一个作业。这将永远是真的。如果要测试,请使用if (style & WS_VISIBLE)...
  • style &= WS_VISIBLE 并不总是返回 true,if 语句按预期工作
  • style &= WS_VISIBLE 表示style = style & WS_VISIBLE; if (style)...。你是对的,它可以工作,但是,你不能再使用style,因为它现在只有可见位(或者甚至没有)。
  • @Paul Oglivie,你是对的,这是遗留代码,我不完全理解这是清除样式值谢谢 :)
  • 这个问题的标题很糟糕。它应该类似于“如何在 Windows 10 中显示和隐藏屏幕键盘?”。请试着说出你的意思。看看它造成的所有麻烦。

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


【解决方案1】:

我决定重写这个答案,因为原来包含很多不相关的细节,其中大部分是错误的。既然我已经正确理解了这一切是如何运作的,那就没什么好说的了,要说的话应该对未来的访问者更有用。

首先,OP 问题的答案是here。那应该让他做他想做的事。感谢@zett42 指出WM_SYSCOMMAND 的技巧。现在来看看有趣的东西。

问题 1:为什么在调用 ShowWindow() 时向 osks 主窗口发布 WM_SYSCOMMAND 消息会起作用,就像 OP 试图做的那样,不是吗?

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

为了将来参考,您可以使用 SysInternals 的Process Explorer 确定程序是否正在运行提升。如果您查看“进程属性”窗口的“安全”选项卡,那么对于 OSK,您会看到:

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

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

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

问题 2:OSK 是 UWP 应用这一事实是否会影响上述情况(请参阅下面@IInspectable 提供的 cmets)?

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

旁白:

  1. OP,请尝试写better questions。这是一团糟,它造成了很多麻烦。我已经以示例的方式编辑了您的问题,并为将来的访问者清理它,请看一下。请投票给我。我赚到了。

  2. 发布回复的人:请先进行一些研究。该线程中的其他答案没有用,部分原因是(我将是第一个承认的)因为问题最初的措辞方式。我自己在最初的 cmets 中犯了这个错误,所以我们都可以从中吸取教训。

【讨论】:

【解决方案2】:

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

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

【讨论】:

  • IsWindowVisible 与从样式中检索位相同(这是 Windows 在此函数的底层所做的)。
  • 这就是为什么我们不应该重新发明轮毂 :) 但你是对的,我说过这可能会产生不同的结果,但它不应该 - 会编辑我的帖子。
  • @PaulOgilvie:不完全是。 IsWindowVisible 还检查父窗口的可见性,如documented。因此,在某些情况下可能需要测试样式位(尽管可能不在此处)。
  • 我不需要确定窗口是否可见,如果当前不可见,我想让它可见。 if 语句工作正常,当我尝试获取 TabTip 键盘窗口的句柄时,它在可见时失败,因此我无法调用 IsWindowVisible
  • @stuicidle 您确定您看到但无法通过代码检测到的键盘正是您要搜索的键盘吗?可见键盘的窗口类可能不同。玩一下 Inspect 应用程序(在 Windows 上探索 UI 结构的出色工具)msdn.microsoft.com/pl-pl/library/windows/desktop/…
【解决方案3】:

你犯了一些错误:

  • 如果你使用作业而不是测试

  • 在您的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

【讨论】:

  • 如果您无论如何都要显示窗口,那么设置样式位有点毫无意义......发布的原始代码有点混乱。
  • 还是错了,应该是style |= WS_VISIBLE。虽然正如之前的海报所写,但无论如何都没有意义。
  • 我也试过调用 SetWindowPos "SetWindowPos(wHandle, NULL, 0, 0, 100, 100, SWP_DRAWFRAME);"但这没有效果
  • 实际上(尽管上面有 IInspectable 的评论),不需要测试任何东西,只需显示窗口即可。如果它已经可见,则什么也不做。而且你不需要摆弄人们的风格!所以代码应该是(如果我们有一个有效的 HWND,显然我们没有):ShowWindow (wHandle, SW_SHOW); Honestly.
  • @PaulSanders:Windows 10 屏幕键盘是一个 UWP 应用程序。 UWP 应用程序可见性通过关联的HWND 控制。不幸的是,微软还没有彻底记录HWNDs 在 UWP 应用程序中扮演的角色。我相信它们仅限于输入处理,以及作为广播消息的目标。但仅此而已。
猜你喜欢
  • 2013-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多