2013-01-04 41 views
1

我想做一個概念上很簡單的事情:對於每個接受鍵盤輸入(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」而沒有找到的窗口!

回答

0

再來一次,我解決了自己的問題:)

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)說給項目經理,這將是needded執行OSK時,必須通過安全令牌後.exe,他回答說這會在代碼中引入很複雜的一件非常簡單的事情,並且最好是應用程序可以以管理員模式運行:)

4)直到現在還沒有造成問題,所以讓它成爲: )

無論如何,感謝您的幫助。

+1

關於UI自動化的大書目:http://www.code-magazine.com/Milos_DocumentManagement_DownloadFileAttachment.aspx?id=5e886eaa-4381-4978-9590-9f487fa67acf – sergiol

-1

移動OSK窗口。通過命令提示最初將低完整性設置爲osk屏幕。那麼你使用movewindow函數。它生病了。