AutoHotkey Community

It is currently May 26th, 2012, 2:58 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 132 posts ]  Go to page Previous  1 ... 3, 4, 5, 6, 7, 8, 9  Next
Author Message
 Post subject:
PostPosted: February 2nd, 2009, 3:20 pm 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7502
Location: Australia
animeaime wrote:
When AHK recreates the menu, it doesn't save ALL the info
Technically, none of the properties of the Win32 menu are retained. AutoHotkey keeps all of the properties it knows about in its internal UserMenu and UserMenuItem structures.
Quote:
Thus, if you could add the ability to retain the dwItem/MenuData when recreating the menu, that would be AWE-SOME.
As I meant to suggest in my previous post, if there were some built-in method to associate user-data with a menu or menu item, dwItem/MenuData would not be necessary. Item data would be stored in the UserMenuItem structure, along with item text, submenu, icon, etc. This might be easier to implement than some method of retaining dwItem/MenuData, or any other properties associated with the menu handle.
Quote:
so you don't need to worry about the ability to associate data with a menu, because I have that covered.
That is, apart from the pitfalls we have discussed?
Quote:
Right now, I have a "hack" of adding a menu separator, storing the old size, deleting the "temp" separator (and decreasing the old size by one), adding the item, comparing the old/new size, and then, from that, knowing if the menu item was added or only updated.
Is the separator merely because the menu may be empty or non-existent, and therefore not have a valid menu handle? Otherwise, why not simply compare the item count before and after Add?
Quote:
MIIM_ID (do you know what this is for?).
"Application-defined 16-bit value that identifies the menu item. Set fMask to MIIM_ID to use wID." I believe AutoHotkey uses the ID's internally.
Quote:
just need to find a way to remove a submenu without AHK destroying it on me :wink:
If you mean remove a menu item without destroying its associated submenu, what about the workaround I already demonstrated? Specifically, modify the item to remove the sub-menu before removing the item. Actually, there was a comment in the AutoHotkey source indicating the Win32 API may delete the sub-menu as an undocumented side-effect, but this does not seem to be the case on my system.
Quote:
This way, AHK doesn't know about the menu (and thus, can't destroy it).
Are you sure? AutoHotkey uses DeleteMenu() to remove a menu item. It is documented to destroy any sub-menu associated with the menu item. (This is at the Win32 API level, not at the AutoHotkey level.) I'm fairly certain AutoHotkey does not explicitly/intentionally delete the sub-menu.


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

Joined: November 4th, 2008, 9:23 am
Posts: 1045
Lexikos wrote:
As I meant to suggest in my previous post, if there were some built-in method to associate user-data with a menu or menu item

Oh, so there would be a way to retrieve/set this value (to a UInt, let's say) so that the user could then store what they might in the dwMenu/ItemData in there instead? If so, yeah, that sounds great.

Lexikos wrote:
That is, apart from the pitfalls we have discussed?

Well, actually, I think I "hacked" out the pitfalls. I'm testing the code now, but it looks fine. Deleting the entire menu doesn't work right yet, but I'm checking it out. Deleting items with submenus works fine with the "double hack" (first don't store submenus in the labels, then use RemoveMenu before Menu, delete - without either it won't work right, or I can't seem to get it to - looking into it though).

Granted there are quite a few "hacks" to get around AHK's syntax, but it works. The menus are never recreated (going to add a hack in for Menu, NoStandard/Standard); Also, icons, menu data, the "goto label", etc. are retained when menu items are inserted (at the end or middle of a menu), moved within the same menu (or to another menu), and all data is cleared on delete (both the menu icon as well as my menu/menu item data structure). So, besides the number of hacks that are going on in the background, the code will work as expected - no loss in functionality that I can see (well, unless you count recreating the menu to do anything "functionality").

Lexikos wrote:
Is the separator merely because the menu may be empty or non-existent, and therefore not have a valid menu handle?

Right, I need a way to see if the menu item was added or only updated. This is the only way I could think of. I can't just call the menu API because I need the menu handle, and if the menu doesn't exist, your code will then error (like it should). I can (just thought of this), however, keep track of the Menu, UseErrorLevel value internally. Then, the user would call a wrapper function to change this value. The code can then have UseErrorLevel on, run your MI_getMenuHandle function (returning 0 means the menu doesn't exist - or shouldn't... as long as I keep AHK from destroying menus), then set the UserErrorLevel to the previous value - that would work (and I'll use it, thanks).

Lexikos wrote:
"Application-defined 16-bit value that identifies the menu item. Set fMask to MIIM_ID to use wID." I believe AutoHotkey uses the ID's internally.

Oh, ok. I'll definetely add it back in then (and make sure whatever bug I saw before doesn't still exist). I thought of using it to store the menu object, but I saw that you used dwItemData so I thought you knew what you were doing, so I just followed suit.

Lexikos wrote:
If you mean remove a menu item without destroying its associated submenu, what about the workaround I already demonstrated?

It changes the menu handle (which I'll test, but as you said before - this means that AHK is recreating the menu).

Code:
Menu, Sub, Add, Item 1, _
Menu, Main1, Add, Sub-Menu, :Sub
Menu, Main1, Add, Plain old item, _
Menu, Main2, Add, Sub-Menu, :Sub
Menu, Main2, Add, Plain old item, _

hMenu := MI_GetMenuHandle("Main1")

MsgBox, % "SubMenu handle: " . MI_GetMenuHandle("Sub")
Menu, Main1, Show
; should fix problem
; however, changes the menu handle
Menu, Main1, Add, Sub-Menu, _
Menu, Main1, Delete, Sub-Menu

MsgBox, % "SubMenu handle: " . MI_GetMenuHandle("Sub")
Menu, Main1, Show
Menu, Main2, Show
Menu, Sub, Show
ExitApp
_:
return

MI_GetMenuHandle(menu_name)
{
    static   h_menuDummy
    ; v2.2: Check for !h_menuDummy instead of h_menuDummy="" in case init failed last time.
    If !h_menuDummy
    {
        Menu, menuDummy, Add
        Menu, menuDummy, DeleteAll

        Gui, 99:Menu, menuDummy
        ; v2.2: Use LastFound method instead of window title. [Thanks animeaime.]
        Gui, 99:+LastFound

        h_menuDummy := DllCall("GetMenu", "uint", WinExist())

        Gui, 99:Menu
        Gui, 99:Destroy

        ; v2.2: Return only after cleaning up. [Thanks animeaime.]
        if !h_menuDummy
            return 0
    }

    Menu, menuDummy, Add, :%menu_name%

    h_menu := DllCall( "GetSubMenu", "uint", h_menuDummy, "int", 0 )

    DllCall( "RemoveMenu", "uint", h_menuDummy, "uint", 0, "uint", 0x400)
    Menu, menuDummy, Delete, :%menu_name%

    return h_menu
}


Lexikos wrote:
Are you sure? AutoHotkey uses DeleteMenu() to remove a menu item. It is documented to destroy any sub-menu associated with the menu item. (This is at the Win32 API level, not at the AutoHotkey level.) I'm fairly certain AutoHotkey does not explicitly/intentionally delete the sub-menu.

Ohhh... that's why if I don't use RemoveMenu first, there's a problem - that explains it. Yeah, I "fixed" that be first removing the item, then using AHK menu, delete. This way, AHK still sees it as "gone" (so if I add the item later it doesn't try to update, but actually adds the value), and it can't delete the submenu. Good thing the code doesn't crash or produce an error when removing a menu item that doesn't exist anymore...

Like always, thank you SO MUCH for your help - without you I wouldn't have been able to make these libraries of mine work.

_________________
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 2nd, 2009, 8:33 pm 
Offline

Joined: November 4th, 2008, 9:23 am
Posts: 1045
I have a some quick questios about your Menu test (trying to figure what's required and what's not).

