【问题标题】:MFC on screen keyboard when focusing editable control聚焦可编辑控件时屏幕键盘上的 MFC
【发布时间】:2012-12-18 22:27:01
【问题描述】:

我想做一件在概念上很简单的事情:对于每个接受键盘输入的控件(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) 当某个其他控件获得焦点时,然后我直接单击 CBS_DROPDOWN 组合框的下拉按钮,而不是选择其编辑控件,我看到 OSK 出现和消失。使用 Spy++ 和 UIA Inspect,我怀疑文本编辑在组合框进入删除状态之前被聚焦。

3) 用SetWindowPos做了一些实验后,MoveWindow

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

或者

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

或者

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 命令提示符的窗口,它移动了! GRRRRR!

更新 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,我有一个函数可以遍历 CWnd::GetDesktopWindow() 的所有 GW_CHILD 窗口,以搜索 GetClassName(...) 为“OSKMainClass”但没有找到的那个!

【问题讨论】:

    标签: mfc controls onfocus on-screen-keyboard


    【解决方案1】:

    又一次,我自己解决了问题:)

    1) 在阅读了http://social.msdn.microsoft.com/Forums/br/windowsaccessibilityandautomation/thread/aee0be4d-2cf5-45e7-8406-2de3e5d0af03http://www.c-plusplus.de/forum/285011-full(德语,但谷歌翻译可以提供帮助)之后,我决定将相关代码放在单独的线程上。打开 CFileDialog 窗口时不再挂起 :)

    2) 项目经理说这是小问题:)

    3) 在跟项目经理说在执行 osk.exe 时需要传递一个安全令牌后,他回答说对于一个非常简单的事情,这会在代码中引入很多复杂性,最好应用程序可以以管理员模式运行:)

    4) 直到现在都没有引起问题,就这样吧:)

    无论如何,谢谢你的帮助。

    【讨论】:

    【解决方案2】:

    用于移动 OSK 窗口。最初通过命令提示将低完整性设置为 osk 屏幕。然后你使用movewindow函数。效果不好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-21
      • 2019-09-13
      • 2014-04-26
      • 2012-03-07
      • 2018-03-03
      • 2014-01-27
      相关资源
      最近更新 更多