AutoHotkey Community

It is currently May 27th, 2012, 12:29 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 82 posts ]  Go to page 1, 2, 3, 4, 5, 6  Next
Author Message
 Post subject: Menu wrapper library
PostPosted: February 3rd, 2009, 7:33 am 
Offline

Joined: November 4th, 2008, 9:23 am
Posts: 1045
Before I begin, word for the wise, there's a lot of information, but there is also a lot of functionality. I've done thorough testing, but that doesn't mean I thought of every "weird", "bizarre" combination of events that could result when dealing with menus. Thus, if you find a bug, please report it along with code that I can use to reproduce the problem. This way, I can fix it promptly and we can all get back to our regularly scheduled programming (ha ha... not funny?). Likewise, if the included documentation is in some way unclear, please ask any questions you have - I'm sure there are others with the same question, and I will post a description as well as modify the documentation to make it more clear.

Ok, let's begin. This library makes use of my Class Library (which adds OOP (Object-Oriented Programming) to AHK). The needed Class.ahk is included in the zip, found here. By merging the Class Library with the Menu wrapper, it allows you to associate values with a menu or menu item (see included MenuLibraryTest.ahk for as an example).


How to use the menu wrapper in your own projects:

Unzip the files to a Library Folder. Included is a file, MenuLibraryTemplate.ahk. This template shows the necessary functions / function calls to setup the menu library. These functions must be included in each ahk file that makes use of the Menu wrapper library. You can easily include the file in your auto-exec section.

For project-specific functionality, make a copy of the template for each of your projects. Modify the copy of the template according to your needs. See the included MenuLibraryTest.ahk and MenuLibraryTestSetup.ahk (modified template) as an example.

Another feature is that the menu wrapper has a modified version of Lexikos' Menu Icons included that incorporates all features in his menu icon library with the functionality of my menu wrapper. Also, the wrapper automatically frees the icons, as appropriate, so you don't have to. The function names are unaltered (to integrate seamlessly into your existing code). Also, you don't have to move MI.ahk from where it is stored, because when the code calls Menu_setUserDefinedSize and MenuItem_setUserDefinedSize (from the template), it will include all the functions (including Lexikos' Menu Icons found in MenuItem.ahk) into your script.

See the included ReadMe for a list of functions and their use.

The following functions are not wrapped, and you can use normal AHK syntax for. All others, require the use of its respective wrapper function.

Rename, Check, Uncheck, ToggleCheck, Enable, Disable, Default, Icon, NoIcon, Tip, Color, MainWindow, and NoMainWindow

_________________
As always, if you have any further questions, don't hesitate to ask.

Add OOP to your scripts via the Class Library. Check out my scripts.


Last edited by animeaime on February 16th, 2009, 2:50 am, edited 2 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 4th, 2009, 4:57 pm 
Offline

Joined: November 4th, 2008, 9:23 am
Posts: 1045
Since this behavior is different from AHKs, I'll document it here. When the menu is being shown (as called by MI_ShowMenu(MenuNameOrHandle, x = "", y = ""), timers will still activate. Please take appropriate measures if this action is not desired. Since I will be adding functionality which requires this behavior, I will not be adding a fix for this. I am looking at if I can use Thread, NoTimers to provide a fix (for those that want it), and if it can be done, I'll document how to achieve this behavior.

Revision3:
    Mod: For functions that have a ByPosition parameter
    specify -1 to treat MenuItem as an item handle
    specify 0 (or false) to treat MenuItem as a menu item name
    specify 1 (or true) to treat MenuItem as a position

    If MenuItem is not a parameter, then these specify the return type.
    other values are reserved for compatibility with future versions

    Mod: Menu_selectMenuItem(hMenuItem, hwnd = 0)

    Values for hwnd:
    0 - to click an AHK menu item
    the empty string ("") - to click the menu item in the Last Found Window
    else, the hwnd (window unique ID) for the window

    Mod: For functions that take MenuNameOrHandle, the Position (if included) can be one of these:
    1) If an integer, the item's position (starts at 1)
    2) "h" followed by the item's handle (an integer) - as returned from Menu_getMenuItemHandle

    Add: Menu_GetMenuHandle function

    Menu_GetMenuHandle(MenuName)
    wraps MI_getMenuHandle so even if menu doesn't exist, an error won't occur

    Mod: Menu_getMenuItemHandle

    Menu_getMenuItemHandle(MenuNameOrHandle, Position, ByRef ThisMenu = 0)
    returns the menu item's handle for the menu item at the specified Position in the specified menu
    (-1 is returned if the menu item opens a submenu, or if an invalid position is given)

    Position can be an integer,
    or a comma-delimited list of Positions (each that will "wrap")

    The list is the "road map" of menu items (all of which are submenus)
    that lead to the last position, which must be a menu item.

    Add: Menu_getMenu

    Menu_getMenu(hwnd = "")
    returns the menu handle for the menu bar of for the specified window

    the hwnd is the same as the window's unique ID
    (you can use a function call, i.e. WinExist, to retrieve this value)

    if hwnd is not specified (or 0), the Last Found Window will be used
Revision2:
I'm going to lump the updates into one big set and call it Revision2

The codes design is now modified to make it more "user-friendly" and easy to implement into your own projects. The files Menu.ahk, MenuItem.ahk, Class.ahk, and MenuLibrarySetup.ahk should all go into your library folder. Then, make a copy of MenuLibraryTemplate, add any values you want to associate with a menu / menu item (see included MenuLibraryTest.ahk and MenuLibraryTestSetup.ahk as a model). MenuLibraryTestSetup is the Template with added associated values. MenuLibraryTest is the menu construction.

There were several fixes since the last revision:
    Fix: Menu_LoadDllFunction now correctly only returns "positive addresses"

    Fix: Menu_Standard now works on a menu that hasn't been created yet

    Fix: Menu_DeleteAll retains the "standard menu" items, if any

    Mod: Cached remaining DllCall addresses (as suggested in the DllCall docs as an optimization)

Revision1:

Here's an update of the menu library that includes wrapper functions Menu_Standard(MenuName) and Menu_NoStandard(MenuName) for Menu, MenuName, Standard/NoStandard, as well as some other useful features. You can download the zip from here.

The previous release is no longer supported as I had to modify certain core elements in order to have Standard/NoStandard to function correctly without having AHK recreate the menu (and causing a BIG mess). See the updated MenuLibraryTemplate.ahk (you may need to refresh if the page is in your cache).

From this release on, Menu,, click must use the wrapper function Menu_Click(ClickCount = ""). Specify 1 for ClickCount to allow a single-click to activate the tray menu's default menu item. Specify 2 for ClickCount to return to the default behavior (double-click). Also, now you can specify 0 to disable clicking the tray icon from activating the tray menu's default menu item. Regardless, the previous "ClickCount" is returned. This value starts off at 2 in accordance with AHK documentation.

Also, Menu,NameName, NoDefault must use its wrapper function Menu_NoDefault(MenuName). Note: You can still use Menu, MenuName, Default, MenuItemName to set the default item. However, you can NOT use Menu, MenuName, Default to "clear" it - use Menu_NoDefault(MenuName) instead.

Also, there is an added function Menu_Default(MenuNameOrHandle, ItemHandleOrPosition, ByPosition = true), which can be used to set a default item based on position (or item handle) instead of by MenuItemName. If ByPosition is "true", ItemHandleOrPosition is interpreted as the item's position. If ByPosition is "false", ItemHandleOrPosition is interpreted as the item's handle.

There is also a function, Menu_getDefault(MenuNameOrHandle, ByPosition = true) which will return the current default item for the menu. If ByPosition is "true", the position (in the menu) for the default item is returned (0 if there is no default item). If ByPosition is "false", then the item's handle is returned (-1 if there is no default item).

There is also a function, Menu_selectMenuItem(hMenuItem) which sends a message to the script to "select" (as if by clicking on the menu) a menu item. You can retrieve an item handle from a call to Menu_getMenuItemHandle(MenuNameOrHandle, Position)

Edit:
Forgot to mention these two facts

1) Standard menu items such as Exit CAN now be individually deleted
2) You can now use Menu, MenuName, Default, MenuItemName to set an item with a submenu as the default (purely cosmetic).

_________________
As always, if you have any further questions, don't hesitate to ask.

Add OOP to your scripts via the Class Library. Check out my scripts.


Last edited by animeaime on February 16th, 2009, 3:07 am, edited 9 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 4th, 2009, 5:31 pm 
Offline
User avatar

Joined: September 8th, 2008, 12:26 am
Posts: 1048
Location: Ploieşti, RO
Could be my OS version's fault (Win98SE), but I'm getting an error on running the test script. All files are updated with the ones in the above-mentioned zip.

Error is in MenuItem.ahk, line 402: Submenu does not exist. Specifically: Menu2.

_________________
AHK tools by Drugwash (AHK 1.0.48.05 and Win98SE)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 4th, 2009, 7:46 pm 
Offline

Joined: November 4th, 2008, 9:23 am
Posts: 1045
Ok, I'm running vista so I'm relying on running AHK with compatability for testing. Besides the fact that I had to have an include for each of Menu.ahk, MenuItem.ahk, and Class.ahk, and MenuLibraryTemplate, it ran MenuLibraryTest with no problems. Did you have to manually include them, or did it do so automatically (provided you put them in a library folder)?

I uploaded the latest files, download the zip, here. This version runs fine on my computer (when tested in compatability mode) and includes a bug fix. It seems that if AHK doesn't "think" there are menu items in the menu, it won't display a menu. This means that when using Menu_Standard (which adds menu items without relying on AHK), AHK won't show the menu if that is its only contents. The posted files fix that error.

Also, I redesigned the code. Now, there is a single copy of the template (store also in a library folder for easy inclusion). Now, MenuTestSetup.ahk ONLY has project-specific values (and the call to MenuLibraryTemplate() to initialize the necessary values and include the template automatically - if it resides in your library folder). See the updated example for a model to follow for your own code. This way, you only need to update Menu.ahk, MenuItem.ahk, Class.ahk, and MenuLibraryTemplate.ahk and your code will use the latest functionality. Sorry about the previous setup - don't know where my brain was at.

So, hopefully this latest version will run for you. If not, please run this modified test, which will output something before it touches Menu2. Please post the outputs to the message boxes, in order, so that I can find the source of the problem. My guess is that you're right it's because your OS, but there is probably a fix I can include so that this library works for you. Hopefully you don't mind being my tester :D

Edit:
The zip now contains a copy of the required Class.ahk.

_________________
As always, if you have any further questions, don't hesitate to ask.

Add OOP to your scripts via the Class Library. Check out my scripts.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 4th, 2009, 11:09 pm 
Offline
User avatar

Joined: September 8th, 2008, 12:26 am
Posts: 1048
Location: Ploieşti, RO
I've been testing alpha software for a few years, it's already a lifestyle for me. :) Thank you for taking the time to help and sorry for being a burdain.

The required files (Class, Menu, MenuItem and MenuLibraryTemplate) are in the lib subfolder of the AHK installation folder. The new test exhibits the same error so I tested the modified one afterwards. Message boxes were in order: Menu_MoveEx, Menu_IsChecked and then the error in line 402.

There's now an extra file (debug, probably) called MemoryLog.mem which contains Alloc: a couple dozen times.

I've put a couple if checks in the code and now there's no error anymore, just a message box stating isChecked?:
Code:
if menu_name not in Menu2
    Menu, menuDummy, Add, :%menu_name%
    h_menu := DllCall( "GetSubMenu", "uint", h_menuDummy, "int", 0 )
    DllCall( "RemoveMenu", "uint", h_menuDummy, "uint", 0, "uint", 0x400 )
if menu_name not in Menu2
    Menu, menuDummy, Delete, :%menu_name%

Still, there's only a bold X in front of the Exit menu item and all other items have empty space in front of them.

_________________
AHK tools by Drugwash (AHK 1.0.48.05 and Win98SE)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 4th, 2009, 11:16 pm 
Offline

Joined: November 4th, 2008, 9:23 am
Posts: 1045
Yeah, the MemoryLog.mem is to check the allocations and frees - to check for memory leaks. I just removed them from Class.ahk and updated Class.ahk in Menu.zip. The Class.ahk file in Menu.zip doesn't have them anymore. Thanks for that.

I'll look into the code and see if I can't find what's causing the problem. Please bear with me as I add a fix.

PS:
You're not a burden - if anything you're a lifesaver. This code may be used in programs needing to run on Win98, so thank you for being available for testing.

_________________
As always, if you have any further questions, don't hesitate to ask.

Add OOP to your scripts via the Class Library. Check out my scripts.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 4th, 2009, 11:28 pm 
Offline

Joined: November 4th, 2008, 9:23 am
Posts: 1045
OK, Since it crashes before isChecked works, this implies that the item wasn't moved. Can you run this script and tell me if the values in comments are returned.

Code:
#NoEnv ;Must be specified to work - tried to find out why, no luck
#Include MenuLibraryTestSetup.ahk

Menu_add("Tray", "Item1", "DoNothing")

;should be some non-zero value
;if this outputs either a blank or a zero there's a problem
;(if so, which is it a blank or a zero?)
MsgBox, % Menu_moveEx("Tray", 0, "Menu2", 0)

;should output 1
;if not, then the move wasn't successful
MsgBox, % Menu_getMenuSize_Private("Menu2")
return

DoNothing:
return

_________________
As always, if you have any further questions, don't hesitate to ask.

Add OOP to your scripts via the Class Library. Check out my scripts.


Last edited by animeaime on February 4th, 2009, 11:31 pm, edited 1 time in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 4th, 2009, 11:28 pm 
Offline
User avatar

Joined: September 8th, 2008, 12:26 am
Posts: 1048
Location: Ploieşti, RO
Anytime. ;)

Got a couple zero message boxes with the above script.

_________________
AHK tools by Drugwash (AHK 1.0.48.05 and Win98SE)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 4th, 2009, 11:33 pm 
Offline

Joined: November 4th, 2008, 9:23 am
Posts: 1045
So both output "0"? ok, that's the problem.

how about this?

Code:
#NoEnv ;Must be specified to work - tried to find out why, no luck
#Include MenuLibraryTestSetup.ahk

Menu_add("Tray", "Item1", "DoNothing")

MsgBox, % Menu_getMenuSize("tray")

DoNothing:
return


Also, do you see the standard menu items?

_________________
As always, if you have any further questions, don't hesitate to ask.

Add OOP to your scripts via the Class Library. Check out my scripts.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 4th, 2009, 11:51 pm 
Offline
User avatar

Joined: September 8th, 2008, 12:26 am
Posts: 1048
Location: Ploieşti, RO
The result of the above script is blank message box.
The standard menu items are all present.


I've squeezed the DllCallDebugger in the Class script and guess what: it started spitting error -4 one after another. Now, I'm not 100% sure the debugger works correctly because I didn't have time to test it; this was the first time I actually tried to put it at work. But I feel the problem is somewhere in the DllCalls and most likely in Class.ahk.
Code:
Class_Alloc(size)
{
    static AlreadyDone, HeapAlloc, ProcessHeap

    if (!AlreadyDone)
    {
        AlreadyDone := true
        HeapAlloc := Class_LoadDllFunction("Kernel32", "HeapAlloc")
DllCallDebugger()

        ProcessHeap := DllCall("GetProcessHeap")
    }

If the script output until the Menu2 error can be of any use for you, here it is:
Code:
Script lines most recently executed (oldest first).  Press [F5] to refresh.  The seconds elapsed between a line and the one after it is in parentheses to the right (if not 0).  The bottommost line's elapsed time is the number of seconds since it executed.

087: Class_setString(MenuItemObject, "b2", MenuItemLabel) 
590: Class_setValue(ClassObject, index, data, "String") 
597: if (!ClassObject) 
598: Return
591: }
088: }
367: VarSetCapacity(mii, 48, 0), NumPut(48, mii), NumPut(4, mii, 4) 
369: if (subMenu) 
372: Menu_SetMenuItemInfo(hMenu, Position, mii) 
1347: if MenuNameOrHandle is integer
1348: hMenu := MenuNameOrHandle
1352: if (!hMenu) 
1355: if (!Position := Menu_getIndex(Position, Menu_getMenuItemCount(hMenu))) 
1168: if (!GetMenuItemCount) 
1171: Return,DllCall(GetMenuItemCount, "uInt", hMenu)
078: ListLines (0.01)
061: Critical
063: id := wParam & 0xFFFF
065: if id in 65306,65403
080: }
080: Call = DllCall(
081: Loop,aParamCount
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """") 
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """") 
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """") 
086: Call.=")" 
088: MsgBox,DllCall failed with ErrorLevel = %ErrorLevel%

     Specifically: %Call% (0.01)
061: Critical
063: id := wParam & 0xFFFF
065: if id in 65306,65403
080: } (0.53)
061: Critical
063: id := wParam & 0xFFFF
065: if id in 65306,65403
080: } (0.01)
089: }
249: if (ThisSize = 0) 
251: if (ThisIndex > 0) 
253: if (ThisIndex = 0) 
254: Return,ThisSize
1356: Return
374: Return,MenuItem
051: MI_SetMenuItemIcon("Menu1", 5, A_AhkPath, 5, 16) 
213: unused1 = 0
214: unused2 = 0
216: if MenuNameOrHandle is integer
219: h_menu := MI_GetMenuHandle(MenuNameOrHandle)
383: if !h_menuDummy 
403: Menu,menuDummy,Add,:%menu_name%
404: h_menu := DllCall( "GetSubMenu", "uint", h_menuDummy, "int", 0 )
405: DllCall( "RemoveMenu", "uint", h_menuDummy, "uint", 0, "uint", 0x400 ) 
407: Menu,menuDummy,Delete,:%menu_name%
409: Return,h_menu
221: if !h_menu 
224: if FilenameOrHICON is integer
237: {
240: if !(loaded_icon := h_icon := MI_ExtractIcon(FilenameOrHICON, IconNumber, IconSize)) 
443: if A_OSVersion in WIN_VISTA,WIN_2003,WIN_XP,WIN_2000
461: if DllCall("shell32.dll\ExtractIconExA","str",Filename,"int",IconNumber-1,"uint*",h_icon,"uint*",h_icon_small,"uint",1)   (0.00)
463: {
464: SysGet,SmallIconSize,49
467: if (IconSize <= SmallIconSize) 
467: {
468: DllCall("DestroyIcon","uint",h_icon) 
469: h_icon := h_icon_small
470: }
475: if (h_icon && IconSize) 
476: h_icon := DllCall("CopyImage","uint",h_icon,"uint",1,"int",IconSize,"int",IconSize,"uint",4|8)
478: }
480: Return,h_icon ? h_icon : 0
242: }
249: use_bitmap := (A_OSVersion="WIN_VISTA")
252: VarSetCapacity(mii,48,0), NumPut(48,mii), NumPut(0xA0,mii,4) 
253: if DllCall("GetMenuItemInfo","uint",h_menu,"uint",ItemPos-1,"uint",1,"uint",&mii) 
255: h_previous := use_bitmap ? NumGet(mii,44,"int") : MenuItem_getIconHandle(NumGet(mii,32))
072: Return,Class_getValue(MenuItemObject, "b1")
554: if (!ClassObject) 
555: Return
257: if use_bitmap 
282: {
288: if (h_icon) 
289: {
290: if (!MenuItem := NumGet(mii, 32)) 
291: {
293: MenuItem := MenuItem_new("")
108: if (UserDefinedSize = "") 
109: UserDefinedSize := MenuItem_setUserDefinedSize()
095: if (Size != "") 
098: Return,UserDefinedSize
112: if (MenuItemObject := Class_Alloc(4 * UserDefinedSize + BuiltInSize)) 
032: if (!AlreadyDone) 
040: start := subStr(size, 1,1 )
042: if (start >= "0" && start <= "9") 
043: {
045: size += 8
046: }
058: addr := DllCall(HeapAlloc, "uint", ProcessHeap, "uint", 0x8, "uint", size)
078: ListLines (0.01)
061: Critical
063: id := wParam & 0xFFFF
065: if id in 65306,65403 (0.00)
080: }
080: Call = DllCall(
081: Loop,aParamCount
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """") 
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """") 
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """") 
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """") 
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """") 
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """") 
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """") 
086: Call.=")" 
088: MsgBox,DllCall failed with ErrorLevel = %ErrorLevel%

     Specifically: %Call% (0.02)
061: Critical
063: id := wParam & 0xFFFF
065: if id in 65306,65403
080: } (0.52)
061: Critical
063: id := wParam & 0xFFFF
065: if id in 65306,65403
080: } (0.00)
089: }
059: FileAppend,Alloc: %addr%
,MemoryLog.mem
060: Return,addr
125: Return,MenuItemObject
296: NumPut(MenuItem, mii, 32) 
297: }
304: MenuItem_setIconHandle(MenuItem, h_icon) 
077: Class_setValue(MenuItemObject, "b1", h_icon) 
597: if (!ClassObject) 
598: Return
078: }
305: }
307: NumPut(-1,mii,44) 
308: }
310: if DllCall("SetMenuItemInfo","uint",h_menu,"uint",ItemPos-1,"uint",1,"uint",&mii) 
311: {
313: if use_bitmap 
318: DllCall("DestroyIcon","uint",h_previous) 
320: Return,true
052: MenuItem_setValue1(MenuItem, "Menu1->Item5") 
029: Class_setString(MenuItemObject, 1, Value1) 
590: Class_setValue(ClassObject, index, data, "String") 
597: if (!ClassObject) 
598: Return
591: }
030: }
053: MenuItem_setValue2(MenuItem, 5) 
039: Class_setValue(MenuItemObject, 2, Value2, "uint") 
597: if (!ClassObject) 
598: Return
040: }
058: Menu_Insert(1, "tray", "Menu1", ":Menu1") 
305: OldMenuSize := Menu_getMenuSize_private(MenuName, hMenu)
1078: Old_Menu_UseErrorLevel := Menu_UseErrorLevel(true)
999: Old_Menu_UseErrorLevel := Menu_UseErrorLevel
1001: if (UseErrorLevel != "") 
1002: {
1003: Menu,tray,UseErrorLevel,(UseErrorLevel) ? "" : "Off"
1004: Menu_UseErrorLevel := UseErrorLevel
1005: }
1007: Return,Old_Menu_UseErrorLevel
1081: if (hMenu := MI_getMenuHandle(MenuName)) 
383: if !h_menuDummy 
403: Menu,menuDummy,Add,:%menu_name%
404: h_menu := DllCall( "GetSubMenu", "uint", h_menuDummy, "int", 0 )
405: DllCall( "RemoveMenu", "uint", h_menuDummy, "uint", 0, "uint", 0x400 ) 
407: Menu,menuDummy,Delete,:%menu_name%
409: Return,h_menu
1082: MenuSize := Menu_getMenuItemCount(hMenu)
1168: if (!GetMenuItemCount) 
1171: Return,DllCall(GetMenuItemCount, "uInt", hMenu)
078: ListLines (0.01)
061: Critical
063: id := wParam & 0xFFFF
065: if id in 65306,65403
080: }
080: Call = DllCall(
081: Loop,aParamCount
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """")   (0.00)
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """") 
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """") 
086: Call.=")" 
088: MsgBox,DllCall failed with ErrorLevel = %ErrorLevel%

     Specifically: %Call% (0.01)
061: Critical
063: id := wParam & 0xFFFF
065: if id in 65306,65403
080: } (0.62)
061: Critical
063: id := wParam & 0xFFFF
065: if id in 65306,65403
080: } (0.01)
089: }
1087: Menu_UseErrorLevel(Old_Menu_UseErrorLevel) 
999: Old_Menu_UseErrorLevel := Menu_UseErrorLevel
1001: if (UseErrorLevel != "") 
1002: {
1003: Menu,tray,UseErrorLevel,(UseErrorLevel) ? "" : "Off"
1004: Menu_UseErrorLevel := UseErrorLevel
1005: }
1007: Return,Old_Menu_UseErrorLevel
1089: Return,MenuSize
308: if (MenuItemLabel = "") 
317: if (subStr(MenuItemLabel, 1, 1) = ":") 
318: {
320: SubMenu := subStr(MenuItemLabel, 2)
322: if (!hSubMenu := MI_GetMenuHandle(SubMenu)) 
383: if !h_menuDummy 
403: Menu,menuDummy,Add,:%menu_name%
404: h_menu := DllCall( "GetSubMenu", "uint", h_menuDummy, "int", 0 )
405: DllCall( "RemoveMenu", "uint", h_menuDummy, "uint", 0, "uint", 0x400 ) 
407: Menu,menuDummy,Delete,:%menu_name%
409: Return,h_menu
328: Menu,%MenuName%,add,%MenuItemName%,_
330: if (ErrorLevel && Menu_UseErrorLevel()) 
335: }
348: if (!hMenu) 
355: if (OldMenuSize = MenuSize := Menu_getMenuItemCount(hMenu)) 
1168: if (!GetMenuItemCount) 
1171: Return,DllCall(GetMenuItemCount, "uInt", hMenu)
078: ListLines (0.01)
061: Critical
063: id := wParam & 0xFFFF
065: if id in 65306,65403
080: }
080: Call = DllCall(
081: Loop,aParamCount
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """") 
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """") 
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """") 
086: Call.=")" 
088: MsgBox,DllCall failed with ErrorLevel = %ErrorLevel%

     Specifically: %Call% (0.02)
061: Critical
063: id := wParam & 0xFFFF
065: if id in 65306,65403
080: } (0.54)
061: Critical
063: id := wParam & 0xFFFF
065: if id in 65306,65403
080: } (0.01)
089: }
356: {
358: Position := Menu_indexOf(hMenu, MenuItemName)
268: if (MenuItemName = "") 
271: if MenuNameOrHandle is integer
272: hMenu := MenuNameOrHandle
276: if (!hMenu) 
279: Loop,Menu_getMenuSize(hMenu)
1062: if MenuNameOrHandle is integer
1063: hMenu := MenuNameOrHandle
1067: if (!hMenu) 
1070: Return,Menu_getMenuItemCount(hMenu)
1168: if (!GetMenuItemCount) 
1171: Return,DllCall(GetMenuItemCount, "uInt", hMenu)
078: ListLines (0.01)
061: Critical
063: id := wParam & 0xFFFF
065: if id in 65306,65403
080: }
080: Call = DllCall(
081: Loop,aParamCount
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """") 
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """") 
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """") 
086: Call.=")" 
088: MsgBox,DllCall failed with ErrorLevel = %ErrorLevel%

     Specifically: %Call% (0.01)
061: Critical
063: id := wParam & 0xFFFF
065: if id in 65306,65403
080: } (0.45)
061: Critical
063: id := wParam & 0xFFFF
065: if id in 65306,65403
080: } (0.00)
089: }
291: Return,0
361: MenuItem := Menu_getMenuItemObject(hMenu, Position)
1131: if MenuNameOrHandle is integer
1132: hMenu := MenuNameOrHandle
1136: if (!Position := Menu_getIndex(Position, Menu_getMenuItemCount(hMenu))) 
1168: if (!GetMenuItemCount) 
1171: Return,DllCall(GetMenuItemCount, "uInt", hMenu)
078: ListLines (0.01)
061: Critical
063: id := wParam & 0xFFFF
065: if id in 65306,65403
080: }
080: Call = DllCall(
081: Loop,aParamCount
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """") 
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """") 
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """") 
086: Call.=")" 
088: MsgBox,DllCall failed with ErrorLevel = %ErrorLevel%

     Specifically: %Call% (0.01)
061: Critical
063: id := wParam & 0xFFFF
065: if id in 65306,65403
080: } (0.52)
061: Critical
063: id := wParam & 0xFFFF
065: if id in 65306,65403
080: } (0.01)
089: }
249: if (ThisSize = 0) 
251: if (ThisIndex > 0) 
253: if (ThisIndex = 0) 
254: Return,ThisSize
1137: Return
364: MenuItem_setMenuItemLabel(MenuItem, MenuItemLabel) 
087: Class_setString(MenuItemObject, "b2", MenuItemLabel) 
590: Class_setValue(ClassObject, index, data, "String") 
597: if (!ClassObject) 
598: Return
591: }
088: }
367: VarSetCapacity(mii, 48, 0), NumPut(48, mii), NumPut(4, mii, 4) 
369: if (subMenu) 
370: NumPut(hSubMenu, mii, 20) 
372: Menu_SetMenuItemInfo(hMenu, Position, mii) 
1347: if MenuNameOrHandle is integer
1348: hMenu := MenuNameOrHandle
1352: if (!hMenu) 
1355: if (!Position := Menu_getIndex(Position, Menu_getMenuItemCount(hMenu))) 
1168: if (!GetMenuItemCount) 
1171: Return,DllCall(GetMenuItemCount, "uInt", hMenu)
078: ListLines (0.01)
061: Critical
063: id := wParam & 0xFFFF (0.00)
065: if id in 65306,65403
080: }
080: Call = DllCall(
081: Loop,aParamCount
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """") 
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """") 
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """") 
086: Call.=")" 
088: MsgBox,DllCall failed with ErrorLevel = %ErrorLevel%

     Specifically: %Call% (0.02)
061: Critical
063: id := wParam & 0xFFFF
065: if id in 65306,65403
080: } (0.52)
061: Critical
063: id := wParam & 0xFFFF
065: if id in 65306,65403
080: } (0.01)
089: }
249: if (ThisSize = 0) 
251: if (ThisIndex > 0) 
253: if (ThisIndex = 0) 
254: Return,ThisSize
1356: Return
374: Return,MenuItem
062: Menu_Move("Menu1", 1, 0) 
420: if MenuNameOrHandle is integer
423: hMenu := MI_getMenuHandle(MenuNameOrHandle)
383: if !h_menuDummy 
403: Menu,menuDummy,Add,:%menu_name%
404: h_menu := DllCall( "GetSubMenu", "uint", h_menuDummy, "int", 0 )
405: DllCall( "RemoveMenu", "uint", h_menuDummy, "uint", 0, "uint", 0x400 ) 
407: Menu,menuDummy,Delete,:%menu_name%
409: Return,h_menu
425: if (!hMenu) 
428: if (!MenuSize := Menu_getMenuItemCount(hMenu)) 
1168: if (!GetMenuItemCount) 
1171: Return,DllCall(GetMenuItemCount, "uInt", hMenu)
078: ListLines (0.01)
061: Critical
063: id := wParam & 0xFFFF
065: if id in 65306,65403
080: }
080: Call = DllCall(
081: Loop,aParamCount
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """") 
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """") 
082: P:=NumGet(aParam+A_Index*4-4),V:=DllCallDebugger_TokenValue(P+0),T:=NumGet(P+8),Call.=(A_Index>1 ? ", ":"") . (T=1||T=2 ? V : """" V """") 
086: Call.=")" 
088: MsgBox,DllCall failed with ErrorLevel = %ErrorLevel%

     Specifically: %Call% (0.01)
061: Critical
063: id := wParam & 0xFFFF
065: if id in 65306,65403
080: } (0.48)
061: Critical
063: id := wParam & 0xFFFF
065: if id in 65306,65403 (0.00)
080: } (0.01)
089: }
429: Return,0
066: Menu_MoveEx("Menu1", 1, "Menu2", 0) 
487: if (FromMenuName = ToMenuName) 
490: if (!hFrom := MI_getMenuHandle(FromMenuName)) 
383: if !h_menuDummy 
403: Menu,menuDummy,Add,:%menu_name%
404: h_menu := DllCall( "GetSubMenu", "uint", h_menuDummy, "int", 0 )
405: DllCall( "RemoveMenu", "uint", h_menuDummy, "uint", 0, "uint", 0x400 ) 
407: Menu,menuDummy,Delete,:%menu_name%
409: Return,h_menu
493: if (!FromMenuSize := Menu_getMenuItemCount(hFrom)) 
1168: if (!GetMenuItemCount) 
1171: Return,DllCall(GetMenuItemCount, "uInt", hMenu)
078: ListLines (0.00)

Press [F5] to refresh.

_________________
AHK tools by Drugwash (AHK 1.0.48.05 and Win98SE)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 5th, 2009, 12:11 am 
Offline

Joined: November 4th, 2008, 9:23 am
Posts: 1045
Wow, thanks. So, the -4 is the ErrorLevel? I was wondering if my memory allocations were too new...

I think I know why....I just looked up HeapAlloc and it needs Windows 2000 Professional.

So... what does this code output? The value for addr should be non-zero

Code:
addr := DllCall("GlobalAlloc", "uint", 0x40, "uint", 4)
MsgBox, % addr . " " . ErrorLevel . " " . A_LastError


And this? The value for ProcessHeap and addr should be non-zero

Code:
ProcessHeap := DllCall("GetProcessHeap")
MsgBox, % ProcessHeap . " " . ErrorLevel . " " . A_LastError
addr := DllCall("HeapAlloc", "uint", ProcessHeap, "uint", 0x8, "uint", 4)
MsgBox, % addr . " " . ErrorLevel . " " . A_LastError

_________________
As always, if you have any further questions, don't hesitate to ask.

Add OOP to your scripts via the Class Library. Check out my scripts.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 5th, 2009, 12:22 am 
Offline
User avatar

Joined: September 8th, 2008, 12:26 am
Posts: 1048
Location: Ploieşti, RO
First code outputs 4793420 0 0
Second code outputs 4784128 0 0 then 4796080 0 0.

I seem to have HeapAlloc among the exported functions in kernel32.dll but may be (although unlikely) altered by some unofficial patch. Could require different parameters...

_________________
AHK tools by Drugwash (AHK 1.0.48.05 and Win98SE)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 5th, 2009, 12:34 am 
Offline

Joined: November 4th, 2008, 9:23 am
Posts: 1045
well since you are getter non-zero (and both error checks are zero), then both GlobalAlloc and HeapAlloc work.

So, it might be the LoadLibrary functions you might lack...

Since you have the standard items, InsertMenu_private works. I forgot to cache the dll addresses for that function, so it will work fine even if LoadLibrary doesn't. However, it seems that others like Menu_getMenuSize() which uses a cached dll address won't. Hopefully, it's the LoadLibrary that's the problem. If so, at least the problem is found. Maybe I can't cache the addresses for Win98 (or will have to find another way).

which does this output?

Code:
HeapAlloc := Class_LoadDllFunction("Kernel32", "HeapAlloc")
MsgBox, % HeapAlloc . " " . ErrorLevel . " " . A_LastError


If HeapAlloc is zero or ErrorLevel / A_LastError is non-zero, run this.

Code:
if !(hModule := DllCall("GetModuleHandle", "uint", &ThisFile))
{
    MsgBox, % hModule . " " . ErrorLevel . " " . A_LastError
    hModule := DllCall("LoadLibrary", "uint", &ThisFile)
}

MsgBox, % hModule . " " . ErrorLevel . " " . A_LastError
returnValue := DllCall("GetProcAddress", "uint", hModule, "uint", &ThisFunction)
MsgBox, % returnValue . " " . ErrorLevel . " " . A_LastError

_________________
As always, if you have any further questions, don't hesitate to ask.

Add OOP to your scripts via the Class Library. Check out my scripts.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 5th, 2009, 12:51 am 
Offline
User avatar

Joined: September 8th, 2008, 12:26 am
Posts: 1048
Location: Ploieşti, RO
This is strange... I'm getting a negative number. :?
-1074303292 0 0
Could this be a signed integer or is HeapAlloc going nuts?

To be on the safe side, I've run the second script too. Results:
1. 0 0 126
2. 0 0 1157
3. 0 0 6

_________________
AHK tools by Drugwash (AHK 1.0.48.05 and Win98SE)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 5th, 2009, 1:00 am 
Offline

Joined: November 4th, 2008, 9:23 am
Posts: 1045
yeah, it's signed since there is no return type specified, so it uses int. It's converted to a "uint" when needed, but it might be better to return a uint, so I'll do that.

Oops... I forgot to specify the filename and function.... sorry about that.

Code:
ThisFile := "Kernel32"
ThisFunction := "HeapAlloc"

if !(hModule := DllCall("GetModuleHandle", "uint", &ThisFile))
{
    MsgBox, % hModule . " " . ErrorLevel . " " . A_LastError
    hModule := DllCall("LoadLibrary", "uint", &ThisFile)
}

MsgBox, % hModule . " " . ErrorLevel . " " . A_LastError
returnValue := DllCall("GetProcAddress", "uint", hModule, "uint", &ThisFunction)
MsgBox, % returnValue . " " . ErrorLevel . " " . A_LastError

_________________
As always, if you have any further questions, don't hesitate to ask.

Add OOP to your scripts via the Class Library. Check out my scripts.


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 82 posts ]  Go to page 1, 2, 3, 4, 5, 6  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: Bon, SKAN and 5 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group