我想做一個概念上很簡單的事情:對於每個接受鍵盤輸入(CEdit,帶有可編輯文本的CCombobox等)的控件,當控件關注並啓用時,出現屏幕鍵盤。最好使用可訪問性支持(我已經閱讀了一些關於Microsoft User Interface Automation的內容),而不是直接調用osk.exe工具。聚焦可編輯控件時屏幕鍵盤上的MFC
當用戶將焦點放在可編輯控件上時,就像觸摸屏智能手機一樣。
更新:如果有一個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));
或者
後我無法移動OSK窗口。重要的是我可以移動它;否則,它會出現覆蓋集中控制,並且用戶看不到他給控制的輸入! 邊注:爲unminimizing 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
move 1
m ove 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」而沒有找到的窗口!
關於UI自動化的大書目:http://www.code-magazine.com/Milos_DocumentManagement_DownloadFileAttachment.aspx?id=5e886eaa-4381-4978-9590-9f487fa67acf – sergiol