KeyMap.cpp
上传用户:sbftbdw
上传日期:2007-01-03
资源大小:379k
文件大小:8k
源码类别:

远程控制编程

开发平台:

Visual C++

  1. //  Copyright (C) 1997, 1998 Olivetti & Oracle Research Laboratory
  2. //
  3. //  This file is part of the VNC system.
  4. //
  5. //  The VNC system is free software; you can redistribute it and/or modify
  6. //  it under the terms of the GNU General Public License as published by
  7. //  the Free Software Foundation; either version 2 of the License, or
  8. //  (at your option) any later version.
  9. //
  10. //  This program is distributed in the hope that it will be useful,
  11. //  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. //  GNU General Public License for more details.
  14. //
  15. //  You should have received a copy of the GNU General Public License
  16. //  along with this program; if not, write to the Free Software
  17. //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
  18. //  USA.
  19. //
  20. // If the source code for the VNC system is not available from the place 
  21. // whence you received this file, check http://www.orl.co.uk/vnc or contact
  22. // the authors on vnc@orl.co.uk for information on obtaining it.
  23. // Thanks to Martin C. Mueller <mcm@itwm.uni-kl.de> for assistance with the
  24. // international keyboard mapping stuff.
  25. // KeyMap.cpp
  26. #include "stdhdrs.h"
  27. #include "KeyMap.h"
  28. #include "vncviewer.h"
  29. // Define the keymap structure
  30. typedef struct vncKeymapping_struct {
  31. UINT wincode;
  32. UINT Xcode;
  33. } vncKeymapping;
  34. static const vncKeymapping keymap[] = {
  35. {VK_BACK, XK_BackSpace},
  36. {VK_TAB, XK_Tab},
  37. {VK_CLEAR, XK_Clear},
  38. {VK_RETURN, XK_Return},
  39. {VK_LSHIFT, XK_Shift_L},
  40. {VK_RSHIFT, XK_Shift_R},
  41.     {VK_SHIFT,      XK_Shift_L},
  42. {VK_LCONTROL, XK_Control_L},
  43. {VK_RCONTROL, XK_Control_R},
  44.     {VK_CONTROL, XK_Control_L},
  45.     {VK_LMENU, XK_Alt_L},
  46.     {VK_RMENU, XK_Alt_R},
  47.     {VK_MENU, XK_Alt_L},
  48.     {VK_PAUSE, XK_Pause},
  49.     {VK_CAPITAL, XK_Caps_Lock},
  50.     {VK_ESCAPE, XK_Escape},
  51.     {VK_SPACE, XK_space},
  52.     {VK_PRIOR, XK_Page_Up},
  53.     {VK_NEXT, XK_Page_Down},
  54.     {VK_END, XK_End},
  55.     {VK_HOME, XK_Home},
  56.     {VK_LEFT, XK_Left},
  57.     {VK_UP, XK_Up},
  58.     {VK_RIGHT, XK_Right},
  59.     {VK_DOWN, XK_Down},
  60.     {VK_SELECT, XK_Select},
  61.     {VK_EXECUTE, XK_Execute},
  62.     {VK_SNAPSHOT, XK_Print},
  63.     {VK_INSERT, XK_Insert},
  64.     {VK_DELETE, XK_Delete},
  65.     {VK_HELP, XK_Help},
  66.     {VK_NUMPAD0, XK_KP_0},
  67.     {VK_NUMPAD1, XK_KP_1},
  68.     {VK_NUMPAD2, XK_KP_2},
  69.     {VK_NUMPAD3, XK_KP_3},
  70.     {VK_NUMPAD4, XK_KP_4},
  71.     {VK_NUMPAD5, XK_KP_5},
  72.     {VK_NUMPAD6, XK_KP_6},
  73.     {VK_NUMPAD7, XK_KP_7},
  74.     {VK_NUMPAD8, XK_KP_8},
  75.     {VK_NUMPAD9, XK_KP_9},
  76.     {VK_MULTIPLY, XK_KP_Multiply},
  77.     {VK_ADD, XK_KP_Add},
  78.     {VK_SEPARATOR, XK_KP_Separator},   // often comma
  79.     {VK_SUBTRACT, XK_KP_Subtract},
  80.     {VK_DECIMAL, XK_KP_Decimal},
  81.     {VK_DIVIDE, XK_KP_Divide},
  82.     {VK_F1, XK_F1},
  83.     {VK_F2, XK_F2},
  84.     {VK_F3, XK_F3},
  85.     {VK_F4, XK_F4},
  86.     {VK_F5, XK_F5},
  87.     {VK_F6, XK_F6},
  88.     {VK_F7, XK_F7},
  89.     {VK_F8, XK_F8},
  90.     {VK_F9, XK_F9},
  91.     {VK_F10, XK_F10},
  92.     {VK_F11, XK_F11},
  93.     {VK_F12, XK_F12},
  94.     {VK_F13, XK_F13},
  95.     {VK_F14, XK_F14},
  96.     {VK_F15, XK_F15},
  97.     {VK_F16, XK_F16},
  98.     {VK_F17, XK_F17},
  99.     {VK_F18, XK_F18},
  100.     {VK_F19, XK_F19},
  101.     {VK_F20, XK_F20},
  102.     {VK_F21, XK_F21},
  103.     {VK_F22, XK_F22},
  104.     {VK_F23, XK_F23},
  105.     {VK_F24, XK_F24},
  106.     {VK_NUMLOCK, XK_Num_Lock},
  107.     {VK_SCROLL, XK_Scroll_Lock}
  108. };
  109. KeyMap::KeyMap() {
  110. };
  111. KeyActionSpec KeyMap::PCtoX(UINT virtkey, DWORD keyData) { 
  112. UINT numkeys = 0;
  113.     
  114.     KeyActionSpec kas;
  115.     kas.releaseModifiers = 0;
  116.     bool extended = ((keyData & 0x1000000) != 0);
  117.     log.Print(8,_T(" keyData %04x "), keyData);
  118.     
  119.     if (extended) { 
  120.         log.Print(8, _T(" (extended) "));
  121.         switch (virtkey) {
  122.         case VK_MENU :
  123.             virtkey = VK_RMENU; break;
  124.         case VK_CONTROL:
  125.             virtkey = VK_RCONTROL; break;
  126.         }
  127.     }
  128.     
  129.     // We try looking it up in our table
  130.     UINT mapsize = sizeof(keymap) / sizeof(vncKeymapping);
  131.         
  132.     // Look up the desired code in the table
  133.     for (UINT i = 0; i < mapsize; i++)
  134.     {
  135.         if (keymap[i].wincode == virtkey) {
  136.             kas.keycodes[numkeys++] = keymap[i].Xcode;
  137.             break;
  138.         }
  139.     }
  140.     
  141.     if (numkeys != 0) {
  142.         UINT key = kas.keycodes[numkeys-1];
  143.         log.Print(8, _T("keymap gives %u (%x) "), key, key);
  144.     } else {
  145.         // not found in table
  146.         log.Print(8, _T("not in special keymap, "));
  147. // Under CE, we're not so concerned about this bit because we handle a WM_CHAR message later
  148. #ifndef UNDER_CE
  149.         // we try a simple conversion to Ascii, using the current keyboard mapping
  150. ::GetKeyboardState(keystate);
  151.     int ret = ::ToAscii(virtkey, 0, keystate, (WORD *) buf, 0);
  152.         // If Left Ctrl & Alt both pressed and ToAscii gives a valid keysym
  153.         // This is for AltGr on international keyboards  (= LCtrl-Alt).
  154.         // e.g. Ctrl-Alt-Q gives @ on German keyboards
  155.         if (  ((keystate[VK_MENU] & 0x80) != 0) &&
  156.             ((keystate[VK_CONTROL] & 0x80) != 0) ) {
  157.            // If the key means anything in this keyboard layout
  158.            if  ( (ret >= 1) && 
  159.                  ( ( (*buf >= 32) && (*buf <= 126) ) ||
  160.                    ( (*buf >= 160) && (*buf <= 255) ) ) 
  161.                 ) {
  162.                // Send the modifiers up, then the keystroke, then mods down
  163.                // We don't release the right control; this allows German users
  164.                // to use it for doing Ctl-@ etc. (though not under Win95 --
  165.                // see below)
  166.                if (GetKeyState(VK_LCONTROL) & 0x8000) kas.releaseModifiers |= KEYMAP_LCONTROL;
  167.                if (GetKeyState(VK_LMENU)    & 0x8000) kas.releaseModifiers |= KEYMAP_LALT;
  168.                if (GetKeyState(VK_RMENU)    & 0x8000) kas.releaseModifiers |= KEYMAP_RALT;
  169.                // This is for windows 95, and possibly other systems.  
  170.                // The above GetKeyState calls don't work in 95 - they always return 0.
  171.                // But if we're here at all we know that control and alt are pressed, so let's
  172.                // raise all Control and Alt keys if we haven't registered any yet.
  173.                if (kas.releaseModifiers == 0)
  174.                    kas.releaseModifiers = KEYMAP_LCONTROL | KEYMAP_LALT | KEYMAP_RALT;
  175.                log.Print(8, _T("Ctrl-Alt pressed: ToAscii (without modifiers) returns %d byte(s): "), ret);
  176.                 for (int i = 0; i < ret; i++) {
  177.                    kas.keycodes[numkeys++] = *(buf+i);
  178.                    log.Print(8, _T("%02x (%c) "), *(buf+i) , *(buf+i));
  179.                 }
  180.                 log.Print(8,_T("n"));
  181.            } 
  182.         } 
  183.         
  184.         // If not a ctrl-alt key
  185.         if (numkeys == 0) {
  186.             // There are no keysyms corresponding to control characters 
  187.             // Eg Ctrl F.  The server already knows whether the control 
  188.             // key is pressed. So we are interested in the key that would be 
  189.             // there if the Ctrl were not pressed.
  190.             keystate[VK_CONTROL] = keystate[VK_LCONTROL] = keystate[VK_RCONTROL] = 0;
  191.     int ret = ::ToAscii(virtkey, 0, keystate, (WORD *) buf, 0);
  192.             if (ret < 0) {
  193.                 switch (*buf) {
  194. case '`' :
  195. kas.keycodes[numkeys++] = XK_dead_grave; break;
  196. case ''' :
  197. kas.keycodes[numkeys++] = XK_dead_acute; break;
  198. case '~' :
  199. kas.keycodes[numkeys++] = XK_dead_tilde; break;
  200. case '^':
  201. kas.keycodes[numkeys++] = XK_dead_circumflex; break;
  202. }
  203.             }
  204.             // if this works, and it's a regular printable character, we just send that
  205.             if (ret >= 1) {
  206.                 log.Print(8,_T("ToAscii (without ctrl) returns %d byte(s): "), ret);
  207.                 for (int i = 0; i < ret; i++) {
  208.                    kas.keycodes[numkeys++] = *(buf+i);
  209.                   log.Print(8, _T("%02x (%c) "), *(buf+i) , *(buf+i));
  210.                 }
  211.             }
  212.         }
  213. #endif
  214.     }
  215.     kas.keycodes[numkeys] = VoidKeyCode;
  216. return kas;
  217. };