Code:
if (A_OSVersion != "WIN_VISTA")
{   ; It is necessary to hook the tray icon for owner-drawing to work.
    ; (Owner-drawing is not used on Windows Vista.)
    OnMessage(0x404, "AHK_NOTIFYICON")
    OnMessage(0x111, "WM_COMMAND") ; To track "pause" status.
    MI_SetMenuStyle(hTM, 0x4000000) ; MNS_CHECKORBMP (optional)
}


1) Is calling WM_COMMAND only to track "pause" status, or is there another use (i.e. is it required - in the general case)?

2) In AHK_NotifyIcon, you call MI_ShowMenu. On vista which is the prefered call - Menu, tray, show or MI_ShowMenu("tray")?

3) You say the below call is optional, when (or if) would you call it (i.e. what are the benefits/disadvantages and uses for it)?

Code:
MI_SetMenuStyle(hTM, 0x4000000) ; MNS_CHECKORBMP (optional)


Thanks again.

_________________
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 2nd, 2009, 10:33 pm 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7502
Location: Australia
animeaime wrote:
It changes the menu handle
Right, it happens when the sub-menu is removed from "Sub-Menu" via Menu, Add. I could swear this didn't happen in my previous tests (which did use MI_GetMenuHandle), but it is now. Must be the undocumented side-effect I mentioned.
Quote:
1) Is calling WM_COMMAND only to track "pause" status
Yes.
Quote:
2) In AHK_NotifyIcon, you call MI_ShowMenu. On vista which is the prefered call - Menu, tray, show or MI_ShowMenu("tray")?
AHK_NotifyIcon is not called on Vista. Generally, it does not matter either way.
Quote:
3) You say the below call is optional, when (or if) would you call it (i.e. what are the benefits/disadvantages and uses for it)?
Aesthetics.
Quote:
Source: MSDN: MENUINFO Structure ()
The same space is reserved for the check mark and the bitmap. If the check mark is drawn, the bitmap is not. All checkmarks and bitmaps are aligned. Used for menus where some items use checkmarks and some use bitmaps.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 3rd, 2009, 1:15 pm 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7502
Location: Australia
Cases when a menu handle is destroyed include, but may not be limited to:
  • Menu,,[No]MainWindow destroys the menu handle if the menu includes the standard menu items. Next time the menu handle is created, only the relevant standard menu items are added.
  • Menu,,DeleteAll destroys the menu handle.
  • If a pop-up menu is used with Gui, Menu, it has to be destroyed and recreated to convert it to the correct type of menu.
    Quote:
    Source: AutoHotkey Documentation: Gui, Menu
    Once a menu has been used as a menu bar, it should not be used as a popup menu or a submenu. This is because menu bars internally require a different format (however, this restriction applies only to the menu bar itself, not its submenus).
  • If a menu item which has a sub-menu is given a different sub-menu or converted into a normal menu item, the old sub-menu is destroyed by SetMenuItemInfo. Although this is undocumented for SetMenuItemInfo, it was documented for its predecessor:
    Quote:
    Source: MSDN: ModifyMenu Function ()
    If ModifyMenu replaces a menu item that opens a drop-down menu or submenu, the function destroys the old drop-down menu or submenu and frees the memory used by it.
  • If a menu handle is destroyed, its sub-menus' handles are also destroyed. There doesn't seem to be a way around this:
    Quote:
    Source: MSDN: DestroyMenu Function ()
    DestroyMenu is recursive, that is, it will destroy the menu and all its submenus.
  • Any menus containing the destroyed menu are also destroyed. This is done so that the sub-menu itself is automatically recreated when the parent menu is next shown.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 3rd, 2009, 1:42 pm 
Offline

Joined: November 4th, 2008, 9:23 am
Posts: 1045
Hmmm... I'll have to check into those, thanks. Also, why not use RemoveMenu instead of DeleteMenu when deleting an item? This way the menu won't be recreated next time - which should be more efficient anyway, right?

Also, now I see what you mean, a built-in value would be MUCH better than the dwMenu/ItemData value. This way, when the menu / menu item is destroyed and recreated, the behavior, is as expected, that nothing happens. If both the menu icons could be restored and this built-in value, then that would be great. If that built-in value stored a Class, then it would remain valid (because it's destroy function was never called), also, any other values which may be stored in that space are preserved. This way, only when the user calls something like Menu: delete, deleteAll, etc. where the menu SHOULD be destroyed, will the menu wrapper actually destroy anything (which will help fight potential memory leaks). Right now it's safe for delete and deleteAll, although I'm going to keep testing. I didn't test [No]MainWindow or Guis - never even crossed my mind that those would destroy the menu - so thank you a bunch for that information.

Edit:
I just thought of something. Since AHK has its own data structure that holds the menu data, is it destroyed automatically when the the menu / menu item handle is invalid? For example, when you call Menu, MenuName, delete, won't that remove each item that has MenuName as its submenu? That would mean that each of those item's data structures need to be removed, right? Is there a way to have a function run on the menu item's data at that time (likewise a function, or the same function, when deleting a menu). For example, both the Menu and MenuItem objects can be destroyed automatically by a call to Class_DestroyThis(Object) - where Object is the value stored in the dwMenu/ItemData (which hopefully can be instead stored as part of the UserMenu[Item] data structure). This function, then dynamically calls the destroy function for the Class object (either Menu_destroy for a Menu object or MenuItem_destroy for a MenuItem object). If you could add the ability to call a user-specified function when AHK destroys the menu/menu item's AHK data - that would be GREAT (although not sure if plausible). This way, only when AHK destroys the menu/menu item its Class object destroyed. Like I said, not sure if it's possible, but just a thought. Of course, since the function is user-specified it won't limit the use of the menu/menu item's data to solely a Class object.

_________________
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 3rd, 2009, 2:42 pm, edited 2 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 3rd, 2009, 2:38 pm 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7502
Location: Australia
animeaime wrote:
Also, why not use RemoveMenu instead of DeleteMenu when deleting an item?
I already suggested that in the bug report thread, and implemented it in my working copy of AutoHotkey_L.
Quote:
This way the menu won't be recreated next time - which should be more efficient anyway, right?
As I explained in the bug report, the sub-menu is not recreated as AutoHotkey does not expect the sub-menu handle to be destroyed. However, your argument is valid when considering the alternative, which is to clear the sub-menu handle and allow it to be recreated. :)


Edit in response to your last-minute edit: :lol:
Quote:
Since AHK has its own data structure that holds the menu data, is it destroyed automatically when the the menu / menu item handle is invalid?
No, with the exception below.
Quote:
For example, when you call Menu, MenuName, delete, won't that remove each item that has MenuName as its submenu?
It will remove the individual menu items which use the sub-menu, as documented. I don't see any problem with this.
Quote:
That would mean that each of those item's data structures need to be removed, right?
It would be part of the UserMenuItem structure, and would be deleted automatically when the item is deleted.
Quote:
Is there a way to have a function run on the menu item's data at that time
I have thought of this. I can see its uses, and will consider it for AutoHotkey_L. However, a UserMenuItem structure is only deleted when the item is removed explicitly by some Menu command, so it wouldn't be entirely necessary.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 3rd, 2009, 5:27 pm 
Offline

Joined: November 4th, 2008, 9:23 am
Posts: 1045
I hope I'm not a bother with all these questions - I'm going to you because you seem able to answer them. If I ever become a bother, please tell, that's not my intent.

Right now I'm trying to add functionality to "save" the menu so when NoStandard and other operations need to be done that recreate the menu, the previous values are restored. I know that the menu items have their wid (and menu item handle) which can be used to see that they are part of the "standard menu", but is there any characteristics on the menu separators? Or, does the code just "know" that they are there. I'm testing different configurations to reverse enginer the algorith used, but I thought since you were familiar with the AHK source code, you might have an idea.

Edit:
This might clear up my question: how does AHK know that what items are part of the standard menu? I know I can use the handle for the menu items; do the separators have any value associated with them to say that they are part of the standard menu? Or, does AHK just know that menu items X to Y in the structure are for the standard menu, and when NoStandard is called, those items are removed (and not used in the menu rebuild)?

Thanks for any help you can provide.

_________________
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 3rd, 2009, 10:22 pm 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7502
Location: Australia
animeaime wrote:
how does AHK know that what items are part of the standard menu?
It doesn't need to. Item ID's tell which item was activated. As already mentioned, AutoHotkey simply destroys and recreates the whole menu if it needs to modify the standard items. They do not have corresponding UserMenuItem structures, like user-created items.

Separator items have the MFT_SEPARATOR flag for fType.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 11th, 2010, 3:59 am 
I have an issue with the MI_EnableOwnerDrawnMenus() function that i'm not sure how to resolve. I'm hoping you can help me out a bit.

My problem is as follows. When using MI_EnableOwnerDrawnMenus() because I'm adding icons to the menu bar of my gui I have to pass the script hwnd using MI_EnableOwnerDrawnMenus(WinExist()). But when i do this the buttons I added to the gui dont trigger there associated gLabels any more. ??

Code:
;Forces the program to only run one instance. If it is already open,
;it closes the existing instance and replaces it with a new one.

#SingleInstance Force
;SetBatchLines, -1                  ;No Delay between lines
Menu, Tray, Icon, Graphics\Sun-icon.ico ;Change regular Icon
Menu, Tray, Tip, VNCGUI

BtnMargin := 2                     ;Set Constants
BtnH := 58                        ;Button Height
BtnW := 108                        ;Button Height
ILSize := BtnH  * .8               ;H and W of pictures on buttons
ILSize := Ceil(ILSize)                ;H and W of pictures on buttons rounded up
INI = %A_ScriptDir%\ClientList.ini      ;inifile
FileRead, IniFile, %INI%            ;read into memory
TtlBtn := 0                        ;reset total button count
FontOptions = cWhite s8 +Center         ;Font Options  ex cColor(HTML or HEX) sSize +Center
Font = Arial                       ;Font Style ex. Arial, Arial Bold, Arial bold Italic, Times New Roman
GuiColor = White                  ;Gui Color
About = Created by Joel Wagner`njwagner@linamar.com`n`nVersion 2.2  March 08`, 2010`n`nAdded icons to all menus.`nAdded right click context menu.

Loop, Parse, IniFile, `n,=,      ;Store all client info for later
{
   If A_LoopField Not Contains =
      Continue
   TtlBtn := TtlBtn + 1
   StringSplit, OutputArray, A_LoopField, =
   Name%TtlBtn% := OutputArray1               ;Name
   If OutputArray2 Contains |
   {
      StringSplit, OutputArray, OutputArray2, |   ;IP and Password
      IPAddress%TtlBtn% := OutputArray1
      StringTrimRight, OutputArray2, OutputArray2, 1
      Password%TtlBtn% := OutputArray2
      Continue
   }
   Else
   {
      StringTrimRight, OutputArray2, OutputArray2, 1
      IPAddress%TtlBtn% := OutputArray2         ;IP no Password
   }
}
                                             ;Start to Build Gu
    ;Square root of total buttons rounded up
Pos := 0
Grid := Sqrt(TtlBtn)
Grid := Ceil(Grid) 
Loop, %Grid%            ;Find button row structure
{
   RowStart%A_Index% := Pos + 1 , RowEnd%A_Index% := Grid * A_Index + 1
   Pos := Grid * A_Index      
}
Y := ((BtnMargin + BtnH) * Grid) + BtnMargin
X := BtnW + (BtnMargin * 2)

Gui, Color, %GuiColor%
Gui, Font, %FontOptions%, %Font%
If FileExist("Graphics\SPINIC SOLUTION.jpg")
   Gui, Add, Picture, x%X% y%Y% 0, Graphics\SPINIC SOLUTION.jpg
;------------------Add Button Loop-----------------------
;--------------------------------------------------------



Loop, %TtlBtn%             ;Total button count max
{
   Pos := CalcPos(A_Index, BtnH, BtnW, TtlBtn, BtnMargin)        ;Returns x y h w
   BtnName := Name%A_Index%
   Gui, Add, Button, gBtn %Pos% hwndhBtn, %BtnName%            ;Add Button
      ILButton(hBtn, "Graphics\LinamarLogo.bmp:" 0, ILSize, ILSize, 0)    ;Add Icon
}
Gui, Add, Button, x%BtnMargin% y%Y% w%BtnW% h%BtnH% hwndhBtn, VNC Viewer   ;Add VNC button
   ILButton(hBtn, "Graphics\vnc.bmp:" 0, ILSize, ILSize, 0)



Gui, +LastFound
MI_EnableOwnerDrawnMenus(WinExist())

;===========================Add File Menu,icons and tooltip==========================

Menu, FileMenu, Add, Add Client, AddClient
   MI_SetMenuItemIcon("FileMenu", 1, "C:\Program Files\RealVNC\VNC4\vncviewer.exe", 1, 16)
Menu, FileMenu, Add, Enable VNCGUI, EnableVNCGUI
   MI_SetMenuItemIcon("FileMenu", 2, "shell32.dll", 45, 16)
Menu, FileMenu, Add, Disable VNCGUI, DisableVNCGUI
   MI_SetMenuItemIcon("FileMenu", 3, "shell32.dll", 48, 16)
Menu, FileMenu, Add
Menu, FileMenu, Add, Exit, ExitVNC
   MI_SetMenuItemBitmap("FileMenu", 5, 6) ; exit

MI_SetMenuStyle("FileMenu", 0x4000000)

;===========================Add Edit Menu,icons and tooltip==========================
Menu, EditMenu, Add, Edit this Script, EditScript
   MI_SetMenuItemIcon("EditMenu", 1, A_AhkPath, 2, 16)
Menu, EditMenu, Add, Edit Client List, EditScriptSettings
   MI_SetMenuItemIcon("EditMenu", 2, A_ProgramFiles "\AutoHotkey\SciTE\SciTE.exe", 1, 16)
Menu, EditMenu, Add
Menu, EditMenu, Add, Edit Script on J:\, EditScriptJ
   MI_SetMenuItemIcon("EditMenu", 4, A_AhkPath, 2, 16)
Menu, EditMenu, Add, Edit IP List on J:\, OpenIPListJ
   MI_SetMenuItemIcon("EditMenu", 5, A_ProgramFiles "\AutoHotkey\SciTE\SciTE.exe", 1, 16)

MI_SetMenuStyle("EditMenu", 0x4000000)


;===========================Add BackUp Menu,icons and tooltip==========================
Menu, BackUpMenu, Add, Back Up VNCGUI on J:\, BackUpJ
   MI_SetMenuItemIcon("BackUpMenu", 1, "shell32.dll", 69, 16)
Menu, BackUpMenu, Add, Back Up VNCGUI Directory, BackUp
   MI_SetMenuItemIcon("BackUpMenu", 2, "shell32.dll", 69, 16)

MI_SetMenuStyle("BackUpMenu", 0x4000000)

;===========================Add Help Menu,icons and tooltip==========================
Menu, HelpMenu, Add, Client List Help, ClientHelp
   MI_SetMenuItemIcon("HelpMenu", 1, A_WinDir "\hh.exe", 1, 16)
Menu, HelpMenu, Add, Script Help, ScriptHelp
   MI_SetMenuItemIcon("HelpMenu", 2, A_WinDir "\hh.exe", 1, 16)

MI_SetMenuStyle("HelpMenu", 0x4000000)

;===========================Add About Menu,icons and tooltip==========================
Menu, AboutMenu, Add, About, About
   MI_SetMenuItemIcon("AboutMenu", 1, "shell32.dll", 24, 16)

MI_SetMenuStyle("AboutMenu", 0x4000000)

;======================Attach the sub-menus that were created above===================

Menu, MyMenuBar, Add, File, :FileMenu 
Menu, MyMenuBar, Add, Edit, :EditMenu 
Menu, MyMenuBar, Add, Back Up, :BackUpMenu
Menu, MyMenuBar, Add, Help, :HelpMenu 
Menu, MyMenuBar, Add, About, :AboutMenu 
Gui, Menu, MyMenuBar

;===========================Add Context Menu for later reference==========================
Menu, RSLogix, Add,
Menu, ShiftReports, Add,
Menu, BtnSettings, Add,
Menu, Context, Add,
Menu, Program, Add,
;======================Show Main Gui ===================

Gui +OwnDialogs +LastFound
WinTitle = Real VNC %A_ComputerName% -- %A_IPAddress1%
Gui, Show,, %WinTitle%
MainWin := WinExist()
Return


;============Button Handler=======================
;=================================================

Btn:
Loop, %TtlBtn%
{
   Name := Name%A_Index%
   If A_GuiControl = %Name%
      Connect := Connect(A_Index)
   If Connect
      Break
}
Sleep, 10
Connect =
Return


When i comment out that function all gLabels are executed properly. It looks like when MI_OwnerDrawnMenuItemWndProc() is exucuting thats ALL that can be done. The Menu's still function as normal and event are triggered properly as well as a context menu that is made later in the script on a hotkey. It appears only the buttons dont register there gLabels anymore.

I've looked at this for a bit and tried a few different things but can't seem to get around it yet. Any ideas why this is happening and how to resolve this??

Thanks in advance


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: March 11th, 2010, 4:00 am 
Sorry forgot to add im running xp sp3


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: March 11th, 2010, 9:38 pm 
I think I'm getting closer to why i'm having an issue with the gLabels on my buttons but I'm still not sure how to fix it.

Straight out of the help file for the Critical command:

In v1.0.47+, specifying a positive number as the first parameter (e.g. Critical 30) turns on Critical but also changes the number of milliseconds between checks of the internal message queue. If unspecified, messages are checked every 16 milliseconds while Critical is On, and every 5 ms while Critical is Off. Increasing the interval postpones the arrival of messages/events, which gives the current thread more time to finish. This reduces the possibility that certain OnMessage() and GUI events will be lost due to "thread already running". However, commands that wait such as Sleep and WinWait will check messages regardless of this setting (a workaround is DllCall("Sleep", Uint, 500)). Note: Increasing the message-check interval too much may reduce the responsiveness of various events such as GUI window repainting.

Can anyone show me how to check if i am loosing the gui events? Or point me in the right direction possibly.


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: March 12th, 2010, 10:27 pm 
I found a work around for anyone who is interested about the problem i described above.

This is a script that demonstrates my problem as desribed above. No includes neccesary. If you comment out the line in red the gLabel is executed with no problem. If you enable that function the gLabel gets lost.

Code:
;Forces the program to only run one instance. If it is already open,
;it closes the existing instance and replaces it with a new one.

#SingleInstance Force
SetBatchLines, -1                  ;No Delay between lines
Menu, Tray, Tip, VNCGUI

FontOptions = cWhite s8 +Center         ;Font Options  ex cColor(HTML or HEX) sSize +Center
Font = Arial                       ;Font Style ex. Arial, Arial Bold, Arial bold Italic, Times New Roman
GuiColor = White                  ;Gui Color

Gui, Color, %GuiColor%
Gui, Font, %FontOptions%, %Font%
;------------------Add Button Loop-----------------------
;--------------------------------------------------------



Gui, Add, Button, x10 y10 w50 h50 , VNC Viewer   ;Add VNC button
   

Gui, +LastFound
MI_EnableOwnerDrawnMenus(WinExist())
;===========================Add File Menu,icons and tooltip==========================

Menu, FileMenu, Add, Add Client, c
   MI_SetMenuItemIcon("FileMenu", 1, "shell32.dll", 45, 16)
Menu, FileMenu, Add, Enable VNCGUI, c
   MI_SetMenuItemIcon("FileMenu", 2, "shell32.dll", 45, 16)
Menu, FileMenu, Add, Disable VNCGUI, c
   MI_SetMenuItemIcon("FileMenu", 3, "shell32.dll", 48, 16)
Menu, FileMenu, Add
Menu, FileMenu, Add, Exit, c
   MI_SetMenuItemBitmap("FileMenu", 5, 6) ; exit

MI_SetMenuStyle("FileMenu", 0x4000000)

;===========================Add Edit Menu,icons and tooltip==========================
Menu, EditMenu, Add, Edit this Script, c
   MI_SetMenuItemIcon("EditMenu", 1, A_AhkPath, 2, 16)
Menu, EditMenu, Add, Edit Client List, c
   MI_SetMenuItemIcon("EditMenu", 2, A_AhkPath, 2, 16)
Menu, EditMenu, Add
Menu, EditMenu, Add, Edit Script on J:\, c
   MI_SetMenuItemIcon("EditMenu", 4, A_AhkPath, 2, 16)
Menu, EditMenu, Add, Edit IP List on J:\, c
   MI_SetMenuItemIcon("EditMenu", 5, A_AhkPath, 2, 16)

MI_SetMenuStyle("EditMenu", 0x4000000)


;===========================Add BackUp Menu,icons and tooltip==========================
Menu, BackUpMenu, Add, Back Up VNCGUI on J:\, c
   MI_SetMenuItemIcon("BackUpMenu", 1, "shell32.dll", 69, 16)
Menu, BackUpMenu, Add, Back Up VNCGUI Directory, c
   MI_SetMenuItemIcon("BackUpMenu", 2, "shell32.dll", 69, 16)

MI_SetMenuStyle("BackUpMenu", 0x4000000)

;===========================Add Help Menu,icons and tooltip==========================
Menu, HelpMenu, Add, Client List Help, c
   MI_SetMenuItemIcon("HelpMenu", 1, A_WinDir "\hh.exe", 1, 16)
Menu, HelpMenu, Add, Script Help, c
   MI_SetMenuItemIcon("HelpMenu", 2, A_WinDir "\hh.exe", 1, 16)

MI_SetMenuStyle("HelpMenu", 0x4000000)

;===========================Add About Menu,icons and tooltip==========================
Menu, AboutMenu, Add, About, c
   MI_SetMenuItemIcon("AboutMenu", 1, "shell32.dll", 24, 16)

MI_SetMenuStyle("AboutMenu", 0x4000000)

;======================Attach the sub-menus that were created above===================

Menu, MyMenuBar, Add, File, :FileMenu
Menu, MyMenuBar, Add, Edit, :EditMenu
Menu, MyMenuBar, Add, Back Up, :BackUpMenu
Menu, MyMenuBar, Add, Help, :HelpMenu
Menu, MyMenuBar, Add, About, :AboutMenu
Gui, Menu, MyMenuBar


;======================Show Main Gui ===================

Gui +OwnDialogs +LastFound
WinTitle = Real VNC %A_ComputerName% -- %A_IPAddress1%
Gui, Show, w200 h200, %WinTitle%
MainWin := WinExist()
Return


;============Button Handler=======================
;=================================================


ButtonVNCViewer:
MsgBox, Button Label Worked!!!!
Return

c:
MsgBox, %A_ThisMenu%`n%A_ThisMenuItem%`n%A_ThisMenuItemPos%
Return



;  Menu Icons v2.2
;   by Lexikos
;


