我正在創建一個程序,它安裝鍵盤掛鉤來捕獲所有鍵並顯示與它們相關的一些文本。鍵盤掛鉤改變鍵的行爲
但是,我遇到了一個問題,那就是當安裝鉤子時,一些鍵會改變行爲。
我會看到發佈一個小的,但完整的測試程序,但現在我只會描述這個問題。
該問題在Windows 7 64位,.NET 4.0中是一個C#程序。我認爲這些都不重要。
我的掛鉤通過SetWindowsHookEx
安裝,然後處理系統中處理的所有密鑰。
如果鉤子方法返回簡單或對鍵進行最小限度的處理(我會發布什麼會在一秒內改變行爲),鍵盤按照程序中的預期運行。但是,如果我從User32.dll中調用此函數ToAscii
來確定我的鍵盤OemTilde或類似鍵上的哪個鍵,那麼任何「覆蓋下一個鍵」的鍵都將停止運行。我不知道這些鍵的正確名稱,但是兩個撇號類型,和', as well as
〜and
',停止運作。
例如,如果我打~
然後N
,它顯示如下:
- 沒有鍵盤鉤子安裝:安裝ñ
- 隨着鍵盤鉤子:N(注意沒有〜上文)
有誰知道爲什麼會發生這種情況,我該如何解決這個問題?
現在我會解決在其他程序中正確處理密鑰的問題,即使這意味着我無法在自己的程序中正確檢測到正確的密鑰序列。
一些更多信息:
如果我所說的ToAscii
函數作爲鉤方法的一部分,則發生另一個問題。諸如¨
之類的鍵被處理兩次,即,如果我點擊¨
一次,記事本收到兩個¨¨
字符,並且打N
現在只是增加了N
。
但是,如果我使用BeginInvoke
來處理單獨的線程上的鍵,從鍵盤掛接方法返回後,會出現第一個問題。
我的程序可能是有點在那個特殊:
- 我不使用鍵盤的狀態(即。我傳過來的「Key State」256字節數組只是滿了0)
- 我不在乎死鍵(在我的程序不會處理它們的意義上,我只關心它們,不希望我的程序,使它們沒用到系統的其餘部分)
這樣,我的代碼最終看上去如下:
private bool IsDeadKey(uint key)
{
return ((Hook.Interop.MapVirtualKey(key, 2) & 2147483648) == 2147483648);
}
void _Hook_KeyDown_Async(KeyDownEventArgs e)
{
var inBuffer = new byte[2];
char key = '\0';
if (!IsDeadKey((uint)e.KeyCode))
{
int ascii = Hook.Interop.ToAscii((int) e.KeyCode,
e.ScanCode,
_KeyState,
inBuffer,
e.Flags);
if (ascii == 1)
{
key = Char.ToUpper((char) inBuffer[0]);
}
}
BeginInvoke(
new Action<Keys, Boolean, Boolean, Boolean, Char>(ProcessKeyboardEvent),
e.KeyCode, e.Control, e.Shift, e.Alt, key);
}
刪除對'ToAscii'的調用會很好,但由於我的應用程序的全部重點是*顯示*您按哪些鍵,並且國際鍵盤上的許多鍵返回導致不同鍵的虛擬鍵碼,所以我需要*一些*獲取這些密鑰的方式。也許我可以緩存所有這些,儘管這可能是可能的... – 2010-08-23 15:43:32
@Lasse V. Karlsen:我沒有深入研究,但也許你可以通過使用[MapVirtualKey](http:// msdn.microsoft.com/en-us/library/ms646306.aspx)函數? – 2010-08-23 15:47:37
或者你可以在*調用'ToAscii' /'ToUnicode'之前檢查是否按下了死鍵? – 2010-08-23 15:55:56