2011-01-27 16 views
6

Si necesito generar un diseño de teclado para la personalización del usuario que se parece a su teclado, ¿cómo puedo hacerlo?¿Es posible crear un diseño de teclado que sea idéntico al teclado utilizado?

Por ejemplo algo como esto:

enter image description here

Francés, Sueco, Inglés, Canadá, etc tendrá diferentes diseños, a la derecha. ¿Es esto mucho trabajo o simplemente una cuestión de utilizar algún tipo de clases regionales integradas de .NET?

+4

Parece un complemento agradable para que alguien escriba;) – Oded

+0

Puede obtener imágenes de los diseños internacionales de teclado simplemente con Google Images. Prueba buscar en Google [diseño de teclado francés] (http://www.google.com/images?hl=es&q=french+keyboard+layout), por ejemplo. – Timwi

+0

Sí, pero necesito dibujarlo desde cero con un estilo predefinido. Además, si uso diseños, entonces tendría que almacenar todas las imágenes, ¿verdad? Necesito hacer esto en tiempo de ejecución dinámicamente (cuando se inicia el diálogo de personalización). –

Respuesta

8

Una pulsación de tecla genera un evento de hardware que informa un "código de exploración" al sistema operativo Windows. Este código de exploración se convierte entonces en base al código de escaneado junto con otros factores de estado del teclado de un "código de tecla virtual" (bloqueo de mayúsculas estado, Shift/Alt/Ctrl KeyState, y también cualquier tecla muertos en espera golpes). El valor de VK convertido es el que informa el evento KeyDown, etc.

La conversión del código de escaneo al código VK depende de la configuración regional actual: simplísticamente, la configuración regional de entrada define una asignación entre códigos de escaneo y códigos de tecla virtual. Consulte the MSDN documentation para obtener una descripción completa de la entrada del teclado.

Al invertir este proceso de búsqueda, es posible determinar el código de escaneo que corresponde a cada código de tecla virtual (por supuesto, el mismo código de escaneo se correlacionará con múltiples códigos VK debido al estado shift/ctrl/alt, etc.). La API de Win32 proporciona la función MapVirtualKeyEx para realizar esta asignación, mediante la opción MAPVK_VK_TO_VSC_EX. Puede usar esto para determinar qué código de exploración genera el código VK particular.

Lamentablemente, esto es lo más lejos que puede ir programáticamente: no hay forma de determinar el diseño físico del teclado o la ubicación de la clave para cada código de exploración. Sin embargo, la mayoría de los teclados físicos están cableados de la misma manera, por lo que (por ejemplo) la tecla de la parte superior izquierda tendrá el mismo código de exploración en la mayoría de los diseños de teclado físico. Puede usar esta convención supuesta para inferir la ubicación física correspondiente a un código de escaneo, dependiendo de la disposición física básica del teclado (101 teclas, 102 teclas, etc.). No está garantizado, pero es una suposición bastante segura.

El siguiente código es un extracto de una librería de manejo de teclado más grande que escribí (he tenido la intención de abrirlo pero no he tenido el tiempo). El método inicializa una matriz (this._virtualKeyScanCodes) indexada por código VK para una configuración regional de entrada determinada (almacenada en this._inputLanguage que se declara como System.Windows.Forms.InputLanguage. Puede usar la matriz para determinar el código de exploración que corresponde al código VK examinando, por ejemplo, this._virtualKeyScanCodes[VK_NUMPAD0] - si el código de exploración es cero, entonces ese VK no está disponible en el teclado en la configuración regional de entrada actual; si no es cero, es el código de exploración desde el que puede deducir la clave física.

Desafortunadamente, las cosas son un poco más complicadas que esto cuando se entra en el reino de las teclas muertas (combinaciones de teclas múltiples que producen caracteres acentuados, por ejemplo). Eso es demasiado complicado para entrar en este momento, pero Michael S. Kaplan escribió una serie detallada de blog posts si desea explorar más a fondo. ¡Buena suerte!

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

Editar: véase también this question que es similar a la suya.

+2

+1 Esto es mejor de lo que estábamos discutiendo en los comentarios sobre mi respuesta :) – GWLlosa

2

No hay una clase .NET incorporada que contenga los diseños de teclado. Los diseños de teclado son una función del sistema operativo, generalmente Windows. Para cuando .NET se involucra, la tecla presionada se convierte de un evento de hardware a uno de software. Si desea ver esto en acción, busque 2 diseños de teclado donde una tecla se haya movido entre ellos. Configure una aplicación ficticia con un controlador de eventos en el evento Key_Down, y luego tenga en cuenta que los eventos args son idénticos; si presionó la tecla -, presionó la tecla -, independientemente de dónde se encuentre esa clave -.

+0

Gracias, eso tiene sentido. Pero, ¿cómo lo hacen para decir los teclados rusos y chinos? Al igual que la tecla devuelve Keys.A, etc. También, ¿cómo hacen algunas aplicaciones cuando pueden recrear el diseño del teclado que está utilizando en la pantalla? ¿El teclado de Windows OSD hace eso? –

+0

Pueden estar utilizando Windows OSD; dado que se trata de una utilidad de sistema operativo, ES de hecho consciente del diseño; ver http://www.microsoft.com/windowsxp/using/accessibility/osklayout.mspx – GWLlosa

+0

Gracias, pero ¿cómo pueden usarlo? ¿No es otra aplicación como que no parece tener una API para engancharse, ¿verdad? –

Cuestiones relacionadas