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 to
ShellExecute`, 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.
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
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 osk
s 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:
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.
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.
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