WPF 從鍵盤事件 KeyEventArgs 裡獲取 Scan Code 的方法

lindexi發表於2024-05-07

本文將告訴大家如何在 WPF 裡面,從鍵盤事件 KeyEventArgs 引數裡獲取到 Scan Code 鍵盤按鍵的裝置獨立識別符號的方法

概念:

以下來自 bing 的答案

鍵盤的 Scan Code 是按鍵的裝置獨立識別符號,對應於按鍵在硬體上的實際標識。每個按鍵都有一個唯一的掃描碼,用於表示該按鍵。當使用者按下一個鍵時,鍵盤會生成兩個掃描碼:通碼(Make Code)斷碼(Break Code)。通碼錶示按鍵被按下,而斷碼錶示按鍵被釋放。這些掃描碼由鍵盤裝置驅動解釋並對映為虛擬鍵碼(Virtual Key Code),這是系統定義的裝置獨立值,用於標識鍵盤的按鍵²³.

虛擬鍵碼與掃描碼之間的區別在於,虛擬鍵碼是系統定義的值,而掃描碼是硬體上的實際識別符號。虛擬鍵碼通常用於處理鍵盤輸入的應用程式,而掃描碼更接近鍵盤的底層硬體表示。 。

總結一下:

  • Scan Code:鍵盤按鍵的裝置獨立識別符號,由硬體生成。
  • Virtual Key Code:系統定義的裝置獨立值,用於標識鍵盤的按鍵,由鍵盤裝置驅動解釋掃描碼並對映而來。

方法1: 推薦的方法,透過 Win32 函式獲取,程式碼實現如下

          KeyDown += MainWindow_KeyDown;

    private void MainWindow_KeyDown(object sender, KeyEventArgs e)
    {
        var key = e.Key;
        var virtualKey = KeyInterop.VirtualKeyFromKey(key);

        // MAPVK_VK_TO_VSC 0
        var scanCode = MapVirtualKeyW((uint) virtualKey, 0 /*MAPVK_VK_TO_VSC*/);
    }

    [DllImport("User32.dll")]
    private static extern uint MapVirtualKeyW(uint code, uint mapType);

方法2: 透過反射方式獲取,不推薦,且 API 可能被變更

    private void MainWindow_KeyDown(object sender, KeyEventArgs e)
    {
        var scanCodeFromWpf = typeof(KeyEventArgs).GetProperty("ScanCode", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)!.GetValue(e);
    }

這兩個方法獲取到的值是相同的,如使用下面程式碼,判斷相等成立

        Debug.Assert(scanCode == (int) scanCodeFromWpf!);

但如 MapVirtualKeyW 函式所述,確實存在一些情況下,獲取不到相同的結果

本文程式碼放在 githubgitee 上,可以使用如下命令列拉取程式碼

先建立一個空資料夾,接著使用命令列 cd 命令進入此空資料夾,在命令列裡面輸入以下程式碼,即可獲取到本文的程式碼

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 1806c3b45f5f10242da97a2fc1e3fa433fca783d

以上使用的是 gitee 的源,如果 gitee 不能訪問,請替換為 github 的源。請在命令列繼續輸入以下程式碼,將 gitee 源換成 github 源進行拉取程式碼

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin 1806c3b45f5f10242da97a2fc1e3fa433fca783d

獲取程式碼之後,進入 LaykechererolelQemyukilee 資料夾,即可獲取到原始碼

相關文章