2013-10-03 24 views
5

我有一個連接到讀卡器(磁條)的應用程序。當我有一個輸出我的數據的表單時,或者在可以將數據輸出到控制檯的控制檯應用程序中時,我可以捕獲卡上的數據。按鍵事件處理程序,但在沒有窗體的Windows應用程序中

但是在我正在使用的應用程序中,它有一個Program類作爲它的啓動,並且只是以這種方式啓動程序。

我想我需要的是一個通用的按鍵監聽器來查看讀卡器刷卡時的情況。

Windows Forms App Ex Console App Ex KeyPressEventHandler Delegate

我想,我想是這樣的KeyPressEventHandler,但我似乎無法得到這在我的應用程序。

我創建了以下Extention方法:

public static class Utilities 
{ 
    private static KeyPressEventHandler handler = KeyPressed; 

    public static void KeyPressed(Object sender, KeyPressEventArgs e) 
    { 
     while (true) 
     { 
      dataReceived.Append(e.KeyChar); 
     } 
    } 

    public static KeyPressEventHandler getKeyPressHandler() 
    { 
     return handler; 
    } 
} 

但我不確定如何引用它在我的Main()方法。我沒有看到按鍵方法。

+2

您需要一個窗口來捕獲密鑰,或者您應該查看'SetWindowsHook' http://msdn.microsoft.com/en-us/library/ms644990(VS.85).aspx –

+0

@JeroenvanLangen - 你有一個如何在C#中完成的例子? – webdad3

+0

@ webdad3你有沒有試過一個着名的網站有很多例子:http://google.com? – BartoszKP

回答

2

根據CLR和Windows的版本,你將會遇到一些使用Windows Hooks的特定問題。

  1. WH_KEYBOARD/WH_KEYBOARD_LL鍵盤掛鉤需要消息循環才能正常運行。將鍵盤事件發送到安裝線程的消息隊列,然後生成對掛接委託的調用。
  2. Windows Vista及更高版本將不允許來自較低特權進程的掛接看到較高特權進程中的活動。所以你可能會也可能不會得到鍵盤事件,這取決於當前有哪些輸入焦點。
  3. 一旦你掛上了鍵盤事件,你將需要一個由讀卡器產生的啓動和停止標記,以表明你應該捕獲剩餘的輸入。這是否可以實現將取決於配置讀卡器的能力。

說了這麼多,使用WH_KEYBOARD或WH_KEYBOARD_LL鉤子肯定可以達到預期的結果。如果您決定走這條路線,我建議您使用交替的左鍵Ctrl和右鍵控制按鍵作爲閱讀器的啓動和停止哨兵(假設它有能力這樣做)。另外,如果你最終得到一個Windows Hook,你將需要從後臺線程安裝鉤子,而不是你的應用程序的主線程,因爲你需要在一定的時間內處理鍵盤事件。如果您花費的時間超過Windows允許的時間,掛鉤將被忽略。

作爲Windows Hooks的替代品,您可以使用DirectInput。老實說,我從來沒有嘗試過這種方法,但這個概念似乎是合理的,並消除了Windows Hook的一些不確定性。

我假設既然你是要求全球性的鍵盤事件,那你的讀卡器就是各種各樣的USB HID設備。您可以通過運行DxDiag來驗證您的讀卡器是否顯示爲DirectInput設備。該設備應顯示在輸入選項卡上,如果它可以訪問。似乎有各種可用的DirectX託管程序集。

如果您不僅限於您擁有的讀卡器類型,那麼使用基於串行的讀卡器可能會更好。有了它,你不會完成其他應用程序的設備輸出。

我意識到我沒有真正回答你的問題,所以隨意投票或忽略這個答案。希望這會給你一些關於你可能面臨的問題的信息。

經過一番進一步的思考,我認爲您可以直接訪問HID設備並使用標準的Win32 API執行鍵盤翻譯。沿着這條路線看,我碰到了Raw Input API。使用此功能,您應該能夠註冊所有鍵盤設備的原始輸入,然後在輸入時確定實際生成事件的設備。消除讀者啓動和停止哨兵的需求。

更好的是,API發送消息以區分當窗口是前景窗口時和當窗口不是前景窗口時生成的輸入。有了這個API,你仍然需要在後臺線程上創建一個窗口和消息循環,但它應該比Windows Hook方法更清潔。

有關使用C#編寫原始輸入的示例應用程序,請參見CodeProject上的Using Raw Input from C# to handle multiple keyboards

1

一個例子(以爲我沒有更新,因爲.NET框架1.1的代碼)有一個事件時按下任意鍵

public class Hook 
{ 

    [DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)] 
    private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId); 
    [DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)] 
    private static extern bool UnhookWindowsHookEx(int idHook); 
    [DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)] 
    private static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam); 
    [DllImport("kernel32.dll")] 
    public static extern int GetCurrentThreadId(); 

    public static event Action Event = null; 
    private const int WH_KEYBOARD = 2; 
    private delegate int HookProc(int code, IntPtr wParam, IntPtr lParam); 
    static int _hookKeyboard = 0; 
    private static HookProc _hookKeyboardProc; 

    public static bool Install() 
    { 
     _hookKeyboardProc = new HookProc(KeyboardHook); 
     _hookKeyboard = SetWindowsHookEx(WH_KEYBOARD, _hookKeyboardProc, IntPtr.Zero, GetCurrentThreadId()); 
     return _hookKeyboard != 0; 
    } 

    public static bool Uninstall() 
    { 
     // uninstall keyboard hook 
     if(!UnhookWindowsHookEx(_hookKeyboard)) 
      return false; 
     _hookMouseProc = null; 
     return true; 
    } 

    private static int KeyboardHook(int nCode, IntPtr wParam, IntPtr lParam) 
    { 
     // if any message - fire event 
     if(nCode >= 0 && Event != null) 
      Event(); 
     return CallNextHookEx(_hookKeyboard, nCode, wParam, lParam); 
    } 
} 
相關問題