所以,我一直在開發一個類來處理VSTO插件中的Kwyboard輸入,到目前爲止我一直在使用Windows鉤子來取得相對的成功。VSTO Windows Hook keydown event called 10 times
有了這個代碼:
//.....
private const int WH_KEYBOARD = 2;
private const int WH_MOUSE = 7;
private enum WM : uint {
KEYDOWN = 0x0100,
KEYFIRST = 0x0100,
KEYLAST = 0x0108,
KEYUP = 0x0101,
MOUSELEFTDBLCLICK = 0x0203,
MOUSELEFTBTNDOWN = 0x0201,
MOUSELEFTBTNUP = 0x0202,
MOUSEMIDDBLCLICK = 0x0209,
MOUSEMIDBTNDOWN = 0x0207,
MOUSEMIDBTNUP = 0x0208,
MOUSERIGHTDBLCLK = 0x0206,
MOUSERIGHTBTNDOWN = 0x0204,
MOUSERIGHTBTNUP = 0x0205
}
private hookProcedure proc;
private static IntPtr hookID = IntPtr.Zero;
//Enganches
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr SetWindowsHookEx(int hookId, hookProcedure proc, IntPtr hInstance, uint thread);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern bool unHookWindowsHookEx(int hookId);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr CallNextHookEx(IntPtr hookId, int ncode, IntPtr wparam, IntPtr lparam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string name);
[DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetCurrentThreadId();
public CPInputListener() {
proc = keyBoardCallback;
hookID = setHook(proc);
}
private IntPtr setHook(hookProcedure procedure){
ProcessModule module = Process.GetCurrentProcess().MainModule;
uint threadId = (uint)GetCurrentThreadId();
return SetWindowsHookEx(WH_KEYBOARD, procedure, IntPtr.Zero, threadId);
}
public void stopListeningAll() {
unHookWindowsHookEx(WH_KEYBOARD);//For now
}
private IntPtr keyBoardCallback(int ncode, IntPtr wParam, IntPtr lParam) {
if (ncode >= 0) {
//LPARAM pretty useless
Keys key = (Keys)wParam;
KeyEventArgs args = new KeyEventArgs(key);
onKeyDown(args);//for now
}
return CallNextHookEx(hookID, ncode, wParam, lParam);
}
//....
我成功地接收鍵盤輸入,但這裏是大謎;每次按下某個按鍵時,不管其速度如何快,事件(onKeyDown)都被精確調用10次,不多不少。
如果長時間按下該按鍵,該事件將繼續被調用,但是會被調用10次,而不是隻調用一次。
到目前爲止,我已經試過
- 使用wParam參數來調用鍵向上所需的事件:好像沒有工作,所有的代碼我已經看到了重點處理向下和向上事件,
IntPtr wParam
被使用,但是從那個變量我只能檢索沒有幫助的鍵碼。 - 使用
lParam
或nCode
:這些瓦爾是那些10個調用之間給予unconsistent值,ncode
趨於檢索0和3的和lParam
一些值,這似乎是託管內存不會忽略...
什麼我期望
我確實期望onKeyDown只在鍵被按下時調用一次,或者另一方面可以通過在鍵上調用該方法,我希望每個鍵釋放時只調用一次。
如何繞過這個
如果我不能找到一個合理的答案,我想使用由計時器自定義丟棄所有的召喚,並使用只有最後一個,你會推薦這個,如果一切都失敗了?
非常感謝!快樂,善良! :D
確實!它確實有用!非常感謝你的幫助! 現在,爲了學習,你介意解釋我(或處理任何文檔)關於你如何弄清楚這些標誌? 再次感謝! –
@LuisMoyano很高興能幫到你!爲了學習,我彙集了所有相關文件和缺少的解釋。我希望這有幫助。現在,只需享受血腥的細節。 ;-) – haindl