Ist es möglich, ein Tastaturlayout zu erstellen, das mit der verwendeten Tastatur identisch ist?

StackOverflow https://stackoverflow.com/questions/4822261

Frage

Wenn ich ein Tastaturlayout für die Anpassung an den Benutzer generieren muss, das wie seine/ihre Tastatur aussieht, wie kann ich das tun?

Zum Beispiel so etwas:

enter image description here

Französisch, Schwedisch, Englisch, Kanadier usw. haben unterschiedliche Layouts, richtig. Ist das eine Menge Arbeit oder nur eine Frage der Verwendung einer integrierten .NET -Regionalklassen?

War es hilfreich?

Lösung

Eine Taste -Presse generiert ein Hardware -Ereignis, bei dem ein "Scan -Code" für das Windows -Betriebssystem berichtet wird. Dieser Scan -Code wird dann zusammen mit anderen Tastaturstatusfaktoren in einen "virtuellen Schlüsselcode" basierend auf dem Scan -Code konvertiert (Caps Lock Zustand, Wechsel/Alt/Strg Keystate und auch alle ausstehenden toten Schlüsselstriche). Der konvertierte VK -Wert ist das, was von der gemeldet wird KeyDown Ereignis usw.

Die Konvertierung vom Scan -Code in den VK -Code hängt vom aktuellen Eingangsgebietsschema ab. Einfaches Eingangsgebietsschema definiert eine Zuordnung zwischen Scan -Codes und virtuellen Schlüsselcodes. Sehen Die MSDN -Dokumentation Für eine vollständige Beschreibung der Tastatureingabe.

Durch die Umkehrung dieses Suchprozesses ist es möglich, den Scan -Code zu bestimmen, der jedem virtuellen Schlüsselcode entspricht (natürlich ist der gleiche Scan -Code aufgrund von Shift/Strg/Alt -Status usw. mehrere VK -Codes zugeordnet). Die Win32 -API liefert die MapVirtualKeyEx Funktion zur Ausführung dieser Zuordnung, indem Sie die verwenden MAPVK_VK_TO_VSC_EX Möglichkeit. Sie können dies verwenden, um festzustellen, welcher Scan -Code den bestimmten VK -Code generiert.

Leider ist dies so weit wie möglich programmgesteuert. Es gibt keine Möglichkeit, das physische Layout der Tastatur oder die Position der Taste für jeden Scancode zu bestimmen. Die meisten physischen Tastaturen sind jedoch auf die gleiche Weise verdrahtet. Die obere Linksschlüssel verfügt also über den gleichen Scancode für die meisten physischen Tastaturdesigns. Sie können diese angenommene Konvention verwenden, um den physischen Standort zu schließen, der einem Scan-Code entspricht, abhängig vom grundlegenden physischen Tastaturlayout (101-Key, 102-Key usw.). Es ist nicht garantiert, aber es ist eine ziemlich sichere Vermutung.

