2011-11-21 65 views
0

WIndows API中的兩個鍵狀態函數GetKeyState()GetAsyncKeyState()都基於密鑰上/下消息而不是密鑰的物理狀態來確定密鑰狀態。物理密鑰狀態

我正在處理輸入的程序,使用SendInput()釋放修改鍵(alt,ctrl等等),發送輸入,然後重新按下修改鍵。

問題是,我不知道在發送輸入後是否仍然按下修飾鍵,因爲我發送了鍵入事件,並且上述兩個函數都返回了鍵不管物理密鑰的狀態。因此,如果我假定它們仍然處於關閉狀態,則用戶將留下一個懸而未決的ctrl-down,直到用戶再次按下並釋放cntl(或任何修改鍵)爲止。否則,即使物理鍵仍然關閉,鍵仍可能保留。

因此,有什麼方法(最好沒有任何太低的水平)來檢測物理鍵狀態。僅限Windows的方法很好。關鍵監控(聽取關鍵事件)實際上是不可能的(或者至少真的,真的不可取)。

回答

0

經過多次測試,我似乎已經弄明白了。 MSDN約GetKeyState()

該函數返回的鍵狀態隨着線程從其消息隊列中讀取關鍵消息而發生更改。

GetAsyncKeyState()仍然在關鍵的向上/向下消息(不是物理密鑰狀態)上工作,但是它只是不等待消息被讀取。因此,如果通過SendInput()發送關鍵事件消息,它仍然會錯誤地返回 - 事實上,在GetKeyState()之前它將不正確,因爲它在呼叫之後立即不正確。

演示此功能的簡單測試是here(VS2010解決方案)或僅源here

+0

「GetAsyncKeyState()仍然適用於鍵上/下消息(不是物理鍵狀態)」與[MSDN文檔](http://msdn.microsoft.com/en-us/library/windows/desktop/ ms646293(v = vs.85).aspx) –

+0

這是無關緊要的。這是它的工作原理。一旦發佈關鍵事件,GetAsyncKeyState()的返回值就會改變。 –

+0

他們的鑰匙掉下來了,信息就發佈了。是的,這幾乎是發生了什麼! –

0

你在這裏有點困惑。實際上GetAsyncKeyState()確實在調用GetAsyncKeyState()的時刻返回關鍵狀態。另一方面,GetKeyState()基於排隊消息的歷史返回關鍵狀態。

+0

MSDN聲稱這同樣的事情,但在測試中,它不成立。發送密鑰註冊事件後,無論物理密鑰狀態如何,GetAsyncKeyState()實際上都會報告密鑰已啓動。 (Win7 64-bit) –

+0

所以你認爲一些基本的東西,因爲這在Windows中被打破,沒有人注意到了25年? –

+0

我知道在發送按鍵事件後會返回不正確的結果。 –

1

您沒有給窗口管理器足夠的時間來處理剛注入的輸入。直到它達到「更新密鑰狀態GetAsyncKeyState」部分代碼時,GetAsyncKeyState纔會報告舊值。 (特別是,直到所有低級別鍵盤鉤子都有機會檢查動作並可能拒絕動作時纔會達到該點)。

換句話說,您的代碼有一個競爭條件,那就是你在觀察什麼。