Code Viewer

./Classes/__menu.js File Size: 26.18 KB

  1. /*
  2. * -----
  3. * Screenshot Sender - __menu.js
  4. * -----
  5. * Menu class to create Windows menus.
  6. * -----
  7. */
  8.  
  9. //Message constants for menu
  10. var MF_CHECKED = 0x8;
  11. var MF_UNCHECKED = 0x0;
  12. var MF_ENABLED = 0x0;
  13. var MF_DISABLED = 0x2;
  14. var MF_GRAYED = 0x1;
  15. var MF_APPEND = 0x100;
  16. var MF_SEPARATOR = 0x800;
  17. var MF_STRING = 0x0;
  18. var MF_POPUP = 0x10;
  19. var MF_BYPOSITION = 0x400;
  20. var MF_BITMAP = 0x4;
  21. var TPM_LEFTALIGN = 0x0;
  22. var TPM_RIGHTALIGN = 0x8;
  23. var TPM_RETURNCMD = 0x0100;
  24. var TPM_VERNEGANIMATION = 0x2000;
  25. var TPM_LAYOUTRTL = 0x8000;
  26. var MIIM_STRING = 0x40;
  27. var MIIM_SUBMENU = 0x4;
  28. var MIM_APPLYTOSUBMENUS = 0x80000000;
  29. var MIM_BACKGROUND = 0x2;
  30. var MIM_STYLE = 0x10;
  31. var MNS_CHECKORBMP = 0x4000000;
  32.  
  33. //Other menu globals
  34. var MENU_ID_BASE = 0x1337;
  35. var subclass;
  36.  
  37. /**
  38. *      MENU CLASS - by Mattias Buelens
  39. *      This class lets you create and open Windows menus. You can even add submenus and images to the menu.
  40. *      Requirements:
  41. *           The Gdi.js file of Countdown Live 2 for the bitmap functions. Note that this file contains Trace() function calls. You can
  42. *            either replace these calls by Debug.Trace() calls and remove the last parameter, or you can simply remove these lines or copy
  43. *            the Trace() function into your script. I really don't care. :-P
  44. *      Usage:
  45. *            1. Create a new instance with "new Menu() " with the fCallback parameter, which should be a function to receive the menu clicks.
  46. *            2. Now, you can:
  47. *                  - Add menu items with "Menu.AddMenuItem() ".
  48. *                  - Add submenus:
  49. *                        1. Create a new submenu with "Menu.CreateSubMenu() ".
  50. *                        2. Add stuff in this submenu, for example by using "SubMenu.AddMenuItem() ". You can even add sub-submenus!
  51. *                        3. Add the submenu to its parent with "Menu.AddSubMenu() ".
  52. *                  - Add menu separators with "Menu.AddSeparator() ".
  53. *            3. You can make the menu pop up anywhere you want by calling "Menu.Open() ".
  54. *            4. The callback function will receive up to 2 parameters:
  55. *                  - A string specifying the ID of the menu item clicked. This is the ID given to an item in "Menu.AddMenuItem() ".
  56. *                  - An extra parameter passed through "Menu.Open() ".
  57. *                    It can be anything you want and may be useful if you use the same menu on various places.
  58. *            5. When the menu isn't needed anymore, call "Menu.Destroy() " to destroy it along with any bitmaps or submenus that were created.
  59. *      You can use and modify this class in any way you like, as long as you keep the appropriate credits in the script.
  60. *            - The GDI and GDI+ functions for the bitmaps were originally written by Matty(Screenshot Sender developer) and further
  61. *              modified by myself.
  62. *            - The class was written by me. You don't need to place this whole header, just a small note will do just fine. :-)
  63. *      Other than that, feel free to do whatever you want with this. Hopefully this class can be useful to you one day and will let you
  64. *      create beautiful menus for your scripts. :-)
  65. *
  66. *      - Mattias Buelens.
  67. */
  68. var Menu = function (fCallback, oMenu) {
  69.         this.Owner = (typeof oMenu == "object") ? oMenu : false;
  70.         this.Callback = (typeof fCallback == "function") ? fCallback : function () { };
  71.         this.Index = (this.Owner != false) ? this.Owner.Index : 0;
  72.         this.ItemIDs = [], this.Bitmaps = {}, this.SubMenus = [];
  73.         this.Handle = Interop.Call("user32", "CreatePopupMenu");
  74.         this.SetMenuInfo();
  75. }
  76.  
  77. Menu.prototype = {
  78.         /**
  79.          *      Adds a menu item to the menu.
  80.          *            sId         Unique string identifier for this menu item, used to identify it when clicked.
  81.          *            sLabel                The label for the new menu item. Ignored when nState is MF_SEPARATOR. Optional.
  82.          *            nState                The state of the menu item. Optional.
  83.          *                                    Possible values: MF_CHECKED, MF_UNCHECKED, MF_ENABLED, MF_DISABLED, MF_GRAYED, MF_SEPARATOR
  84.          *            sBitmapPath   The path to an image file to add to the menu item. Optional.
  85.          *            bIsDefault    Boolean defining whether this is the default menu item. Optional.
  86.          *      Return value: True indicates success, otherwise false.
  87.          */
  88.         "AddMenuItem" : function (sId, sLabel, nState, sBitmapPath, bIsDefault) {
  89.                 sId = (typeof sId != "undefined") ? sId : 0
  90.                 sLabel = (typeof sLabel == "string") ? sLabel : "";
  91.                 nState = (typeof nState == "number") ? nState : 0;
  92.                 sBitmapPath = (typeof sBitmapPath == "string") ? sBitmapPath : "";
  93.                 bIsDefault = (bIsDefault == true);
  94.  
  95.                 var nIndex = (this.Owner == false) ? this.Index : this.Owner.Index - this.Index;
  96.  
  97.                 //When this is a separator, add it and stop.
  98.                 if (nState & MF_SEPARATOR) {
  99.                         var bResult = Interop.Call("user32", "AppendMenuW", this.Handle, MF_SEPARATOR, MENU_ID_BASE + this.Index, 0);
  100.                         if (bResult == 0) return false;
  101.                         this.IndexInc(sId);
  102.                         return true;
  103.                 }
  104.  
  105.                 //Add the menu item as a string.
  106.                 Interop.Call("user32", "AppendMenuW", this.Handle, MF_STRING, MENU_ID_BASE + this.Index, sLabel);
  107.                 if (bResult == 0) return false;
  108.  
  109.                 //Sets the menu item to default when asked.
  110.                 if (bIsDefault) Interop.Call("user32", "SetMenuDefaultItem", this.Handle, nIndex, true);
  111.  
  112.                 //Add a bitmap if one is specified.
  113.                 if (sBitmapPath.length > 0 && FileExists(sBitmapPath) ) {
  114.                         var bResult = this.SetBitmap(sBitmapPath, nIndex);
  115.                 }
  116.  
  117.                 //Sets the item states
  118.                 if (typeof nState == "number" && nState > 0) {
  119.                         if (nState & MF_CHECKED) Interop.Call("user32", "CheckMenuItem", this.Handle, nIndex, MF_BYPOSITION | MF_CHECKED);
  120.                         if (nState & MF_DISABLED) Interop.Call("user32", "EnableMenuItem", this.Handle, nIndex, MF_BYPOSITION | MF_DISABLED);
  121.                         if (nState & MF_GRAYED) Interop.Call("user32", "EnableMenuItem", this.Handle, nIndex, MF_BYPOSITION | MF_GRAYED);
  122.                 }
  123.  
  124.                 this.IndexInc(sId);
  125.                 return true;
  126.         },
  127.         /**
  128.          *      Adds a separator to the menu.
  129.          *      Return value: True indicates success, otherwise false.
  130.          */
  131.         "AddSeparator" : function () {
  132.                 return this.AddMenuItem("", "", MF_SEPARATOR, "", false);
  133.         },
  134.         /**
  135.          *      Creates a new submenu.
  136.          *      Return value: The new submenu.
  137.          */
  138.         "CreateSubMenu" : function () {
  139.                 var _this = this;
  140.                 var SubMenu = new Menu(0, _this);
  141.                 return SubMenu;
  142.         },
  143.         /**
  144.          *      Adds a submenu to the menu.
  145.          *            SubMenu              The menu object to add as submenu.
  146.          *            sLabel                The label for the submenu. Optional.
  147.          *            nState                The state of the submenu. See AddMenuItem. Optional.
  148.          *            sBitmapPath   The path to an image file to add to the submenu. Optional.
  149.          *      Return value: True indicates success, otherwise false.
  150.          */
  151.         "AddSubMenu" : function (SubMenu, sLabel, nState, sBitmapPath) {
  152.                 sLabel = (typeof sLabel == "string") ? sLabel : "";
  153.                 nState = (typeof nState == "number") ? nState : 0;
  154.                 sBitmapPath = (typeof sBitmapPath == "string") ? sBitmapPath : "";
  155.  
  156.                 //Add the submenu
  157.                 var bResult = Interop.Call("user32", "AppendMenuW", this.Handle, MF_POPUP | MF_STRING, SubMenu.Handle, sLabel);
  158.                 if (bResult == 0) return false;
  159.  
  160.                 //Set the owner of the submenu
  161.                 var _this = this;
  162.                 SubMenu.Owner = _this;
  163.  
  164.                 //Add the submenu to the list of submenus
  165.                 this.SubMenus.push(SubMenu);
  166.  
  167.                 //Add a bitmap if one is specified.
  168.                 if (sBitmapPath.length > 0 && FileExists(sBitmapPath) ) {
  169.                         var bResult = this.SetBitmap(sBitmapPath, this.Index);
  170.                 }
  171.  
  172.                 //Sets the item states
  173.                 if (typeof nState == "number" && nState > 0) {
  174.                         if (nState & MF_CHECKED) Interop.Call("user32", "CheckMenuItem", this.Handle, this.Index, MF_BYPOSITION | MF_CHECKED);
  175.                         if (nState & MF_DISABLED) Interop.Call("user32", "EnableMenuItem", this.Handle, this.Index, MF_BYPOSITION | MF_DISABLED);
  176.                         if (nState & MF_GRAYED) Interop.Call("user32", "EnableMenuItem", this.Handle, this.Index, MF_BYPOSITION | MF_GRAYED);
  177.                 }
  178.  
  179.                 this.IndexInc("");
  180.                 return true;
  181.         },
  182.         /**
  183.          *      Sets the state of the specified menu item's check-mark attribute.
  184.          *            Id            Menu item position(number) or menu item ID(string) to change.
  185.          *            bCheck                Boolean defining the new check state.
  186.          *      Return value: None(void)
  187.          */
  188.         "CheckMenuItem" : function (Id, bCheck) {
  189.                 bCheck = (typeof bCheck == "undefined") ? true : (bCheck != false);
  190.                 var nId = 0;
  191.                 if (typeof Id == "string") {
  192.                         //Look up Id in ItemIDs
  193.                         var i = this.ItemIDs.length;
  194.                         while (i--) {
  195.                                 if (Id == this.ItemIDs[i]) {
  196.                                         nId = i;
  197.                                         break;
  198.                                 }
  199.                         }
  200.                 } else nId = 1*Id;
  201.                 Interop.Call("user32", "CheckMenuItem", this.Handle, nId, MF_BYPOSITION | (bCheck ? MF_CHECKED : 0) );
  202.         },
  203.         /**
  204.          *      Opens the menu.
  205.          *            oPt      Array of the form[x,y]where x and y are the coordinates to open the menu. Optional.
  206.          *            oParam        Parameter to pass to the callback function with the menu item ID. Optional.
  207.          *            bRTL    Boolean specifying if the menu should be positioned for an RTL window. Optional.
  208.          *            nColor        COLORREF(0x00bbggrr) defining the background color of the menu. Optional.
  209.          *      Return value: True indicates success, otherwise false.
  210.          */
  211.         "Open" : function (oPt, oParam, bRTL, nColor) {
  212.                 oParam = (typeof oParam != "undefined") ? oParam : undefined;
  213.                 if (!this.IsMenuValid() ) return false;
  214.  
  215.                 //Set the position
  216.                 var POINTAPI = Interop.Allocate(8);
  217.                 if (typeof oPt == "object") {
  218.                         //Set given position
  219.                         POINTAPI.WriteDWORD(0, oPt[0]);
  220.                         POINTAPI.WriteDWORD(4, oPt[1]);
  221.                 } else {
  222.                         //Set current cursor position
  223.                         Interop.Call("user32", "GetCursorPos", POINTAPI);
  224.                 }
  225.                 //Get the subclass window
  226.                 if (!subclass) subclass = MsgPlus.CreateWnd('Languages\\en\\Subclass.xml', 'Subclass', /*WNDOPT_INVISIBLE*/ 2);
  227.  
  228.                 //Set the background color of the menu
  229.                 if (typeof nColor == "number") {
  230.                         var hBrush = Interop.Call("gdi32", "CreateSolidBrush", nColor);
  231.                         var MENUINFO = Interop.Allocate(28);
  232.                         MENUINFO.WriteDWORD(0, Size); //cbSize
  233.                         MENUINFO.WriteDWORD(4, MIM_APPLYTOSUBMENUS | MIM_BACKGROUND); //fMask
  234.                         MENUINFO.WriteDWORD(16, hBrush); //hBrush
  235.                         var Result = Interop.Call("user32", "SetMenuInfo", this.Handle, MENUINFO);
  236.                         MENUINFO.Size = 0;
  237.                         Interop.Call("gdi32", "DeleteObject", hBrush);
  238.                 }
  239.  
  240.                 //Open and retrieve clicked item
  241.                 var Flags = TPM_RETURNCMD | TPM_VERNEGANIMATION;
  242.                 if (typeof bRTL != "undefined") Flags |= bRTL ? TPM_RIGHTALIGN | TPM_LAYOUTRTL : TPM_LEFTALIGN;
  243.                 var Result = Interop.Call("user32", "TrackPopupMenu", this.Handle, Flags, POINTAPI.ReadDWORD(0), POINTAPI.ReadDWORD(4), 0, subclass.Handle, 0);
  244.                 POINTAPI.Size = 0;
  245.  
  246.                 this.Callback( (Result == 0) ? -1 : this.ItemIDs[(Result - MENU_ID_BASE) ], oParam);
  247.                 return true;
  248.         },
  249.         /**
  250.          *      Destroys the menu.
  251.          *      Return value: True indicates success, otherwise false.
  252.          */
  253.         "Destroy" : function () {
  254.                 //Destroy submenus first.
  255.                 if (this.SubMenus.length > 0) {
  256.                         var i = this.SubMenus.length;
  257.                         while (i--) this.SubMenus[i].Destroy();
  258.                 }
  259.  
  260.                 //Check if this menu can be destroyed.
  261.                 if (!this.IsMenuValid()) return false;
  262.  
  263.                 //Destroy the menu.
  264.                 Interop.Call("user32", "DestroyMenu", this.Handle);
  265.                 this.Handle = 0;
  266.  
  267.                 //Destroys all bitmaps associated with menu items.
  268.                 if (typeof this.Bitmaps === "object") {
  269.                         var i = this.Bitmaps.length;
  270.                         while (i--) DestroyBitmap(this.Bitmaps[i]);
  271.                 }
  272.  
  273.                 return true;
  274.         },
  275.         /**
  276.          *      Increases the menu's index and the index of its owner.
  277.          */
  278.         "IndexInc" : function (sItemID) {
  279.                 var nIndex = (this.Owner == false) ? this.Index : this.Owner.Index - this.Index;
  280.                 this.ItemIDs[nIndex] = sItemID;
  281.                 this.Index++;
  282.                 if (this.Owner != false) this.Owner.IndexInc(sItemID);
  283.         },
  284.         /**
  285.          *      Creates and sets the bitmap to a menu item. Used internally.
  286.          *            sBitmapPath   The path to an image file to add to the item.
  287.          *            uItem   The numeric identifier of the item.
  288.          *      Return value: True indicates success, otherwise false.
  289.          */
  290.         "SetBitmap" : function (sBitmapPath, uItem) {
  291.                 //Create the bitmap if it doesn't exist yet
  292.                 var hBitmap = 0;
  293.                 if (typeof this.Bitmaps[sBitmapPath] === "number") {
  294.                         hBitmap = this.Bitmaps[sBitmapPath];
  295.                 } else {
  296.                         hBitmap = GdiCreateHBITMAPFromFile(sBitmapPath);
  297.                         if (hBitmap == false) {
  298.                                 DestroyBitmap(hBitmap);
  299.                                 this.Bitmaps[sBitmapPath] = false;
  300.                                 return false;
  301.                         } else {
  302.                                 this.Bitmaps[sBitmapPath] = hBitmap;
  303.                         }
  304.                 }
  305.  
  306.                 //Set the bitmap to the menu item
  307.                 var MIIM_BITMAP = 0x80;
  308.                 var MENUITEMINFO = Interop.Allocate(48);
  309.                 MENUITEMINFO.WriteDWORD(0, Size);
  310.                 MENUITEMINFO.WriteDWORD(4, MIIM_BITMAP);
  311.                 MENUITEMINFO.WriteDWORD(44, hBitmap);
  312.                 var Result = Interop.Call("user32", "SetMenuItemInfoW", this.Handle, uItem, true, MENUITEMINFO);
  313.                 if (Result == 0) Debug.Trace("!!! Error occured while setting bitmap for item "+uItem+".");
  314.                 MENUITEMINFO.Size = 0;
  315.                 return(Result != 0);
  316.         },
  317.         /**
  318.          *      Sets the necessary properties of the menu. Used internally.
  319.          *      Return value: True indicates success, otherwise false.
  320.          */
  321.         "SetMenuInfo" : function () {
  322.                 var MENUINFO = Interop.Allocate(28);
  323.                 MENUINFO.WriteDWORD(0, MENUINFO.Size);
  324.                 var Result = Interop.Call("user32", "GetMenuInfo", this.Handle, MENUINFO);
  325.                 if (Result == 0) {
  326.                         MENUINFO.Size = 0;
  327.                         return false;
  328.                 }
  329.                 with (MENUINFO) {
  330.                         WriteDWORD(4, MIM_STYLE);
  331.                         WriteDWORD(8, ReadDWORD(8) | MNS_CHECKORBMP);
  332.                 }
  333.                 var Result = Interop.Call("user32", "SetMenuInfo", this.Handle, MENUINFO);
  334.                 MENUINFO.Size = 0;
  335.                 return(Result == 0);
  336.         },
  337.         /**
  338.          *      Checks if the current menu handle is valid. Used internally.
  339.          */
  340.         "IsMenuValid" : function () {
  341.                 return(typeof this.Handle == "number" && Interop.Call("user32", "IsMenu", this.Handle) != 0);
  342.         }
  343. }

Version

  • 5.0.0070_20100325_publicbeta1

Developers

Project Details

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

User Count

  • 162