Der folgende Code ist ein Auszug aus einer größeren Bibliothek mit Tastaturabwicklung, die ich geschrieben habe (ich habe beabsichtigt, ihn zu open-Source, aber keine Zeit hatte). Die Methode initialisiert ein Array (this._virtualKeyScanCodes) Das wird durch VK -Code für ein bestimmtes Eingangsgebietsschema (gespeichert in this._inputLanguage was als a deklariert wird System.Windows.Forms.InputLanguage. Sie können das Array verwenden, um den Scan -Code zu bestimmen, der dem VK -Code entspricht, indem Sie EG untersuchen this._virtualKeyScanCodes[VK_NUMPAD0] - Wenn der Scan -Code Null ist, ist dieser VK auf der Tastatur im aktuellen Eingangsgebietsschema nicht verfügbar. Wenn es sich um ungleich Null handelt, ist es der Scancode, aus dem Sie den physischen Schlüssel schließen können.

Leider sind die Angelegenheiten etwas komplizierter als dies, wenn Sie in die Bereiche toter Schlüssel einsteigen (zum Beispiel mehrere Schlüsselkombinationen, die akzentuelle Zeichen erzeugen). Das ist alles viel zu kompliziert, um jetzt zu gehen, aber Michael S. Kaplan schrieb eine detaillierte Reihe von Blogeinträge Wenn Sie dies weiter untersuchen möchten. Viel Glück!

private void Initialize()
{
    this._virtualKeyScanCodes = new uint[MaxVirtualKeys];

    // Scroll through the Scan Code (SC) values and get the Virtual Key (VK)
    // values in it. Then, store the SC in each valid VK so it can act as both a 
    // flag that the VK is valid, and it can store the SC value.
    for (uint scanCode = 0x01; scanCode <= 0xff; scanCode++)
    {
        uint virtualKeyCode = NativeMethods.MapVirtualKeyEx(
            scanCode, 
            NativeMethods.MAPVK_VSC_TO_VK, 
            this._inputLanguage.Handle);
        if (virtualKeyCode != 0)
        {
            this._virtualKeyScanCodes[virtualKeyCode] = scanCode;
        }
    }

    // Add the special keys that do not get added from the code above
    for (KeysEx ke = KeysEx.VK_NUMPAD0; ke <= KeysEx.VK_NUMPAD9; ke++)
    {
        this._virtualKeyScanCodes[(uint)ke] = NativeMethods.MapVirtualKeyEx(
            (uint)ke, 
            NativeMethods.MAPVK_VK_TO_VSC, 
            this._inputLanguage.Handle);
    }

    this._virtualKeyScanCodes[(uint)KeysEx.VK_DECIMAL] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_DECIMAL, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_DIVIDE] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_DIVIDE, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_CANCEL] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_CANCEL, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);

    this._virtualKeyScanCodes[(uint)KeysEx.VK_LSHIFT] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_LSHIFT, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_RSHIFT] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_RSHIFT, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_LCONTROL] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_LCONTROL, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_RCONTROL] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_RCONTROL, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_LMENU] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_LMENU, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_RMENU] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_RMENU, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_LWIN] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_LWIN, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_RWIN] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_RWIN, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_PAUSE] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_PAUSE, NativeMethods.MAPVK_VK_TO_VSC_EX, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_VOLUME_UP] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_VOLUME_UP, NativeMethods.MAPVK_VK_TO_VSC_EX, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_VOLUME_DOWN] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_VOLUME_DOWN, NativeMethods.MAPVK_VK_TO_VSC_EX, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_VOLUME_MUTE] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_VOLUME_MUTE, NativeMethods.MAPVK_VK_TO_VSC_EX, this._inputLanguage.Handle);

    this._virtualKeyScanCodes[(uint)KeysEx.VK_MEDIA_NEXT_TRACK] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_MEDIA_NEXT_TRACK, NativeMethods.MAPVK_VK_TO_VSC_EX, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_MEDIA_PREV_TRACK] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_MEDIA_PREV_TRACK, NativeMethods.MAPVK_VK_TO_VSC_EX, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_MEDIA_PLAY_PAUSE] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_MEDIA_PLAY_PAUSE, NativeMethods.MAPVK_VK_TO_VSC_EX, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_MEDIA_STOP] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_MEDIA_STOP, NativeMethods.MAPVK_VK_TO_VSC_EX, this._inputLanguage.Handle);

    this._stateController = new KeyboardStateController();
    this._baseVirtualKeyTable = new VirtualKeyTable(this);
}

Bearbeiten: Siehe auch diese Frage Welches ist Ihnen ähnlich.

Andere Tipps

Es gibt keine integrierte .NET-Klasse, die die Tastaturlayouts enthält. Die Tastaturlayouts sind eine Funktion des Betriebssystems, normalerweise Windows. Bis .NET involviert wird die gedrückte Taste von einem Hardwareereignis in eine Software konvertiert. Wenn Sie dies in Aktion sehen möchten, finden Sie 2 Tastaturlayouts, bei denen sich ein Schlüssel zwischen ihnen bewegt hat. Richten Sie eine Dummy -App mit einem Event -Handler auf der Key_Down Ereignis und dann beachten Sie, dass die Ereignisargs identisch sind; Wenn Sie die gedrückt haben - Taste Sie haben die gedrückt - Schlüssel, unabhängig davon, wo das ist - Der Schlüssel befindet sich.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top