簡體   English   中英

keypress事件處理程序,但在沒有表單的Windows應用程序上

[英]keypress event handler but on a windows app with no forms

我有一個與讀卡器(磁條)相連的應用程序。 當我有一個輸出我的數據的表單時,或者在我可以將數據輸出到控制台的控制台應用程序中時,我能夠捕獲卡上的數據。

但是在我正在開發的應用程序上它有一個Program類作為它的啟動,只是以這種方式啟動程序。

我認為我需要的是一個通用的按鍵監聽器,可以在讀卡器時查找。

Windows窗體應用程序Ex 控制台應用程序Ex KeyPressEventHandler委托

我想我想要像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()方法中引用它。 我沒有看到按鍵方法。

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

  1. WH_KEYBOARD / WH_KEYBOARD_LL鍵盤掛鈎需要消息循環才能正常運行。 在生成對鈎子委托的調用之前,鍵盤事件將發布到安裝線程的消息隊列。
  2. Windows Vista及更高版本不允許來自較低權限進程的掛鈎在較高權限進程中查看活動。 因此,您可能會或可能不會獲取鍵盤事件,具體取決於當前具有輸入焦點的進程。
  3. 連接鍵盤事件后,您需要有一個由讀卡器生成的開始和停止標記,以指示您應該捕獲剩余的輸入。 這是否可實現取決於配置讀卡器的能力。

說完所有這些之后,使用WH_KEYBOARD或WH_KEYBOARD_LL掛鈎肯定可以實現所需的結果。 如果您決定走這條路線,我建議您使用交替的Left-Ctrl和Right-Control按鍵作為讀取器的開始和停止標記(假設它能夠這樣做)。

此外,如果您最終使用Windows Hook,則需要從后台線程而不是應用程序的主線程安裝鈎子,因為您需要在一定時間內處理鍵盤事件。 如果您花費的時間比Windows允許的時間長,則會忽略該掛鈎。

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

我假設你要求全球鍵盤事件,你的讀卡器是各種各樣的USB HID設備。 您可以通過運行DxDiag驗證您的讀卡器是否顯示為DirectInput設備。 如果設備可以訪問,則該設備應出現在“輸入”選項卡上。 似乎有各種可用的DirectX托管程序集。

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

我意識到我實際上並沒有回答你的問題,所以請隨意投票或忽略這個答案。 希望這確實能為您提供有關您可能面臨的問題的一些信息。

經過深思熟慮后,我認為您可以直接訪問HID設備並使用標准Win32 API執行鍵盤翻譯。 在查看該路線時,我遇到了Raw Input API。 使用此功能,您應該能夠為所有鍵盤設備注冊原始輸入,然后在輸入時確定實際生成事件的設備。 消除了讀者啟動和停止哨兵的需要。

更好的是,API發送消息以區分窗口是前景窗口時生成的輸入和不是窗口時生成的輸入。 使用此API,您仍然需要在后台線程上創建窗口和消息循環,但它應該比Windows Hook方法更清晰。

有關在C#中讀取原始輸入的示例應用程序,請參閱使用C#中的原始輸入來處理 CodeProject上的多個鍵盤

一個例子(我以為自.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); 
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM