Ward

GUICtrlMenuEx UDF (Standard Menu With Icon)

15 posts in this topic

#1 ·  Posted (edited)

looks beautiful, and I like it very much. But I need the standard menu style with icon support on my new application. I search on the forums but I can't find a complete solution works both under XP and Win7. So I wrote one. The screenshot says everything

This UDF has only two key functions: _GUICtrlMenuEx_Startup() and _GUICtrlMenuEx_SetItemIcon(). But for convenient to use, _GUICtrlMenuEx_AddMenuItem() and _GUICtrlMenuEx_InsertMenuItem() warp the standard UDF and accept similar parameters except the icon handle. There are also two convenient functions to add menu bar more quickly (_GUICtrlMenuEx_AddMenuBar() and _GUICtrlMenuEx_InsertMenuBar()). See the example for detail usage.

Technical speaking, this UDF use the MSDN suggested method to convert an icon to bitmap. Another simple way discussed before on the forums is to use GdipCreateBitmapFromHICON. But this function seems poor support to alpha channel icon. So I choose the MSDN's way. Complete code in __GUICtrlMenuEx_CreateBitmapFromIcon_Vista(). It was converted from MSDN's CVistaMenuApp.cpp.

Have a nice day ! :x

GUICtrlMenuEx.zip (3.89K)

Number of downloads: 58

2010/12/16 Update Note:

#Better windows version detect (Thanks to Mat, wraithdu)

#A bug about redraw icon (Typing error in PaintParams structure)

#DLL path problem in example (Thanks to Raupi)

GUICtrlMenuEx.zip

post-10768-0-15288100-1292377349_thumb.p

post-10768-0-12109500-1292377357_thumb.p

Edited by Ward
2 people like this

新版 _ArrayAdd 的白痴作者,不管是誰,去死一死好了

 

Share this post


Link to post
Share on other sites



I like it, but for me there are no icons at all.

I use WinXP SP2


Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Share this post


Link to post
Share on other sites

It work great under Win7/64 but not under WinXP SP3..

The problem on WinXP is the path to the shell32.dll.

On my System the Windows Path ist \WINXP.

With this example the UDF run without Problems:

; ===============================================================================================================================
; GUICtrlMenuEx UDF Example
; Purpose: Demonstrate The Usage Of GUICtrlMenuEx UDF
; Author:  Ward
; ===============================================================================================================================

#Include "GUICtrlMenuEx.au3"

GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

Example1()
Example2()
Example3()
Example4()

Func Example1()
    Example("Example1", Default, 24, 24, 24, 24, "Basic Example")
EndFunc

Func Example2()

    Example("Example2", Default, 16, 36, 48, 64, "Differet Icon Size")
EndFunc

Func Example3()
    Example("Example3", True, 24, 24, 24, 24, "Force Use Callback (2K/XP Default)")
EndFunc

Func Example4()
    Example("Example4", False, 24, 24, 24, 24, "Force Not Use Callback (Vista/Win7 Default)")
EndFunc

Func Example($Title, $UseCallback, $Size1, $Size2, $Size3, $Size4, $Text)

    _GUICtrlMenuEx_Startup($UseCallback)

    Local $Icon1 = _WinAPI_ShellExtractIcons(@WindowsDir & "\system32\shell32.dll", 0, $Size1, $Size1)
    Local $Icon2 = _WinAPI_ShellExtractIcons(@WindowsDir & "\system32\shell32.dll", 1, $Size2, $Size2)
    Local $Icon3 = _WinAPI_ShellExtractIcons(@WindowsDir & "\system32\shell32.dll", 2, $Size3, $Size3)
    Local $Icon4 = _WinAPI_ShellExtractIcons(@WindowsDir & "\system32\shell32.dll", 3, $Size4, $Size4)
    Local $Icon5 = _WinAPI_ShellExtractIcons(@WindowsDir & "\system32\shell32.dll", 7, 64, 64)

    Local $GUI = GUICreate($Title, 600)

    Local $SubMenu = _GUICtrlMenu_CreatePopup()
    _GUICtrlMenuEx_AddMenuItem($SubMenu, "Test Menu Item 1", 1001, $Icon1)
    _GUICtrlMenuEx_AddMenuItem($SubMenu, "Test Menu Item 2", 1002, $Icon2)
    _GUICtrlMenuEx_AddMenuBar($SubMenu)
    _GUICtrlMenuEx_AddMenuItem($SubMenu, "Test Menu Item 3", 1003, $Icon3)

    _GUICtrlMenuEx_InsertMenuItem($SubMenu, 1, "Test Menu Item Insertion", 1004, $Icon4)
    _GUICtrlMenuEx_InsertMenuBar($SubMenu, 1)

    Local $MainMenu = _GUICtrlMenu_CreateMenu()
    _GUICtrlMenu_AddMenuItem($MainMenu, $Text, 0, $SubMenu)
    _GUICtrlMenuEx_SetItemIcon($MainMenu, 0, $Icon5)
    _GUICtrlMenu_SetMenu($GUI, $MainMenu)

    GUISetState()

    _WinAPI_DestroyIcon($Icon1)
    _WinAPI_DestroyIcon($Icon2)
    _WinAPI_DestroyIcon($Icon3)
    _WinAPI_DestroyIcon($Icon4)
    _WinAPI_DestroyIcon($Icon5)

    While 1
        Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            GUISetState(@SW_HIDE)
            _GUICtrlMenuEx_DestroyMenu($SubMenu)    ; Release the image resource used by GUICtrlMenuEx
            _GUICtrlMenuEx_DestroyMenu($MainMenu)   ; Release the image resource used by GUICtrlMenuEx
            ExitLoop

        Case $GUI_EVENT_SECONDARYUP
            _GUICtrlMenu_TrackPopupMenu($SubMenu, $GUI)

        EndSwitch
    WEnd
EndFunc

Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    Local $Code =_WinAPI_HiWord($wParam)
    If $Code = 0 Then ; Menu Command
        Local $MenuID = _WinAPI_LoWord($wParam)
        ConsoleWrite("MenuID " & $MenuID & @CRLF)
    EndIf
EndFunc

Func _WinAPI_ShellExtractIcons($Icon, $Index, $Width, $Height)
    Local $Ret = DllCall('shell32.dll', 'int', 'SHExtractIconsW', 'wstr', $Icon, 'int', $Index, 'int', $Width, 'int', $Height, 'ptr*', 0, 'ptr*', 0, 'int', 1, 'int', 0)
    If @Error Or $Ret[0] = 0 Or $Ret[5] = Ptr(0) Then Return SetError(1, 0, 0)
    Return $Ret[5]
EndFunc

PS: Sorry for my bad english. :x

Share this post


Link to post
Share on other sites

It work great under Win7/64 but not under WinXP SP3..

The problem on WinXP is the path to the shell32.dll.

On my System the Windows Path ist \WINXP.

PS: Sorry for my bad english. :x

Thanks, I will fix the path problem later.

新版 _ArrayAdd 的白痴作者,不管是誰,去死一死好了

 

Share this post


Link to post
Share on other sites

I don't have a testing base, so I'm only guessing, but will this work on all operating systems?

Surely there is better way to detect which type to use than Switch @OSVersion... Like check if the version of comctl is 6 or higher. That way it will work for decades to come :x

Share this post


Link to post
Share on other sites

It's true. Detecting @OSVersion seems not a good method. I think a better way is to detected the "Operating System Version". If the version number > 6.0 (Vista) then the "Vista Style Menu" should be used. But I don't have all version of system to test, too. Is there any other good idea?


新版 _ArrayAdd 的白痴作者,不管是誰,去死一死好了

 

Share this post


Link to post
Share on other sites

One of the simplest implementations I ever did:

Global Const $tagOSVERSIONINFO = "DWORD dwOSVersionInfoSize; DWORD dwMajorVersion; DWORD dwMinorVersion; DWORD dwBuildNumber; DWORD dwPlatformId; wchar szCSDVersion[128]"

MsgBox(0, "test", OSVersion())

Func OSVersion()
    Local $tOSVI = DllStructCreate($tagOSVERSIONINFO)

    DllStructSetData($tOSVI, "dwOSVersionInfoSize", DllStructGetSize($tOSVI))
    DllCall("kernel32.dll", "bool", "GetVersionExW", "ptr", DllStructGetPtr($tOSVI))

    Return DllStructGetData($tOSVI, "dwMajorVersion") & "." & DllStructGetData($tOSVI, "dwMinorVersion")
EndFunc

Share this post


Link to post
Share on other sites

thanks a lot, wraithdu !


新版 _ArrayAdd 的白痴作者,不管是誰,去死一死好了

 

Share this post


Link to post
Share on other sites

Great menu system!

I have a question. I have tried _WinAPI_LoadImage to load bitmap and then _GUICtrlMenuEx_SetItemIcon but it just won't display any image on Windows 7, haven't yet tried XP. I also tried calling user32.dll LoadImage on MenuEx but it's not working, while on menus created by GUICtrlCreateContextMenu it's working nicely. Does anybody have an idea how to load image in this menu from image file?

Share this post


Link to post
Share on other sites

Great menu system!

I have a question. I have tried _WinAPI_LoadImage to load bitmap and then _GUICtrlMenuEx_SetItemIcon but it just won't display any image on Windows 7, haven't yet tried XP. I also tried calling user32.dll LoadImage on MenuEx but it's not working, while on menus created by GUICtrlCreateContextMenu it's working nicely. Does anybody have an idea how to load image in this menu from image file?

Ok, I did it after few minutes well spent, here's example:

$_Gui = GUICreate ( "SimpleGUI", 400, 300 )
GUISetState(@SW_SHOW)
_GUICtrlMenuEx_Startup(Default)
$_Sub_Menu = _GUICtrlMenu_CreatePopup()
_GUICtrlMenuEx_AddMenuItem( $_Sub_Menu, "Test Menu Item 1", 1001 )
_GUICtrlMenu_SetItemBmp( $_Sub_Menu, 0, _WinAPI_LoadImage(0, @ScriptDir & "\my_test.bmp", $IMAGE_BITMAP, 24, 24, $LR_LOADFROMFILE) )
_GUICtrlMenu_TrackPopupMenu($_Sub_Menu, $_Gui)

If anybody has smarter/better method I would love to know. :mellow:

Share this post


Link to post
Share on other sites

Can anybody please reupload this item.
It looks like it got lost on the server somehow .. :/

 

Quote

Sorry, there is a problem

We could not locate the item you are trying to view.

Error code: 2S328/1

 

Thank you! :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now