聚焦可编辑控件时屏幕键盘上的MFC [英] MFC on screen keyboard when focusing editable control

查看:132
本文介绍了聚焦可编辑控件时屏幕键盘上的MFC的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想做一个概念上很简单的事情:对于每个接受键盘输入的控件(CEdit,带有可编辑文本的CCombobox等),在焦点对准并启用该控件时,使屏幕键盘"出现.最好具有可访问性支持(我已经阅读了一些有关Microsoft用户界面自动化的文章),而不是直接调用osk.exe实用程序.

I want to do a thing conceptually simple as this: For every control that accepts keyboard input(CEdit, CCombobox with Editable text, etc.), when the control is focused and enabled, make the On Screen Keyboard appear. Preferably with accessibility support (I've done some reading about Microsoft User Interface Automation) rather than calling directly the osk.exe utility.

当用户将焦点放在可编辑控件上时,就非常类似于触摸屏智能手机.

A thing very like the touchscreen smartphones when the user puts the focus on an editable control.

更新:如果有Windows选项可以使屏幕键盘"按照我描述的方式运行,那就好了!

UPDATE: If there is a Windows option that can make the On Screen Keyboard to behave the way I describe that's just fine!

更新2:我想要的东西类似于 http: //msdn.microsoft.com/zh-CN/library/windows/apps/hh465404.aspx ,但在Windows 7中使用.

UPDATE 2: The thing I want is similar to http://msdn.microsoft.com/en-us/library/windows/apps/hh465404.aspx , but in Windows 7.

我已经用IUIAutomation类做过实验,在聚焦可编辑控件时直接调用osk.exe,而在聚焦不可编辑控件时关闭该窗口.

I had done experiments with the IUIAutomation class, calling directly osk.exe when focusing an editable control, and closing that window when focusing a non-editable one.

但是,我仍然有三个问题:

But, I still have three problems:

1)打开CFileDialog应用程序时,它无响应.仅应用程序的另一个模态对话框"发生了相同的情况(在其他每个模态对话框"中,一切正常.)我发现CFileDialog打开了一些后台线程,也是我唯一有问题的模式.我怀疑这与线程问题有关.

1) When opening a CFileDialog application becomes unresponsive. The same is happening for only another Modal Dialog of the application (in every other Modal Dialog everything works fine). I discovered that CFileDialog opens some background threads and my only problematic modal too. I suspect this has to do with threading issues.

2)当其他某个控件处于焦点位置之后,此后我直接单击CBS_DROPDOWN组合框的DropDown按钮,而不是选择其编辑控件,则看到闪烁的OSK消失了.使用Spy ++和UIA Inspect,我怀疑文本编辑在组合框进入放置状态之前就被集中了.

2) When some other control is focused, and thereafter I click directly the DropDown button of a CBS_DROPDOWN combobox, not picking on its edit control, I see a flash of OSK appear and disappear. Using Spy++ and UIA Inspect I got the suspicion of the text edit being focused before the combobox goes to the dropped state.

3)在使用SetWindowPos,MoveWindow做一些实验之后

3) After doing some experiments with SetWindowPos, MoveWindow

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

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

并使用一些消息处理实验,例如

and using also some message processing experiments like

//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窗口的代码非常有效:

I could not move the OSK window. It is important that I can move it; otherwise, it will appear covering the focused control, and the user can not see the input he is giving to the control! Side note: the following code for unminimizing OSK window worked perfectly:

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

即使尝试使用此AutoIt脚本移动该窗口也没有执行任何操作:

Even trying to move that window with this AutoIt script did nothing:

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窗口没有被移到任何地方.也许它正在积极拒绝定位指令.

being printed, but the OSK window is not being moved to anywhere. Maybe it is actively rejecting posiotioning instructions.

我尝试使用此AutoIt脚本移动Tabtip.exe窗口,但它也失败.我尝试使用此脚本移动Visual Studio命令提示符的窗口,并且该窗口也移动了! GRRRRR!

I tried this AutoIt script to move the Tabtip.exe Window and it also fails. I tried this script to move the Visual Studio Command Prompt's Window and it moves! GRRRRR!

更新3:在我看来,这与用户访问控制和权限有关.如果我禁用用户访问控制或以管理员身份运行该应用程序,则MoveWindow指令会完美运行!这同样适用于试图移动OSKMainCLASS窗口的AutoIt!因此,Windows 7中是否有一些本地或组策略允许我对OSK应用程序进行例外处理?

UPDATE 3: Seems to me this thing has to do with User Access Control and Permissions. If I disable User Access Control or run the application as Administrator the MoveWindow instruction works perfectly! The same applies to AutoIt trying to move OSKMainCLASS window! So, is there some Local or group policy in Windows 7 that allow me to make an exception to the OSK application?

4)为了使osk.exe在64位操作系统上运行,我尝试了所有不强制禁用SysWOW64重定向的操作,但我无法摆脱.到现在为止,我还没有发现任何问题,但是下面的代码将来可能会引起问题.

4) For getting the osk.exe running on 64 bit operating system I tried everything that didn't force to disable the SysWOW64 redirection, but I could not escape from it. Till now, I did not see any problems, but maybe the following code will cause problems in the future.

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"且找不到任何窗口!

UPDATE 5: Seems last times I tried to execute osk.exe the process begins, but its window doesn't appear! To attribute the value to osk_wnd, I have a function that traverses all GW_CHILD windows of the CWnd::GetDesktopWindow() to search the one which GetClassName(...) is "OSKMainClass" and none is found!

推荐答案

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

One more time, I solved the problem by myself :)

1)阅读 http: //social.msdn.microsoft.com/Forums/br/windowsaccessibilityandautomation/thread/aee0be4d-2cf5-45e7-8406-2de3e5d0af03

1) After reading http://social.msdn.microsoft.com/Forums/br/windowsaccessibilityandautomation/thread/aee0be4d-2cf5-45e7-8406-2de3e5d0af03 and http://www.c-plusplus.de/forum/285011-full (German, but Google translator can help), I decided to put the code related on a separate thread. No more hanging when opening CFileDialog windows :)

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

2) Project manager said that this is a minor problem :)

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

3) After saying to Project manager that it would be needded to pass a security token when executing osk.exe, he replied that that would introduce much complexity in the code for a very simple thing, and it is preferable that application can run in admin mode :)

4)直到现在都不会引起问题,所以就让它成为:)

4) Not causing problems till now, so let it be :)

无论如何,谢谢您的帮助.

Anyway, thanks for help.

这篇关于聚焦可编辑控件时屏幕键盘上的MFC的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