; Associates an icon with a menu item.
; NOTE: On versions of Windows other than Vista, the menu MUST be shown with
;       MI_ShowMenu() for the icons to appear.
;
;   MenuNameOrHandle
;       The name or handle of a menu. When setting icons for multiple items,
;       it is more efficient to use a handle returned by MI_GetMenuHandle("menuname").
;   ItemPos
;       The position of the menu item, where 1 is the first item.
;   FilenameOrHICON
;       The filename or handle of an icon.
;       SUPPORTS EXECUTABLE FILES ONLY (EXE/DLL/ICL/CPL/etc.)
;   IconNumber
;       The icon group to use (if omitted, it defaults to 1.)
;       This is not used if FilenameOrHICON specifies an icon handle.
;   IconSize
;       The desired width and height of the icon. If omitted, the system's small icon size is used.
;   h_bitmap
;   h_icon
;       v2.2: These parameters are no longer used as MI now automatically deletes the
;       icon/bitmap if a new icon/bitmap is being set.
;     OBSOLETE:
;       These are set to the bitmap or icon resources which are used.
;       Bitmaps and icons can be deleted as follows:
;           DllCall("DeleteObject", "uint", h_bitmap)
;           DllCall("DestroyIcon", "uint", h_icon)
;       This is only necessary if the menu item displaying these resources
;       is manually removed.
;       Usually only one of h_icon or h_bitmap will be used, and the other will be 0 (NULL).
;
; OPERATING SYSTEM NOTES:
;
; Windows 2000 and above:
;   PrivateExtractIcons() is used to extract the icon.
;
; Older versions of Windows:
;   PrivateExtractIcons() is not available, so ExtractIconEx() is used.
;   As a result, a 16x16 or 32x32 icon will be loaded. If a size is specified,
;   the icon may be stretched to fit. If no size is specified, 16x16 is used.
;
MI_SetMenuItemIcon(MenuNameOrHandle, ItemPos, FilenameOrHICON, IconNumber=1, IconSize=0, ByRef unused1="", ByRef unused2="")
{
    ; Set for compatibility with older scripts:
    unused1=0
    unused2=0
   
    if MenuNameOrHandle is integer
        h_menu := MenuNameOrHandle
    else
        h_menu := MI_GetMenuHandle(MenuNameOrHandle)
   
    if !h_menu
        return false
   
    if FilenameOrHICON is integer
    {
        ; May be 0 to remove icon.
        h_icon := FilenameOrHICON
        ; Copy and potentially resize the icon. Since the caller is probably "caching"
        ; icon handles or assigning them to multiple items, we don't want to delete
        ; it if/when a future call to this function re-sets this item's icon.
        if h_icon
            h_icon := DllCall("CopyImage","uint",h_icon,"uint",1
                                ,"int",IconSize,"int",IconSize,"uint",0)
        ; else caller wants to remove and delete existing icon.
    }
    else
    {
        ; Load icon from file. Remember to clean up this icon if we end up using a bitmap.
        ; Resizing is not necessary in this case since MI_ExtractIcon already does that.
        if !(loaded_icon := h_icon := MI_ExtractIcon(FilenameOrHICON, IconNumber, IconSize))
            return false
    }
   
    ; Windows Vista supports 32-bit alpha-blended bitmaps in menus. Note that
    ; A_OSVersion does not report WIN_VISTA when running in compatibility mode.
    ; To get nice icons on other versions of Windows, we need to owner-draw.
    ; DON'T TOUCH UNLESS YOU KNOW WHAT YOU'RE DOING:
    ;   use_bitmap MUST have the same value for each use on a given menu item.
    use_bitmap := (A_OSVersion="WIN_VISTA")
   
    ; Get the previous bitmap or icon handle.
    VarSetCapacity(mii,48,0), NumPut(48,mii), NumPut(0xA0,mii,4)
    if DllCall("GetMenuItemInfo","uint",h_menu,"uint",ItemPos-1,"uint",1,"uint",&mii)
        h_previous := use_bitmap ? NumGet(mii,44,"int") : NumGet(mii,32,"int")

    if use_bitmap
    {
        if h_icon
        {
            h_bitmap := MI_GetBitmapFromIcon32Bit(h_icon, IconSize, IconSize)
           
            if loaded_icon
            {
                ; The icon we loaded is no longer needed.
                DllCall("DestroyIcon","uint",loaded_icon)
                ; Don't try to destroy the now invalid handle again:
                loaded_icon := 0
            }
           
            if !h_bitmap
                return false
        }
        else
            ; Caller wants to remove and delete existing icon.
            h_bitmap := 0
       
        NumPut(0x80,mii,4) ; fMask: Set hbmpItem only, not dwItemData.
        , NumPut(h_bitmap,mii,44) ; hbmpItem = h_bitmap
    }
    else
    {
        ; Associate the icon with the menu item. Relies on the probable case that no other
        ; script or dll will use dwItemData. If other scripts need to associate data with
        ; an item, MI should be expanded to allow it.
        NumPut(h_icon,mii,32) ; dwItemData = h_icon
        , NumPut(-1,mii,44) ; hbmpItem = HBMMENU_CALLBACK
    }

    if DllCall("SetMenuItemInfo","uint",h_menu,"uint",ItemPos-1,"uint",1,"uint",&mii)
    {   
        ; Only now that we know it's a success, delete the previous icon or bitmap.
        if use_bitmap
        {   ; Exclude NULL and predefined HBMMENU_ values (-1, 1..11).
            if (h_previous < -1 || h_previous > 11)
                DllCall("DeleteObject","uint",h_previous)
        } else
            DllCall("DestroyIcon","uint",h_previous)
       
        return true
    }
    ; ELSE FAIL
    if loaded_icon
        DllCall("DestroyIcon","uint",loaded_icon)
    return false
}

; v2.2: This should be used to remove and delete all icons in a menu before deleting the menu.
MI_RemoveIcons(MenuNameOrHandle)
{
    if MenuNameOrHandle is integer
        h_menu := MenuNameOrHandle
    else
        h_menu := MI_GetMenuHandle(MenuNameOrHandle)
   
    if !h_menu
        return
   
    Loop % DllCall("GetMenuItemCount","uint",h_menu)
        MI_SetMenuItemIcon(h_menu, A_Index, 0)
}

; Set a menu item's associated bitmap.
; hBitmap can be a handle to a bitmap, or a HBMMENU value (see below.)
MI_SetMenuItemBitmap(MenuNameOrHandle, ItemPos, hBitmap)
{
    if MenuNameOrHandle is integer
        h_menu := MenuNameOrHandle
    else
        h_menu := MI_GetMenuHandle(MenuNameOrHandle)
   
    if !h_menu
        return false
   
    VarSetCapacity(mii,48,0), NumPut(48,mii), NumPut(0x80,mii,4), NumPut(hBitmap,mii,44)
    return DllCall("SetMenuItemInfo","uint",h_menu,"uint",ItemPos-1,"uint",1,"uint",&mii)
}
/*
HBMMENU_SYSTEM              =  1
HBMMENU_MBAR_RESTORE        =  2
HBMMENU_MBAR_MINIMIZE       =  3
HBMMENU_MBAR_CLOSE          =  5
HBMMENU_MBAR_CLOSE_D        =  6
HBMMENU_MBAR_MINIMIZE_D     =  7
HBMMENU_POPUP_CLOSE         =  8
HBMMENU_POPUP_RESTORE       =  9
HBMMENU_POPUP_MAXIMIZE      = 10
HBMMENU_POPUP_MINIMIZE      = 11
*/

;
; General Functions
;

; Gets a menu handle from a menu name.
; Adapted from Shimanov's Menu_AssignBitmap()
;   http://www.autohotkey.com/forum/topic7526.html
MI_GetMenuHandle(menu_name)
{
    static   h_menuDummy
    ; v2.2: Check for !h_menuDummy instead of h_menuDummy="" in case init failed last time.
    If !h_menuDummy
    {
        Menu, menuDummy, Add
        Menu, menuDummy, DeleteAll

        Gui, 99:Menu, menuDummy
        ; v2.2: Use LastFound method instead of window title. [Thanks animeaime.]
        Gui, 99:+LastFound

        h_menuDummy := DllCall("GetMenu", "uint", WinExist())

        Gui, 99:Menu
        Gui, 99:Destroy
       
        ; v2.2: Return only after cleaning up. [Thanks animeaime.]
        if !h_menuDummy
            return 0
    }

    Menu, menuDummy, Add, :%menu_name%
    h_menu := DllCall( "GetSubMenu", "uint", h_menuDummy, "int", 0 )
    DllCall( "RemoveMenu", "uint", h_menuDummy, "uint", 0, "uint", 0x400 )
    Menu, menuDummy, Delete, :%menu_name%
   
    return h_menu
}

