MFC на экранной клавиатуре при фокусировке редактируемого элемента управления

Я хочу сделать концептуально простую вещь: для каждого элемента управления, который принимает ввод с клавиатуры (CEdit, CCombobox с редактируемым текстом и т. Д.), Когда элемент управления сфокусирован и включен, заставьте появиться экранную клавиатуру. Желательно с поддержкой специальных возможностей (я кое-что читал об автоматизации пользовательского интерфейса Microsoft), а не напрямую вызывать утилиту osk.exe.

Вещь очень похожа на смартфоны с сенсорным экраном, когда пользователь делает акцент на редактируемом элементе управления.

ОБНОВЛЕНИЕ: если есть опция Windows, которая может заставить экранную клавиатуру вести себя так, как я описываю, это прекрасно!

ОБНОВЛЕНИЕ 2: То, что я хочу, похоже на http://msdn.microsoft.com/en-us/library/windows/apps/hh465404.aspx, но в Windows 7.

Я проводил эксперименты с классом IUIAutomation, вызывая непосредственно osk.exe при фокусировке редактируемого элемента управления и закрывая это окно при фокусировке нередактируемого элемента.

Но у меня все еще есть три проблемы:

1) При открытии CFileDialog перестает отвечать на запросы. То же самое происходит только с другим модальным диалогом приложения (в каждом другом модальном диалоге все работает нормально). Я обнаружил, что CFileDialog открывает некоторые фоновые потоки, а также мой единственный проблемный модальный файл. Я подозреваю, что это связано с проблемами потоковой передачи.

2) Когда какой-либо другой элемент управления находится в фокусе, и после этого я нажимаю кнопку DropDown в поле со списком CBS_DROPDOWN, не выбирая его элемент управления редактированием, я вижу, как появляется и исчезает мигание OSK. Используя Spy ++ и UIA Inspect, у меня возникло подозрение, что редактирование текста сфокусировано до того, как поле со списком перейдет в состояние сброса.

3) После экспериментов с SetWindowPos, MoveWindow

::MoveWindow(osk_wnd->m_hWnd, LeftOsk, TopOsk, -1, -1, FALSE);

Or

osk_wnd->SetWindowPos(NULL, LeftOsk, TopOsk, -1, -1, SWP_NOSIZE | SWP_NOACTIVATE);

а также некоторые эксперименты по обработке сообщений, например

//osk_wnd is a CWnd* variable that represents OSK main window
osk_wnd->PostMessage(WM_SYSCOMMAND, SC_MOVE + HTCAPTION, MAKELPARAM(point.x, point.y));

Or

POINT       point       = {0};

GetCursorPos(&point);
SendMessage(osk_wnd->m_hWnd, WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x, point.y));

SendMessage(osk_wnd->m_hWnd, WM_NCMOUSEMOVE, HTCAPTION, MAKELPARAM(LeftOsk, TopOsk));

GetCursorPos(&point);
SendMessage(osk_wnd->m_hWnd, WM_NCLBUTTONUP, HTCAPTION, MAKELPARAM(LeftOsk + point.x, TopOsk + point.y));

Я не мог переместить окно OSK. Важно, что я могу его переместить; в противном случае он будет закрывать сфокусированный элемент управления, и пользователь не сможет увидеть ввод, который он передает элементу управления! Боковое примечание: следующий код для отмены минимизации окна OSK работал отлично:

if(osk_wnd->IsIconic())
    osk_wnd->PostMessage(WM_SYSCOMMAND, SC_RESTORE, NULL);

Даже попытка переместить это окно с помощью этого скрипта AutoIt ничего не дала:

If WinActivate("[CLASS:OSKMainClass]") Then

   If WinWaitActive("[CLASS:OSKMainClass]") Then

      ConsoleWrite("activ" & @CRLF)

      Sleep(500)

      If WinMove("[CLASS:OSKMainClass]", "", 30 ,320,360,123) Then
         ConsoleWrite("move 1" & @CRLF)
      EndIf
   EndIf
EndIf

If WinMove("[CLASS:OSKMainClass]", "", 30 ,320,360,123) Then
   ConsoleWrite("move 2" & @CRLF)
EndIf

Я вижу текст

актив

ход 1

ход 2

печатается, но окно OSK никуда не перемещается. Возможно, он активно отвергает инструкции по размещению.

Я пробовал этот скрипт AutoIt для перемещения окна Tabtip.exe, но он тоже не работает. Я пробовал этот сценарий для перемещения окна командной строки Visual Studio, и оно перемещается! ГРРРРР!

ОБНОВЛЕНИЕ 3: Мне кажется, это связано с контролем доступа и разрешениями пользователей. Если я отключу контроль доступа пользователей или запустил приложение от имени администратора, инструкция MoveWindow будет работать отлично! То же самое относится к AutoIt, пытающемуся переместить окно OSKMainCLASS! Итак, есть ли в Windows 7 какая-то локальная или групповая политика, которая позволяет мне сделать исключение для приложения OSK?

4) Для запуска osk.exe в 64-битной операционной системе я пробовал все, что не заставляло отключать перенаправление SysWOW64, но мне не удалось от него уйти. До сих пор я не видел никаких проблем, но, возможно, следующий код вызовет проблемы в будущем.

const int sysDirNameSize= 1024;
TCHAR sysDir[sysDirNameSize];
if( !GetSystemDirectory( sysDir,  sysDirNameSize) )
{
    ASSERT(FALSE);
    return;
}

CString osk_path = CString(sysDir) + _T("\\osk.exe");
PVOID pOldValue = NULL;
BOOL bRes= Wow64DisableWow64FsRedirection(&pOldValue);
::ShellExecute(NULL, NULL, osk_path, _T("") , sysDir, SW_SHOW);
if(bRes)
    Wow64RevertWow64FsRedirection(pOldValue);

ОБНОВЛЕНИЕ 5: Кажется, в прошлый раз, когда я пытался запустить osk.exe, процесс начинается, но его окно не появляется! Чтобы присвоить значение osk_wnd, у меня есть функция, которая просматривает все окна GW_CHILD в CWnd :: GetDesktopWindow () для поиска того, у которого GetClassName (...) является "OSKMainClass", и ничего не найдено!


person sergiol    schedule 04.01.2013    source источник


Ответы (2)


Еще раз решил проблему сам :)

1) После прочтения http://social.msdn.microsoft.com/Forums/br/windowsaccessibilityandautomation/thread/aee0be4d-2cf5-45e7-8406-2de3e5d0af03 и http://www.c-plusplus.de/forum/285011-full (немецкий, но переводчик Google может помочь), я решил вынести связанный с ним код в отдельную ветку . Больше никаких зависаний при открытии окон CFileDialog :)

2) Менеджер проекта сказал, что это небольшая проблема :)

3) Сказав менеджеру проекта, что при запуске osk.exe потребуется передать токен безопасности, он ответил, что это значительно усложнит код для очень простой вещи, и желательно, чтобы приложение могло запускаться в админке. Режим :)

4) Не доставляет проблем до сих пор, пусть будет :)

В любом случае спасибо за помощь.

person sergiol    schedule 08.02.2013
comment
Отличная библиография по автоматизации пользовательского интерфейса: code -nofollow noreferrer magazine. ru / - person sergiol; 13.02.2013

Для перемещения окна OSK. Изначально установите низкую целостность для экрана osk с помощью командной строки. тогда вы используете функцию movewindow. это плохо работает.

person Rangaraj    schedule 11.09.2017