2012-02-28 70 views
0

我做了一個應用程序,即使窗口不活動時需要處理特定的鍵盤按下,現在我有這個,它工作的很好;然而,處理的鍵仍然傳播到窗口(不知道我的應用程序是否先處理它們,所以我可能會倒退)。不傳播到窗口的背景鍵盤快捷方式

有什麼辦法可以讓我的應用程序可以處理我想要的按鍵,但不會將按鍵發送到當前的應用程序/窗口。

EX)我有我的應用程序在監視數字鍵盤的印刷機打開,每次我按下數字鍵盤上的數字鍵我想將該數字添加到文本框用於顯示目的。現在我打開chrome並在地址欄中有光標,我希望能夠按下數字鍵,同時讓我的應用程序處理它們,但不會讓它們顯示在chromes地址欄中。

謝謝。

這基本上是一個非常簡單的鍵盤記錄器。

EDIT) 鍵盤鉤子

#endregion 
using System; 
using System.Text; 
using System.Collections.Generic; 
using System.Runtime.InteropServices; 
using System.Windows.Forms; 

public class GlobalKeyboardHook 
{ 
[DllImport("user32.dll")] 
static extern int CallNextHookEx(IntPtr hhk, int code, int wParam, ref keyBoardHookStruct lParam); 
[DllImport("user32.dll")] 
static extern IntPtr SetWindowsHookEx(int idHook, LLKeyboardHook callback, IntPtr hInstance, uint theardID); 
[DllImport("user32.dll")] 
static extern bool UnhookWindowsHookEx(IntPtr hInstance); 
[DllImport("kernel32.dll")] 
static extern IntPtr LoadLibrary(string lpFileName); 

public delegate int LLKeyboardHook(int Code, int wParam, ref keyBoardHookStruct lParam); 

public struct keyBoardHookStruct 
{ 
    public int vkCode; 
    public int scanCode; 
    public int flags; 
    public int time; 
    public int dwExtraInfo; 
} 

const int WH_KEYBOARD_LL = 13; 
const int WM_KEYDOWN = 0x0100; 
const int WM_KEYUP = 0x0101; 
const int WM_SYSKEYDOWN = 0x0104; 
const int WM_SYSKEYUP = 0x0105; 

LLKeyboardHook llkh; 
public List<Keys> HookedKeys = new List<Keys>(); 

IntPtr Hook = IntPtr.Zero; 

public event KeyEventHandler KeyDown; 
public event KeyEventHandler KeyUp; 

public GlobalKeyboardHook() 
{ 
    llkh = new LLKeyboardHook(HookProc); 
    hook(); 
} 
~GlobalKeyboardHook() 
{ unhook(); } 

public void hook() 
{ 
    IntPtr hInstance = LoadLibrary("User32"); 
    Hook = SetWindowsHookEx(WH_KEYBOARD_LL, llkh, hInstance, 0); 
} 

public void unhook() 
{ 
    UnhookWindowsHookEx(Hook); 
} 

public int HookProc(int Code, int wParam, ref keyBoardHookStruct lParam) 
{ 
    if (Code >= 0) 
    { 
     Keys key = (Keys)lParam.vkCode; 
     if (HookedKeys.Contains(key)) 
     { 
      KeyEventArgs kArg = new KeyEventArgs(key); 
      if ((wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) && (KeyDown != null)) 
       KeyDown(this, kArg); 
      else if ((wParam == WM_KEYUP || wParam == WM_SYSKEYUP) && (KeyUp != null)) 
       KeyUp(this, kArg); 
      if (kArg.Handled) 
       return 1; 
     } 
    } 
    return CallNextHookEx(Hook, Code, wParam, ref lParam); 
} 

} 

GlobalKeyboardHook

GlobalKeyboardHook gHook; 
private void Form1_Load(object sender, EventArgs e) 
{ 
    gHook = new GlobalKeyboardHook(); // Create a new GlobalKeyboardHook 
    // Declare a KeyDown Event 
    gHook.KeyDown += new KeyEventHandler(gHook_KeyDown); 
    // Add the keys you want to hook to the HookedKeys list 
    foreach (Keys key in Enum.GetValues(typeof(Keys))) 
     gHook.HookedKeys.Add(key); 
} 

// Handle the KeyDown Event 
public void gHook_KeyDown(object sender, KeyEventArgs e) 
{ 
    textBox1.Text += ((char)e.KeyValue).ToString(); 
} 

private void button1_Click(object sender, EventArgs e) 
{ 
    gHook.hook(); 
} 

private void button2_Click(object sender, EventArgs e) 
{ 
    gHook.unhook(); 
} 

private void Form1_FormClosing(object sender, FormClosingEventArgs e) 
{ 
    gHook.unhook(); 
} 
+0

我不明白你是如何從你的描述中這樣做的,你可以發表一些代碼來解釋一下更清楚嗎? – KingCronus 2012-02-28 20:56:16

+0

增加了一個在代碼中使用的簡單例子。 – Richard 2012-02-28 21:15:55

+0

您可能想要使用RegisterHotkey而不是掛鉤。請參閱http://stackoverflow.com/questions/4598895/how-to-create-non-window-bound-keyboard-shortcuts – CodesInChaos 2012-02-28 23:07:02

回答

1

的用法在你的HOOKPROC,你不能叫return CallNextHookEx(Hook, Code, wParam, ref lParam);,如果你不想在WM_KEYS傳播。

如果您確實調用CallNextHookEx,則消息將被傳播。

順便說一句,你知道你使用的是一個全局鉤子,而不是一個線程特定的鉤子?因此,您正在捕獲所有按鍵,而不僅僅是與您的應用程序相關的按鍵。

+0

工作,謝謝。 我知道我捕獲所有按鍵,因爲這是我想要的。我希望我的應用能夠處於後臺(不活動),並且仍然可以收到按鍵。 我不是100%你的意思是線程特定的鉤子(這是否意味着只有當我的應用程序是活動的,它將收到印刷機?) 如果有更好的方法來做到這一點,請讓我知道因爲我總是願意學習更好的方法。 – Richard 2012-02-28 23:22:01

+0

你實際上可以掛鉤到一個特定的過程。我說線程,但它實際上是過程。所以是的,你只能處理髮送到你的應用程序的關鍵消息,當它的活動。所以那不是你需要的。 – squelos 2012-02-29 08:08:47