Возникли проблемы с отображением и скрытием экранной клавиатуры Windows 10 (osk.exe)

Я пытался получить экранную клавиатуру (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 но не смог обнаружить когда он виден (я могу определить когда это не видимый, но я не могу получить ручку, когда он виден!).

Любая помощь с этой проблемой будет оценена.

Обновление: причина osk изначально не был показан был ‘nCmdShowparameter supplied toShellExecute`, исходный код предоставил NULL для этого значения, и он прекрасно работал в Windows 7, поэтому я предположил, что проблема заключается в другом программном обеспечении. изменение его с NULL на SW_SHOWNORMAL решило проблему с появлением клавиатуры.

Комментарий Пола Сандерса: В 32-битном приложении вы должны сделать еще одну вещь, смотрите, смотрите: https://stackoverflow.com/a/50510526/5743288.

0

Решение

Ты можешь использовать IsWindowVisible Функция из WinAPI, чтобы определить, является ли ваш hwnd видимым окном или нет. Вы пробовали это? Проверка флагов и управление ими напрямую для такой простой задачи — не лучшая идея

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

2

Другие решения

Я решил переписать этот ответ, потому что оригинал содержал много не относящихся к делу деталей, большинство из которых были неверными. Теперь, когда я правильно понимаю, как все это на самом деле работает, можно сказать гораздо меньше, и то, что можно сказать, должно быть гораздо более полезным для будущих посетителей.

Во-первых, ответ на вопрос ОП: Вот. Это должно позволить ему делать именно то, что он хочет. Слава @ zett42 за указание на WM_SYSCOMMAND трюк. Теперь о интересных вещах.

Вопрос 1: почему размещение WM_SYSCOMMAND сообщение для oskГлавное окно работает при звонке ShowWindow(), как ОП пытался сделать, не так ли?

Ответ: Ну, если оставить в стороне тот факт, что скрывать OSK вместо того, чтобы закрывать или сворачивать его, в любом случае, вероятно, не очень хорошая идея, ответ заключается в чем-то, что называется UI Privilege Level Isolation (МСНС). OSK работает с повышенными правами, и это ограничивает способы, которыми оно может управляться обычным приложением. Вы можете прочитать больше о UIPI Вот.

Для дальнейшего использования вы можете выяснить, работает ли программа с повышенными правами, используя SysInternals. Process Explorer. Если вы посмотрите на вкладку «Безопасность» окна «Свойства процесса», то для OSK вы увидите:

Флаги: Целостность Группа: Обязательные этикетки \ Высоко Обязательный ярлык

в то время как для (например) приложения Настройки вы видите:

Флаги: Целостность Группа: Обязательные этикетки \ Средняя Обязательный ярлык

Вопрос 2: На это влияет тот факт, что OSK такое приложение UWP (см. комментарии ниже @IInspectable)?

Ответ: На самом деле нет. HWND верхнего уровня приложений UWP кажутся просто обычными HWND, хотя Microsoft не хочу, чтобы вы полагались на это. Вы можете исследовать точную иерархию окон, которую они используют, — что там с ней — Spy ++ (а также использовать 64-битную версию, лол).

Asides:

  1. ОП, пожалуйста, попробуйте написать лучшие вопросы. Этот был беспорядок, и это вызвало много неприятностей. Я отредактировал ваш вопрос в качестве примера и, чтобы очистить его для будущих посетителей, пожалуйста, посмотрите. И пожалуйста проголосуй за меня. Я заработал это.

  2. Люди, публикующие ответы: сначала сделайте небольшое исследование. Другие ответы в этой теме бесполезны, отчасти (я бы первым признал) из-за того, как вопрос был изначально сформулирован. Я сам допустил эту ошибку в своих первоначальных комментариях, чтобы мы все могли извлечь уроки из этого.

2

Вы делаете несколько ошибок:

  • в вашем, если вы используете задание вместо теста

  • в вашем 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,

0
По вопросам рекламы [email protected]