当聚焦可编辑控制时,MFC在屏幕键盘上

时间:2013-01-04 13:13:28

标签: mfc controls onfocus on-screen-keyboard

我想做一个概念上简单的事情:对于每个接受键盘输入的控件(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组合框的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

我看到了文字

ACTIV

移动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”且没有找到的窗口!

2 个答案:

答案 0 :(得分:0)

再一次,我自己解决了这个问题:)

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

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

3)在向项目经理说要在执行osk.exe时需要传递安全令牌之后,他回答说这会在代码中引入很多复杂的东西,并且最好是应用程序可以以管理员模式运行:)

4)直到现在都没有引起问题,所以让它成为:)

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

答案 1 :(得分:-1)

用于移动OSK窗口。最初通过命令提示符将低完整性设置为osk屏幕。然后你使用movewindow功能。它生病了。