Code Viewer

./Classes/__global_hotkey.js File Size: 23.18 KB

  1. /**
  2. * GLOBAL HOTKEY CLASS
  3. * Built on: 22 October 2008(revision 1)
  4. * by Mattias Buelens
  5. *
  6. * This class allows script developers to easily
  7. * create system-wide hotkeys.
  8. * You can optionally include the Action Hook class
  9. * so you can hook into specific parts of the class
  10. * for even more functionality and possibilities.
  11. */
  12.  
  13. //Global hotkey message constants
  14. var WM_HOTKEY = 0x312;
  15. var MOD_ALT = 0x1;
  16. var MOD_CONTROL = 0x2;
  17. var MOD_SHIFT = 0x4;
  18. var MOD_WIN = 0x8;
  19.  
  20. //Global object
  21. var GlobalHotkey;
  22.  
  23. /* Atom class */
  24. var Atom = function (sString) {
  25.         var nAtom = Atom.Add(sString);
  26.         return {
  27.                 Get: function () { return Atom.Get(sString); },
  28.                 GetName: function () { return Atom.GetName(nAtom); },
  29.                 Delete: function () { return Atom.Delete(nAtom); }
  30.         };
  31. };
  32. //Adds a global atom to the table
  33. Atom.Add = function (sString) {
  34.         return Interop.Call('kernel32', 'GlobalAddAtomW', sString);;
  35. };
  36. //Retrieves the value of the specified atom
  37. Atom.Get = function (sString) {
  38.         return Interop.Call('kernel32', 'GlobalFindAtomW', sString);
  39. };
  40. //Retrieve the atom name based on a specified atom value
  41. Atom.GetName = function (nAtom) {
  42.         var sBuffer = Interop.Allocate(512);
  43.         Interop.Call('kernel32', 'GlobalGetAtomNameW', 1*nAtom, sBuffer, 255);
  44.         return sBuffer.ReadString(0);
  45. };
  46. //Removes a specified atom from the table based on it's value
  47. Atom.Delete = function (nAtom) {
  48.         Interop.Call('kernel32', 'GlobalDeleteAtom', (1*nAtom).toString(16) );
  49. };
  50.  
  51. /* GlobalHotkey */
  52.  (function () {
  53.         /* Private object properties */
  54.         var oGlobalHotkeys = {};
  55.         var oRegistered = {};
  56.         var Subclass;
  57.         var bInitialized = false;
  58.         var bPaused = false;
  59.  
  60.         /* Private functions */
  61.         //Initializes the hotkey hook
  62.         var InitializeHotkeyHook = function () {
  63.                 GlobalHotkey.Actions.Do('BeforeInit', GlobalHotkey);
  64.                 //Close the subclass window(if already created)
  65.                 try {
  66.                         UnregisterHotkeys();
  67.                         Subclass.RegisterMessageNotification(WM_HOTKEY, false);
  68.                         Subclass.Close(0);
  69.                 } catch (e) {}
  70.                 //Re-open the subclass window
  71.                 Subclass = MsgPlus.CreateWnd(GlobalHotkey.Subclass.InterfacePath, GlobalHotkey.Subclass.WindowId, 0x3);
  72.                 Subclass.RegisterMessageNotification(WM_HOTKEY, true);
  73.                 RegisterHotkeys();
  74.                 GlobalHotkey.Subclass.Registry.SetValue(Subclass.Handle);
  75.                 GlobalHotkey.Actions.Do('AfterInit', GlobalHotkey);
  76.         };
  77.  
  78.         //Registers the hotkeys
  79.         var RegisterHotkeys = function () {
  80.                 GlobalHotkey.Actions.Do('BeforeRegister', GlobalHotkey);
  81.                 hWndOldSubclass = GlobalHotkey.Subclass.Registry.GetValue();
  82.                 var aFailedHotkeys =[];
  83.                 var bSuccess = true;
  84.                 for (var i in oGlobalHotkeys) {
  85.                         var oHotkey = oGlobalHotkeys[i];
  86.                         oHotkey.Update();
  87.                         Interop.Call('user32', 'UnregisterHotKey', hWndOldSubclass, Atom.Get(oHotkey.Id) );
  88.                         GlobalHotkey.Actions.Do('BeforeRegisterHotkey', oHotkey);
  89.                         oHotkey.Update(true);
  90.                         var nHotkey = LoByte(oHotkey.JoinedKey);
  91.                         var nModifier = oHotkey.Modifier;
  92.                         var nAtom = Atom.Add(oHotkey.Id);
  93.                         var Result = Interop.Call('user32', 'RegisterHotKey', Subclass.Handle, nAtom, nModifier, nHotkey);
  94.                         GlobalHotkey.Actions.Do('RegisterHotkey', oHotkey, (Result !== 0) );
  95.                         if (Result === 0) {
  96.                                 aFailedHotkeys.push(oHotkey);
  97.                                 bSuccess = false;
  98.                         } else {
  99.                                 oRegistered[(oHotkey.Id) ] = oHotkey;
  100.                                 Atom.Delete(nAtom);
  101.                         }
  102.                 }
  103.                 if (bSuccess) {
  104.                         GlobalHotkey.Actions.Do('AfterRegister', true);
  105.                 } else {
  106.                         GlobalHotkey.Actions.Do('AfterRegister', false, aFailedHotkeys);
  107.                 }
  108.                 return bSuccess;
  109.         };
  110.        
  111.         //Unregisters all hotkeys
  112.         var UnregisterHotkeys = function () {
  113.                 GlobalHotkey.Actions.Do('BeforeUnregister', GlobalHotkey);
  114.                 if (typeof Subclass  === 'object' && Subclass.Handle) {
  115.                         Subclass.RegisterMessageNotification(WM_HOTKEY, false);
  116.                         for (var i in oRegistered) {
  117.                                 var oHotkey = oRegistered[i];
  118.                                 var nAtom = Atom.Get(oHotkey.Id);
  119.                                 Interop.Call('user32', 'UnregisterHotKey', Subclass.Handle, nAtom);
  120.                                 Atom.Delete(nAtom);
  121.                         }
  122.                 }
  123.                 oRegistered = {};
  124.                 GlobalHotkey.Actions.Do('AfterUnregister', GlobalHotkey);
  125.         }
  126.        
  127.         //Re-registers the hotkeys
  128.         var ReloadHotkeys = function () {
  129.                 UnregisterHotkeys();
  130.                 GlobalHotkey.Actions.Do('BeforeRegister', GlobalHotkey);
  131.                 var aFailedHotkeys =[];
  132.                 var bSuccess = true;
  133.                 for (var i in oGlobalHotkeys) {
  134.                         var oHotkey = oGlobalHotkeys[i];
  135.                         oHotkey.Update();
  136.                         GlobalHotkey.Actions.Do('BeforeRegisterHotkey', oHotkey);
  137.                         oHotkey.Update(true);
  138.                         var nHotkey = oHotkey.JoinedKey;
  139.                         var nVirtualKey = oHotkey.KeyCode;
  140.                         var nModifier = oHotkey.Modifier;
  141.                         var nAtom = Atom.Add(oHotkey.Id);
  142.                         var Result = Interop.Call('user32', 'RegisterHotKey', Subclass.Handle, nAtom, nModifier, LoByte(nHotkey) );
  143.                         GlobalHotkey.Actions.Do('RegisterHotkey', oHotkey, (Result !== 0) );
  144.                         if (Result === 0) {
  145.                                 aFailedHotkeys.push(oHotkey);
  146.                                 bSuccess = false;
  147.                         } else {
  148.                                 oRegistered[(oHotkey.Id) ] = oHotkey;
  149.                                 Atom.Delete(nAtom);
  150.                         }
  151.                 }
  152.                 Subclass.RegisterMessageNotification(WM_HOTKEY, true);
  153.                 if (bSuccess) {
  154.                         GlobalHotkey.Actions.Do('AfterRegister', true);
  155.                 } else {
  156.                         GlobalHotkey.Actions.Do('AfterRegister', false, aFailedHotkeys);
  157.                 }
  158.                 return bSuccess;
  159.         }
  160.  
  161.         /* Helper functions */
  162.         //Parses the modifiers from a key code
  163.         var ParseKeyCode = function (nKeyCode, nModifier) {
  164.                 var nOrigMod = (nModifier = (nModifier ? nModifier : 0) );
  165.                 nModifier &= ~ (0x1000 | 0x800 | 0x400 | 0x200 | 0x100);
  166.                 if ( (nKeyCode | nOrigMod) & 0x1000)    { nKeyCode &= ~0x1000; nModifier |= MOD_WIN; }     //Windows
  167.                 if ( (nKeyCode | nOrigMod) & 0x800)     { nKeyCode &= ~0x800; }     //Extended
  168.                 if ( (nKeyCode | nOrigMod) & 0x400)     { nKeyCode &= ~0x400; nModifier |= MOD_ALT; }       //Alt
  169.                 if ( (nKeyCode | nOrigMod) & 0x200)     { nKeyCode &= ~0x200; nModifier |= MOD_CONTROL }    //Control
  170.                 if ( (nKeyCode | nOrigMod) & 0x100)     { nKeyCode &= ~0x100; nModifier |= MOD_SHIFT }      //Shift
  171.                 return {
  172.                         Key: nKeyCode,
  173.                         Mod: nModifier
  174.                 };
  175.         };
  176.        
  177.         //Applies the modifiers to a key code
  178.         var JoinKeyCode = function (nKeyCode, nModifier) {
  179.                 if (!nModifier) return nKeyCode;
  180.                 if (nModifier & MOD_WIN)               { nKeyCode |= 0x1000; }        //Windows
  181.                 if (nModifier & MOD_ALT)               { nKeyCode |= 0x400; } //Alt
  182.                 if (nModifier & MOD_CONTROL)    { nKeyCode |= 0x200; }     //Control
  183.                 if (nModifier & MOD_SHIFT)           { nKeyCode |= 0x100; }       //Shift
  184.                 return nKeyCode;
  185.         };
  186.        
  187.         //Creates a readable string based on the numerical value of the hotkey
  188.         function GetKeyName(uCode) {
  189.                 var ScanCode = Interop.Call('user32', 'MapVirtualKeyW', LoByte(uCode), 0);
  190.                 if (HiByte(uCode) & 8) ScanCode |= 0x100;
  191.                 var Text = Interop.Allocate(512);
  192.                 Interop.Call('user32', 'GetKeyNameTextW', ScanCode << 16, Text, 255);
  193.                 var Prefix = (HiByte(uCode) & 2 ? 'Ctrl + ' : '') + (HiByte(uCode) & 1 ? 'Shift + ' : '') + (HiByte(uCode) & 4 ? 'Alt + ' : '');
  194.                 return Prefix + Text.ReadString(0);
  195.         };
  196.  
  197.         //Binds a function to an object - based on Function.bind from Prototype(www.prototypejs.org)
  198.         var BindFunction = function () {
  199.                 var args = toArray(arguments);
  200.                 var func = args.shift();
  201.                 var obj = args.shift();
  202.                 return function () {
  203.                         return func.apply(obj, args.concat(toArray(arguments) ) );
  204.                 }
  205.         };
  206.  
  207.         //Converts any iterable object to an array - based on $A from Prototype(www.prototypejs.org)
  208.         var toArray = function (iterable) {
  209.                 if (!iterable) return[];
  210.                 if (iterable.toArray) return iterable.toArray();
  211.                 var length = iterable.length, results = new Array(length);
  212.                 while (length--) results[length] = iterable[length];
  213.                 return results;
  214.         };
  215.        
  216.         //Retrieves the lobyte from a value
  217.         function LoByte(w) { return w & 0xff; }
  218.         //Retrieves the hibyte from a value
  219.         function HiByte(w) { return w >> 8; }
  220.         //Creates a WORD value by concatenating the specified values.
  221.         function MakeWord(a,b) { return a | (b << 8); }
  222.  
  223.         /* GlobalHotkey class */
  224.         GlobalHotkey = function (sId, nKeyCode, nModifier, fCallback, oScope) {
  225.                 /* Private class properties */
  226.                 sId = String(sId);
  227.                 nKeyCode = 1*nKeyCode;
  228.                 nModifier = 1*nModifier;
  229.                 fCallback = (typeof fCallback === 'function')
  230.                         ? (typeof oScope === "undefined") ? fCallback : BindFunction (fCallback, this)
  231.                         : (function () { });
  232.                 var Joined = JoinKeyCode(nKeyCode, nModifier);
  233.                 var Parsed = ParseKeyCode(Joined);
  234.                 var KeyName = GetKeyName(Joined);
  235.  
  236.                 var Instance = {
  237.                         /* Public class properties */
  238.                         Id:               sId,
  239.                         KeyCode:        Parsed.Key,
  240.                         Modifier:       Parsed.Mod,
  241.                         Callback:       fCallback,
  242.                         KeyName:        KeyName,
  243.                         JoinedKey:      Joined,
  244.                         /* Public class functions */
  245.                         Update: function (bNoUnregister) {
  246.                                 if (!bNoUnregister) {
  247.                                         Interop.Call('user32', 'UnregisterHotKey', Subclass.Handle, Atom.Add(sId) );
  248.                                 }
  249.                                 var Joined = JoinKeyCode(this.KeyCode, this.Modifier);
  250.                                 var Parsed = ParseKeyCode(Joined);
  251.                                 var KeyName = GetKeyName(Joined);
  252.                                 this.KeyCode = Parsed.Key;
  253.                                 this.Modifier = Parsed.Mod;
  254.                                 this.KeyName = KeyName;
  255.                                 this.JoinedKey = Joined;
  256.                         },
  257.                         Delete: function (bNoUnregister) {
  258.                                 if (!bNoUnregister) {
  259.                                         Interop.Call('user32', 'UnregisterHotKey', Subclass.Handle, Atom.Get(sId) );
  260.                                 }
  261.                                 delete oRegistered[this.Id];
  262.                                 delete oGlobalHotkeys[this.Id];
  263.                         }
  264.                 };
  265.                
  266.                 oGlobalHotkeys[sId] = Instance;
  267.                 return Instance;
  268.         };
  269.        
  270.         /* Public object properties */
  271.         //Subclass window information
  272.         GlobalHotkey.Subclass = {
  273.                 InterfacePath: 'Subclass.xml',
  274.                 WindowId: 'Subclass',
  275.                 /*
  276.                  *      These functions are used to get and set the key
  277.                  *      value of the current subclass window. To avoid
  278.                  *      overloading this class with duplicate functions,
  279.                  *      I consider you already have such registry
  280.                  *      reading/writing functions in your script.
  281.                  *      GetValue should return the value of the subclass
  282.                  * window handle key, SetValue should set that value
  283.                  *      according to the given parameter as a DWORD.
  284.                  */
  285.                 Registry: {
  286.                         GetValue: function () { return 0; },
  287.                         SetValue: function (hWnd) { }
  288.                 }
  289.         };
  290.         //Global hooks
  291.         GlobalHotkey.Actions = (function () {
  292.                 try {
  293.                         return new ActionHook('GlobalHotkeyClass');
  294.                 } catch (e) {
  295.                         return { Add: function () {}, Do: function () {} };
  296.                 }
  297.         })();
  298.         /* Public object functions */
  299.         GlobalHotkey.Init = function () {
  300.                 InitializeHotkeyHook();
  301.                 bInitialized = true;
  302.         };
  303.         GlobalHotkey.Destroy = function () {
  304.                 UnregisterHotkeys();
  305.                 bInitialized = false;
  306.         };
  307.         GlobalHotkey.Reload = function () {
  308.                 if (bInitialized) ReloadHotkeys();
  309.                 else InitializeHotkeyHook();
  310.                 bInitialized = true;
  311.                 bPaused = false;
  312.         };
  313.         GlobalHotkey.Break = function (bNewState) {
  314.                 bNewState = (typeof bNewState === "undefined") ? !bPaused : (bNewState == true);
  315.                 if (bNewState) UnregisterHotkeys();
  316.                 else InitializeHotkeyHook();
  317.                 bPaused = bNewState;
  318.         };
  319.         GlobalHotkey.Add = function () {
  320.                 var args = toArray(arguments);
  321.                 return GlobalHotkey.apply(null, args);
  322.         };
  323.         GlobalHotkey.Get = function (sId) {
  324.                 try {
  325.                         return oGlobalHotkeys[sId];
  326.                 } catch (e) {
  327.                         return null;
  328.                 }
  329.         };
  330.         GlobalHotkey.DeleteAll = function () {
  331.                 oGlobalHotkeys = {};
  332.         };
  333.         GlobalHotkey.GetSubclass = function () {
  334.                 return Subclass;
  335.         };
  336.         GlobalHotkey.IsInit = function () {
  337.                 return(bInitialized == true);
  338.         };
  339.         GlobalHotkey.GetKeyName = function (nKeyCode, nModifier) {
  340.                 var Joined = JoinKeyCode(nKeyCode, nModifier);
  341.                 var Parsed = ParseKeyCode(Joined);
  342.                 return GetKeyName(Joined);
  343.         };
  344.         /* Public object events */
  345.         GlobalHotkey.HandleNotification = function () {
  346.                 var args = toArray( (arguments.length === 1) ? arguments[0]: arguments);
  347.                 var pPlusWnd = args[0], nMessage = args[1], wParam = args[2], lParam = args[3];
  348.                 if (nMessage === WM_HOTKEY) {
  349.                         var sAtomName = Atom.GetName(wParam);
  350.                         if (typeof oRegistered[sAtomName] === "object") {
  351.                                 var oHotkey = oRegistered[sAtomName];
  352.                                 oHotkey.Callback(oHotkey);
  353.                         }
  354.                         return true;
  355.                 }
  356.                 return false;
  357.         }
  358. })();

Version

  • 5.0.0070_20100325_publicbeta1

Developers

Project Details

  • Folders8
  • Files122
  • Total Lines11,867
  • Repository Version70

User Count

  • 162