È ansible creare un layout di tastiera identico alla tastiera utilizzata?

Se ho bisogno di generare un layout di tastiera per la personalizzazione all’utente che assomiglia alla sua tastiera, come posso farlo?

Ad esempio qualcosa del genere:

inserisci la descrizione dell'immagine qui

Francese, svedese, inglese, canadese, ecc. Avranno layout diversi, giusto. Si tratta di un sacco di lavoro o solo una questione di utilizzare una sorta di classi regionali .NET incorporate?

    Una pressione di un tasto genera un evento hardware che riporta un “codice di scansione” sul sistema operativo Windows. Questo codice di scansione viene quindi convertito in un “codice tasto virtuale” in base al codice di scansione insieme ad altri fattori di stato della tastiera (stato Bloc Maiusc , stato tasto Maiusc / Alt / Ctrl e anche eventuali tratti di tasto in attesa). Il valore VK convertito è ciò che viene segnalato dall’evento KeyDown ecc.

    La conversione dal codice di scansione al codice VK dipende dalle impostazioni locali di input correnti: in modo semplicistico, le impostazioni internazionali di input definiscono una mapping tra codici di scansione e codici di tasti virtuali. Vedere la documentazione MSDN per una descrizione completa dell’input da tastiera.

    Invertendo questo processo di ricerca, è ansible determinare il codice di scansione che corrisponde a ciascun codice di chiave virtuale (ovviamente, lo stesso codice di scansione si associerà a più codici VK a causa di shift / ctrl / alt stato ecc.). L’API Win32 fornisce la funzione MapVirtualKeyEx per eseguire questa mapping, utilizzando l’opzione MAPVK_VK_TO_VSC_EX . È ansible utilizzare questo per determinare quale codice di scansione genera il particolare codice VK.

    Sfortunatamente, questo è il massimo che si può andare programmaticamente: non c’è modo di determinare il layout fisico della tastiera o la posizione della chiave per ogni codice di scansione. Tuttavia, la maggior parte delle tastiere fisiche sono cablate allo stesso modo, quindi (ad esempio) il tasto in alto a sinistra avrà lo stesso codice di scansione sulla maggior parte dei progetti di tastiera fisica. È ansible utilizzare questa convenzione presunta per dedurre la posizione fisica corrispondente a un codice di scansione, a seconda del layout di base della tastiera fisica (101 tasti, 102 tasti, ecc.). Non è garantito, ma è un’ipotesi abbastanza sicura.

    Il seguente codice è un estratto da una più grande libreria di gestione della tastiera che ho scritto (ho intenzione di aprirla ma non ho avuto il tempo). Il metodo inizializza una matrice ( this._virtualKeyScanCodes ) indicizzata dal codice VK per una determinata lingua di input (memorizzata in this._inputLanguage che è dichiarata come System.Windows.Forms.InputLanguage . È ansible utilizzare la matrice per determinare il codice di scansione che corrisponde al codice VK esaminando ad esempio this._virtualKeyScanCodes[VK_NUMPAD0] – se il codice di scansione è zero, allora quel VK non è disponibile sulla tastiera nella locale di input corrente, se è diverso da zero, è il codice di scansione da cui puoi dedurre la chiave fisica.

    Sfortunatamente, le cose sono leggermente più complicate di questo quando si entra nel regno delle chiavi morte (combinazioni di tasti multipli che producono caratteri accentati, per esempio). È tutto troppo complicato per entrare in questo momento, ma Michael S. Kaplan ha scritto una serie dettagliata di post sul blog se vuoi approfondire ulteriormente. In bocca al lupo!

     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); } 

    Modifica: guarda anche questa domanda che è simile alla tua.

    Non esiste una class .NET integrata che contenga i layout della tastiera. I layout della tastiera sono una funzione del sistema operativo, in genere Windows. Quando .NET viene coinvolto, il tasto premuto è stato convertito da un evento hardware a uno software. Se vuoi vedere questo in azione, trova 2 layout di tastiera in cui una chiave si è spostata tra di loro. Impostare un’app fittizia con un gestore di Key_Down sull’evento Key_Down e quindi notare che gli argomenti dell’evento sono identici; se si preme il tasto -, si è premuto il tasto - indipendentemente da dove si trova quel tasto.