; Valid (and safe to use) styles:
;   MNS_AUTODISMISS  0x10000000
;   MNS_CHECKORBMP   0x04000000  The same space is reserved for the check mark and the bitmap.
;   MNS_NOCHECK      0x80000000  No space is reserved to the left of an item for a check mark.
MI_SetMenuStyle(MenuNameOrHandle, style)
{
    if MenuNameOrHandle is integer
        h_menu := MenuNameOrHandle
    else
        h_menu := MI_GetMenuHandle(MenuNameOrHandle)
   
    if !h_menu
        return
       
    VarSetCapacity(mi,28,0), NumPut(28,mi)
    NumPut(0x10,mi,4) ; fMask=MIM_STYLE
    NumPut(style,mi,8)
    DllCall("SetMenuInfo","uint",h_menu,"uint",&mi)
}

; Extract an icon from an executable, DLL or icon file.
MI_ExtractIcon(Filename, IconNumber, IconSize)
{
    ; LoadImage is not used..
    ; ..with exe/dll files because:
    ;   it only works with modules loaded by the current process,
    ;   it needs the resource ordinal (which is not the same as an icon index), and
    ; ..with ico files because:
    ;   it can only load the first icon (of size %IconSize%) from an .ico file.
   
    ; If possible, use PrivateExtractIcons, which supports any size of icon.
    if A_OSVersion in WIN_VISTA,WIN_2003,WIN_XP,WIN_2000
    {
        r:=DllCall("PrivateExtractIcons"
            ,"str",Filename,"int",IconNumber-1,"int",IconSize,"int",IconSize
            ,"uint*",h_icon,"uint*",0,"uint",1,"uint",0,"int")
;         StdOut("icon: " h_icon ", size: " IconSize ", num: " IconNumber ", file: " Filename)
        if !ErrorLevel
        {
            if !h_icon || r>1
            {
                Clipboard:=Filename
                ListVars
                Pause
            }
            return h_icon
        }
    }
    ; Use ExtractIconEx, which only returns 16x16 or 32x32 icons.
    if DllCall("shell32.dll\ExtractIconExA","str",Filename,"int",IconNumber-1
                ,"uint*",h_icon,"uint*",h_icon_small,"uint",1)
    {
        SysGet, SmallIconSize, 49
       
        ; Use the best-fit size; delete the other. Defaults to small icon.
        if (IconSize <= SmallIconSize) {
            DllCall("DestroyIcon","uint",h_icon)
            h_icon := h_icon_small
        } else
            DllCall("DestroyIcon","uint",h_icon_small)
       
        ; I think PrivateExtractIcons resizes icons automatically,
        ; so resize icons returned by ExtractIconEx for consistency.
        if (h_icon && IconSize)
            h_icon := DllCall("CopyImage","uint",h_icon,"uint",1,"int",IconSize
                                ,"int",IconSize,"uint",4|8)
    }

    return h_icon ? h_icon : 0
}

;
; Owner-Drawn Menu Functions
;

; Sub-classes a window from THIS process to owner-draw menu icons.
; This allows the menu to be shown by means other than MI_ShowMenu().
MI_EnableOwnerDrawnMenus(hwnd="")
{
    if (hwnd="") {  ; Use the script's main window if hwnd was omitted.
        dhw := A_DetectHiddenWindows
        DetectHiddenWindows, On
        Process, Exist
        hwnd := WinExist("ahk_class AutoHotkey ahk_pid " ErrorLevel)
        DetectHiddenWindows, %dhw%
    }
    if !hwnd
        return
    wndProc := RegisterCallback("MI_OwnerDrawnMenuItemWndProc","",4
        ,DllCall("GetWindowLong","uint",hwnd,"uint",-4))
    return DllCall("SetWindowLong","uint",hwnd,"int",-4,"int",wndProc,"uint")
}

; Shows a menu, allowing owner-drawn icons to be drawn.
MI_ShowMenu(MenuNameOrHandle, x="", y="")
{
    static hInstance, hwnd, ClassName := "OwnerDrawnMenuMsgWin"

    if MenuNameOrHandle is integer
        h_menu := MenuNameOrHandle
    else
        h_menu := MI_GetMenuHandle(MenuNameOrHandle)
   
    if !h_menu
        return false
   
    if !hwnd
    {   ; Create a message window to receive owner-draw messages from the menu.
        ; Only one window is created per instance of the script.
   
        if !hInstance
            hInstance := DllCall("GetModuleHandle", "UInt", 0)

        ; Register a window class to associate OwnerDrawnMenuItemWndProc()
        ; with the window we will create.
        wndProc := RegisterCallback("MI_OwnerDrawnMenuItemWndProc","",4,0)
        if !wndProc {
            ErrorLevel = RegisterCallback
            return false
        }
   
        ; Create a new window class.
        VarSetCapacity(wc, 40, 0)   ; WNDCLASS wc
        NumPut(wndProc,   wc, 4)   ; lpfnWndProc
        NumPut(hInstance, wc,16)   ; hInstance
        NumPut(&ClassName,wc,36)   ; lpszClassname

        ; Register the class.       
        if !DllCall("RegisterClass","uint",&wc)
        {   ; failed, free the callback.
            DllCall("GlobalFree","uint",wndProc)
            ErrorLevel = RegisterClass
            return false
        }
       
        ;
        ; Create the message window.
        ;
        if A_OSVersion in WIN_XP,WIN_VISTA
            hwndParent = -3 ; HWND_MESSAGE (message-only window)
        else
            hwndParent = 0  ; un-owned
       
        hwnd := DllCall("CreateWindowExA","uint",0,"str",ClassName,"str",ClassName
                        ,"uint",0,"int",0,"int",0,"int",0,"int",0,"uint",hwndParent
                        ,"uint",0,"uint",hInstance,"uint",0)
        if !hwnd {
            ErrorLevel = CreateWindowEx
            return false
        }
    }

    prev_hwnd := DllCall("GetForegroundWindow")

    ; Required for the menu to initially have focus.
    ;DllCall("SetForegroundWindow","uint",hwnd)
    dhw := A_DetectHiddenWindows
    DetectHiddenWindows, On
    WinActivate, ahk_id %hwnd%
    DetectHiddenWindows, %dhw%
   
    if (x="" or y="") {
        CoordMode, Mouse, Screen
        MouseGetPos, x, y
    }

    ; returns non-zero on success.
    ret := DllCall("TrackPopupMenu","uint",h_menu,"uint",0,"int",x,"int",y
                    ,"int",0,"uint",hwnd,"uint",0)
   
    if WinExist("ahk_id " prev_hwnd)
        DllCall("SetForegroundWindow","uint",prev_hwnd)
   
    ; Required to let AutoHotkey process WM_COMMAND messages we may have
    ; sent as a result of clicking a menu item. (Without this, the item-click
    ; won't register if there is an 'ExitApp' after ShowOwnerDrawnMenu returns.)
    Sleep, 1
   
    return ret
}

MI_OwnerDrawnMenuItemWndProc(hwnd, Msg, wParam, lParam)
{
    static WM_DRAWITEM = 0x002B, WM_MEASUREITEM = 0x002C, WM_COMMAND = 0x111
    static ScriptHwnd
    Critical 500

    if (Msg = WM_MEASUREITEM && wParam = 0)
    {   ; MSDN: wParam - If the value is zero, the message was sent by a menu.
        h_icon := NumGet(lParam+20)
        if !h_icon
            return false
       
        ; Measure icon and put results into lParam.
        VarSetCapacity(buf,24)
        if DllCall("GetIconInfo","uint",h_icon,"uint",&buf)
        {
            hbmColor := NumGet(buf,16)
            hbmMask  := NumGet(buf,12)
            x := DllCall("GetObject","uint",hbmColor,"int",24,"uint",&buf)
            DllCall("DeleteObject","uint",hbmColor)
            DllCall("DeleteObject","uint",hbmMask)
            if !x
                return false
            NumPut(NumGet(buf,4,"int")+2, lParam+12) ; width
            NumPut(NumGet(buf,8,"int")  , lParam+16) ; height
            return true
        }
        return false
    }
    else if (Msg = WM_DRAWITEM && wParam = 0)
    {
        hdcDest := NumGet(lParam+24)
        x       := NumGet(lParam+28)
        y       := NumGet(lParam+32)
        h_icon  := NumGet(lParam+44)
        if !(h_icon && hdcDest)
            return false

        return DllCall("DrawIconEx","uint",hdcDest,"int",x,"int",y,"uint",h_icon
                        ,"uint",0,"uint",0,"uint",0,"uint",0,"uint",3)
    }
    else if (Msg = WM_COMMAND && !(wParam>>16)) ; (clicked a menu item)
    {
        DetectHiddenWindows, On
        if !ScriptHwnd {
            Process, Exist
            ScriptHwnd := WinExist("ahk_class AutoHotkey ahk_pid " ErrorLevel)
        }
        if (hwnd != ScriptHwnd) {
            ; Forward this message to the AutoHotkey main window.
            PostMessage, Msg, wParam, lParam,, ahk_id %ScriptHwnd%
            return ErrorLevel
        }
    }
    if A_EventInfo  ; Let the "super-class" window procedure handle all other messages.
        return DllCall("CallWindowProc","uint",A_EventInfo,"uint",hwnd,"uint",Msg,"uint",wParam,"uint",lParam)
    else            ; Let the default window procedure handle all other messages.
        return DllCall("DefWindowProc","uint",hwnd,"uint",Msg,"uint",wParam,"uint",lParam)
}


;
; Windows Vista Menu Icons
;

; Note: 32-bit alpha-blended menu item bitmaps are supported only on Windows Vista.
; Article on menu icons in Vista:
; http://shellrevealed.com/blogs/shellblog/archive/2007/02/06/Vista-Style-Menus_2C00_-Part-1-_2D00_-Adding-icons-to-standard-menus.aspx
MI_GetBitmapFromIcon32Bit(h_icon, width=0, height=0)
{
    VarSetCapacity(buf,40) ; used as ICONINFO (20), BITMAP (24), BITMAPINFO (40)
    if DllCall("GetIconInfo","uint",h_icon,"uint",&buf) {
        hbmColor := NumGet(buf,16)  ; used to measure the icon
        hbmMask  := NumGet(buf,12)  ; used to generate alpha data (if necessary)
    }

    if !(width && height) {
        if !hbmColor or !DllCall("GetObject","uint",hbmColor,"int",24,"uint",&buf)
            return 0
        width := NumGet(buf,4,"int"),  height := NumGet(buf,8,"int")
    }

    ; Create a device context compatible with the screen.       
    if (hdcDest := DllCall("CreateCompatibleDC","uint",0))
    {
        ; Create a 32-bit bitmap to draw the icon onto.
        VarSetCapacity(buf,40,0), NumPut(40,buf), NumPut(1,buf,12,"ushort")
        NumPut(width,buf,4), NumPut(height,buf,8), NumPut(32,buf,14,"ushort")
       
        if (bm := DllCall("CreateDIBSection","uint",hdcDest,"uint",&buf,"uint",0
                            ,"uint*",pBits,"uint",0,"uint",0))
        {
            ; SelectObject -- use hdcDest to draw onto bm
            if (bmOld := DllCall("SelectObject","uint",hdcDest,"uint",bm))
            {
                ; Draw the icon onto the 32-bit bitmap.
                DllCall("DrawIconEx","uint",hdcDest,"int",0,"int",0,"uint",h_icon
                        ,"uint",width,"uint",height,"uint",0,"uint",0,"uint",3)

                DllCall("SelectObject","uint",hdcDest,"uint",bmOld)
            }
       
            ; Check for alpha data.
            has_alpha_data := false
            Loop, % height*width
                if NumGet(pBits+0,(A_Index-1)*4) & 0xFF000000 {
                    has_alpha_data := true
                    break
                }
            if !has_alpha_data
            {
                ; Ensure the mask is the right size.
                hbmMask := DllCall("CopyImage","uint",hbmMask,"uint",0
                                    ,"int",width,"int",height,"uint",4|8)
               
                VarSetCapacity(mask_bits, width*height*4, 0)
                if DllCall("GetDIBits","uint",hdcDest,"uint",hbmMask,"uint",0
                            ,"uint",height,"uint",&mask_bits,"uint",&buf,"uint",0)
                {   ; Use icon mask to generate alpha data.
                    Loop, % height*width
                        if (NumGet(mask_bits, (A_Index-1)*4))
                            NumPut(0, pBits+(A_Index-1)*4)
                        else
                            NumPut(NumGet(pBits+(A_Index-1)*4) | 0xFF000000, pBits+(A_Index-1)*4)
                } else {   ; Make the bitmap entirely opaque.
                    Loop, % height*width
                        NumPut(NumGet(pBits+(A_Index-1)*4) | 0xFF000000, pBits+(A_Index-1)*4)
                }
            }
        }
   
        ; Done using the device context.
        DllCall("DeleteDC","uint",hdcDest)
    }

    if hbmColor
        DllCall("DeleteObject","uint",hbmColor)
    if hbmMask
        DllCall("DeleteObject","uint",hbmMask)
    return bm
}


   ;Exits Apllication

GUIClose:
ExitApp


This is a script the fixes the above mentioned problem. I extract the icon to an hbitmap and assign that to the menu instead of the icon directly. Transparency is lost but for me thats not a big deal.

Youll have to include gdip.ahk by tic
http://www.autohotkey.com/forum/topic32 ... light=gdip
and menu icons v2.2(MI.ahk) by Lexikos
http://www.autohotkey.com/forum/topic21991.html

Code:
;Forces the program to only run one instance. If it is already open,
;it closes the existing instance and replaces it with a new one.

#SingleInstance Force
SetBatchLines, -1                  ;No Delay between lines
Menu, Tray, Tip, VNCGUI

FontOptions = cWhite s8 +Center         ;Font Options  ex cColor(HTML or HEX) sSize +Center
Font = Arial                       ;Font Style ex. Arial, Arial Bold, Arial bold Italic, Times New Roman
GuiColor = White                  ;Gui Color

Gui, Color, %GuiColor%
Gui, Font, %FontOptions%, %Font%
;------------------Add Button Loop-----------------------
;--------------------------------------------------------



Gui, Add, Button, x10 y10 w50 h50 , VNC Viewer   ;Add VNC button
   


If !pToken := Gdip_Startup()
{
   MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
   ExitApp
}

;===========================Add File Menu,icons ==========================

Menu, FileMenu, Add, Add Client, c
    hBitmap := ExtractIcontohBitmap("C:\Program Files\RealVNC\VNC4\vncviewer.exe", 1, 16)
   MI_SetMenuItemBitmap("FileMenu", 1, hBitmap)
   
Menu, FileMenu, Add, Enable VNCGUI, c
    hBitmap := ExtractIcontohBitmap("shell32.dll", 45, 16)
    MI_SetMenuItemBitmap("FileMenu", 2, hBitmap)
   
Menu, FileMenu, Add, Disable VNCGUI, c
    hBitmap := ExtractIcontohBitmap("shell32.dll", 48, 16)
    MI_SetMenuItemBitmap("FileMenu", 3, hBitmap) ; exit

Menu, FileMenu, Add

Menu, FileMenu, Add, Exit, c
   MI_SetMenuItemBitmap("FileMenu", 5, 6) ; exit

MI_SetMenuStyle("FileMenu", 0x4000000)

;===========================Add Edit Menu,icons ==========================
Menu, EditMenu, Add, Edit this Script, c
    hBitmap := ExtractIcontohBitmap(A_AhkPath, 2, 16)
   MI_SetMenuItemBitmap("EditMenu", 1, hBitmap)
   
Menu, EditMenu, Add, Edit Client List, c
    hBitmap := ExtractIcontohBitmap(A_ProgramFiles "\AutoHotkey\SciTE\SciTE.exe", 1, 16)
   MI_SetMenuItemBitmap("EditMenu", 2, hBitmap)
   
Menu, EditMenu, Add

Menu, EditMenu, Add, Edit Script on J:\, c
    hBitmap := ExtractIcontohBitmap(A_AhkPath, 2, 16)
   MI_SetMenuItemBitmap("EditMenu", 4, hBitmap)
   
Menu, EditMenu, Add, Edit IP List on J:\, c
    hBitmap := ExtractIcontohBitmap(A_ProgramFiles "\AutoHotkey\SciTE\SciTE.exe", 1, 16)
   MI_SetMenuItemBitmap("EditMenu", 5, hBitmap)

MI_SetMenuStyle("EditMenu", 0x4000000)


;===========================Add BackUp Menu,icons ==========================
Menu, BackUpMenu, Add, Back Up VNCGUI on J:\, c
    hBitmap := ExtractIcontohBitmap("shell32.dll", 69, 16)
   MI_SetMenuItemBitmap("BackUpMenu", 1, hBitmap)
   
Menu, BackUpMenu, Add, Back Up VNCGUI Directory, c
    hBitmap := ExtractIcontohBitmap("shell32.dll", 69, 16)
   MI_SetMenuItemBitmap("BackUpMenu", 2, hBitmap)

MI_SetMenuStyle("BackUpMenu", 0x4000000)

;===========================Add Help Menu,icons ==========================
Menu, HelpMenu, Add, Client List Help, c
    hBitmap := ExtractIcontohBitmap(A_WinDir "\hh.exe", 1, 16)
   MI_SetMenuItemBitmap("HelpMenu", 1, hBitmap)
   
Menu, HelpMenu, Add, Script Help, c
    hBitmap := ExtractIcontohBitmap(A_WinDir "\hh.exe", 1, 16)
   MI_SetMenuItemBitmap("HelpMenu", 2, hBitmap)

MI_SetMenuStyle("HelpMenu", 0x4000000)

;===========================Add About Menu,icons==========================
Menu, AboutMenu, Add, About, c
    hBitmap := ExtractIcontohBitmap("shell32.dll", 24, 16)
   MI_SetMenuItemBitmap("AboutMenu", 1, hBitmap)

    ;MI_SetMenuItemIcon("AboutMenu", 1, "shell32.dll", 24, 16)

MI_SetMenuStyle("AboutMenu", 0x4000000)


;======================Attach the sub-menus that were created above===================

Menu, MyMenuBar, Add, File, :FileMenu
Menu, MyMenuBar, Add, Edit, :EditMenu
Menu, MyMenuBar, Add, Back Up, :BackUpMenu
Menu, MyMenuBar, Add, Help, :HelpMenu
Menu, MyMenuBar, Add, About, :AboutMenu
Gui, Menu, MyMenuBar


;======================Show Main Gui ===================

Gui +OwnDialogs +LastFound
WinTitle = Real VNC %A_ComputerName% -- %A_IPAddress1%
Gui, Show, w200 h200, %WinTitle%
MainWin := WinExist()
Return


;============Button Handler=======================
;=================================================


ButtonVNCViewer:
MsgBox, Button Label Worked!!!!
Return

c:
MsgBox, %A_ThisMenu%`n%A_ThisMenuItem%`n%A_ThisMenuItemPos%
Return

ExtractIcon(Filename, IconNumber, IconSize=0)
{
    static SmallIconSize, LargeIconSize
    if (!SmallIconSize) {
        SysGet, SmallIconSize, 49  ; 49, 50  SM_CXSMICON, SM_CYSMICON
        SysGet, LargeIconSize, 11  ; 11, 12  SM_CXICON, SM_CYICON
    }


    VarSetCapacity(phicon, 4, 0)
    h_icon = 0

    ; If possible, use PrivateExtractIcons, which supports any size of icon.
    if A_OSVersion in WIN_VISTA,WIN_2003,WIN_XP,WIN_2000
    {
        VarSetCapacity(piconid, 4, 0)
       
        ; MSDN: "... this function is deprecated ..." (oh well)
        ret := DllCall("PrivateExtractIcons"
            , "str", Filename
            , "int", IconNumber-1   ; zero-based index of the first icon to extract
            , "int", IconSize
            , "int", IconSize
            , "str", phicon         ; pointer to an array of icon handles...
            , "str", piconid        ; piconid - won't be used
            , "uint", 1             ; nIcons - number of icons to extract
            , "uint", 0, "uint")    ; flags
       
        if (ret && ret != 0xFFFFFFFF)
            h_icon := NumGet(phicon)
    }
    else
    {   ; Use ExtractIconEx, which only returns 16x16 or 32x32 icons.
        VarSetCapacity(phiconSmall, 4, 0)
       
        ; Extract the icon from an executable, DLL or icon file.
        if DllCall("shell32.dll\ExtractIconExA"
            , "str", Filename
            , "int", IconNumber-1   ; zero-based index of the first icon to extract
            , "str", phicon         ; pointer to an array of icon handles...
            , "str", phiconSmall
            , "uint", 1)
        {
            ; Use the best-fit size; clean up the other.
            if (IconSize <= SmallIconSize) {
                DllCall("DestroyIcon", "uint", NumGet(phicon))
                h_icon := NumGet(phiconSmall)
            } else {
                DllCall("DestroyIcon", "uint", NumGet(phiconSmall))
                h_icon := NumGet(phicon)
            }
        }
    }

    return h_icon
}

ExtractIcontohBitmap(FileName, IconNumber, IconSize){
   
    hIcon := ExtractIcon(Filename, IconNumber, IconSize)
    If !hIcon
    {
        MsgBox, Icon doesn't exist.`nFileName = %FileName%`nIconNumber = %IconNumber%
        Return 0
    }
    pBitmap := Gdip_CreateBitmapFromHICON(hIcon)
    If !pBitmap
    {
        MsgBox, pBitmap doesn't exist.`nFileName = %FileName%`nIconNumber = %IconNumber%
        Return 0
    }
    hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
    If !pBitmap
    {
        MsgBox, hBitmap doesn't exist.`nFileName = %FileName%`nIconNumber = %IconNumber%
        Return 0
    }
    Else
        Return hBitmap
}


#Include GDIP.ahk
#Include MI.ahk


   ;Exits Apllication

GUIClose:
ExitApp


Hope this helps someone else.


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: March 13th, 2010, 3:26 am 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7502
Location: Australia
Quote:
v2.21 (2010-03-13)
  • Fixed: WM_COMMAND messages received by subclassed GUI windows were erroneously forwarded to the script's main window. This broke button gLabels.
  • Fixed: Unicode incompatibility in MI_ExtractIcon.


Report this post
Top
 Profile  
Reply with quote  
 Post subject: png files as menu icons?
PostPosted: March 17th, 2010, 4:19 pm 
Is possible to use ImageList from Listiview to use as icons in menus?

The best is that ImageList can read pngs, bmps, etc file formats... Ico files are really the worst bitmap solution...


Report this post
Top
  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 132 posts ]  Go to page Previous  1 ... 3, 4, 5, 6, 7, 8, 9  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: Uberi, Yahoo [Bot] and 14 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