Having trouble showing and hiding the Windows 10 On Screen Keyboard (osk.exe)

纵然是瞬间 提交于 2020-01-13 19:24:54

问题


I have been trying to get the onscreen keyboard (osk.exe) to appear (and disappear) on Windows 10 from within my app. My app was running fine in windows 7. Calling ShellExecute() on osk.exe would show the keyboard there but trying to get the same behaviour in Windows 10 has proved to be a pain.

To try to hide the keyboard, once it is visible, I tried this:

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

but that had no effect.

I also tried using the TabTip keyboard but was unable to detect when it is visible (I can detect when it's not visible but I can't get a handle to it when it is visible!).

Any help with this problem would be appreciated.

Update: The reason osk wasn't initially been shown was the 'nCmdShowparameter supplied toShellExecute`, the original code supplied NULL for this value and it was working fine on Windows 7 so I had assumed the problem lay elseware. changing it from NULL to SW_SHOWNORMAL fixed the issue with the keyboard appearing.

Comment by Paul Sanders: In a 32 bit app you have to do one more thing, see, see: https://stackoverflow.com/a/50510526/5743288.


回答1:


You can use IsWindowVisible function from WinAPI to determine if your hwnd is a visible window or not. Have you tried that? Checking and managing flags directly for such simple task is not the best idea

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




回答2:


I have decided to rewrite this answer, because the original contained a lot of irrelevant details, most of which were wrong. Now that I understand properly how it all actually works there's a lot less to say, and what there is to say should be a lot more useful to future visitors.

First up, the answer to the OP's question is here. That should let him do exactly what he wants to do. Kudos to @zett42 for pointing out the WM_SYSCOMMAND trick. Now for the interesting stuff.

Question 1: why does posting a WM_SYSCOMMAND message to osks main window work when calling ShowWindow(), as the OP was trying to do, does not?

Answer: Well, putting aside the fact that hiding the OSK rather than closing or minimising it is probably not a good idea anyway, the answer lies in something called UI Privilege Level Isolation (UIPI). OSK runs elevated and this limits the ways it can be manipulated by a regular app. You can read more about UIPI here.

For future reference, you can figure out if a program is running elevated using SysInternals' Process Explorer. If you look in the Security tab of the Process Properties window, then for OSK you see:

Flags: Integrity Group: Mandatory Label\ High Mandatory Label

while for (e.g.) the Settings app, you see:

Flags: Integrity Group: Mandatory Label\ Medium Mandatory Label

Question 2: Is any of this affected by the fact that OSK is a UWP app (see comments below by @IInspectable)?

Answer: Actually, no. The top-level HWND's of UWP apps appear to be just regular HWND's, although Microsoft don't want you to rely on that. You can investigate the exact window hierarchy they use - what there is of it - with Spy++ (and use the 64 bit version, lol).

Asides:

  1. OP, please try to write better questions. This one was a mess and it has caused a lot of trouble. I have edited your question by way of example and to clean it up for future visitors, please take a look. And please vote me up. I have earned it.

  2. People posting replies: please do a bit of research first. The other answers in this thread are not useful, partly (I would be the first to admit) because of the way the question was originally worded. I myself made this mistake in my initial comments so we can all learn from this.




回答3:


You are making a few errors:

  • in your if you use an assignment in stead of a test

  • in your SetWindowLongPtr you set only one bit and all existing flags are lost. You should use:

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

Note: The windows documentation says you must call SetWindowPos, not ShowWindow.



来源:https://stackoverflow.com/questions/50410958/having-trouble-showing-and-hiding-the-windows-10-on-screen-keyboard-osk-exe

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!