benners

Getting handle to a .ico file

4 posts in this topic

I am trying to add icons to a menu and I am having an issue when it comes to actual .ico files. The function I am using works with dll and exe files and I have tried to modify it to work with .ico with no success.

I have cobbled the code together from the help file and this forum and now it's time to ask for help before the dog gets kicked j/k.

What I need to know is either where I am going wrong or another way to get a handle to an icon using and actual icon file so that it can be converted to a bitmap and added to a menu. The _WinAPI_ExtractIconEx is successful as $i_Result = 1, for 1 icon extracted but no icon is displayed.

I would have thought _WinAPI_ShellExtractIcon would have worked with .ico files but no icon is diplayed.

 

Cheers

; #FUNCTION# ====================================================================================================================
; Name ..........: CreateBitmapFromIcon
; Description ...: Create a bitmap image from an icon
; Syntax ........: CreateBitmapFromIcon($iBackground, $sIcon, $iIndex, $iWidth, $iHeight)
; Return values .: Handle to the bitmap
; Author ........: Yashied
; Modified ......: Benners 28/12/2015
; Remarks .......:
; Related .......:
; Link ..........: https://www.autoitscript.com/forum/topic/97365-how-to-convert-a-hicon-to-a-32-bit-hbitmap/?do=findComment&comment=700670
; ===============================================================================================================================
Func CreateBitmapFromIcon($sIcon, $iIndex = 0, $iWidth = 16, $iHeight = 16)
    Local $hDC = _WinAPI_GetDC(0)
    Local $hBackDC = _WinAPI_CreateCompatibleDC($hDC)
    Local $hBitmap = _WinAPI_CreateSolidBitmap(0, _WinAPI_GetSysColor($COLOR_MENU), $iWidth, $iHeight)
    Local $hBackSv = _WinAPI_SelectObject($hBackDC, $hBitmap)
    Local $hIcon = 0

    If StringRight($sIcon, 4) = '.ico' Then
        Local $tIcon = DllStructCreate("int Handle")
        Local $i_Result = _WinAPI_ExtractIconEx("C:\Program Files (x86)\AutoIt3\Beta\Icons\au3script_v10.ico", 0, 0, DllStructGetPtr($tIcon), 1)
        $hIcon = DllStructGetData($tIcon, "Handle")
    Else
        $hIcon = _WinAPI_ShellExtractIcon($sIcon, $iIndex, $iWidth, $iHeight)
    EndIf

    If Not @error Then
        _WinAPI_DrawIconEx($hBackDC, 0, 0, $hIcon, 0, 0, 0, 0, $DI_NORMAL)
        _WinAPI_DestroyIcon($hIcon)
    EndIf

    _WinAPI_SelectObject($hBackDC, $hBackSv)
    _WinAPI_ReleaseDC(0, $hDC)
    _WinAPI_DeleteDC($hBackDC)

    Return $hBitmap
EndFunc   ;==>CreateBitmapFromIcon

 

Share this post


Link to post
Share on other sites



OK, I have spent some more time looking at other examples and googling. I have got round the ico file issues by using another way to get the associated icon. This works mostly as I want but the icons look shite when viewed lower than 32x32. This appears to be when the icon are gotten using shell32.dll cal ExtractAssociatedIcon. I found using SHGetFileInfo maybe better but that requires further reading and hair pulling.

below is the full code for testing, if anyone has the time to lend a hand with the icon size\display issues and an ini is attached for the program.

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_au3check_parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#AutoIt3Wrapper_Icon=Icons\BennersQL.ico
#AutoIt3Wrapper_Res_Description=Shortcut launcher for files
#AutoIt3Wrapper_Res_Fileversion=1.0.0.8
#AutoIt3Wrapper_Res_Fileversion_AutoIncrement=y
#AutoIt3Wrapper_Res_LegalCopyright=@ Benners Inc 2015
#AutoIt3Wrapper_Res_requestedExecutionLevel=requireAdministrator
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

#include <array.au3>
#include <ButtonConstants.au3>
#include <ComboConstants.au3>
#include <FileConstants.au3>
#include <GUIConstantsEx.au3>
#include <GuiComboBox.au3>
#include <GuiMenu.au3>
#include <GuiStatusBar.au3>
#include <IE.au3>
#include <misc.au3>
#include <MsgBoxConstants.au3>
#include <WindowsConstants.au3>
#include 'UDF\Logging_Functions.au3'
#include <WinAPIShellEx.au3>
If Not $CMDLINE[0] Then
    If UBound(ProcessList(@ScriptName)) > 2 Then Exit
ElseIf $CMDLINE[1] <> '/restart' Then
    Exit
EndIf

Opt("GUIOnEventMode", 1)

; global vars
Global $g_s_INI = stringtrimright(@ScriptFullPath,3) & 'ini'
Global $g_s_DefaultTitle = 'Benners'' Quick Launch'
Global $g_a_MenuEvents[50][2]

Global $g_i_Dpi = GetDPI()

Global $g_h_Main_GUI = 0
Global $g_h_MainMenu = 0
Global $g_h_Status_bar = 0

Global Enum $g_id_FileAdd_mnu = 1000, $g_id_FileOpen_mnu, $g_id_FilePreferences_mnu, $g_id_FileExit_mnu

Main_GUI_Draw() ; create the gui

; set the function to run when a menu message is received.
GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

; show the gui
GUISetState(@SW_SHOW)

While 1
    Sleep(100)
WEnd

Func Main_GUI_Draw()
    Local $i_Left = IniRead($g_s_INI, 'GUI', 'Left', -1)
    Local $i_Top = IniRead($g_s_INI, 'GUI', 'Top', -1)

    $g_h_Main_GUI = GUICreate(IniRead($g_s_INI, 'GUI', 'Title', $g_s_DefaultTitle), 491 * $g_i_Dpi, 130 * $g_i_Dpi, $i_Left, $i_Top)

    ; set the GUI on top of others
    WinSetOnTop($g_h_Main_GUI, '', 1)
    GUISetOnEvent($GUI_EVENT_CLOSE, "Main_GUI_Close")

    ; create a menu (This is the main menu, others will be added to this)
    $g_h_MainMenu = _GUICtrlMenu_CreateMenu()

    #Region #### create the default file menu ####
    ; create a menu (this will be the File menu added to the main menu)
    Local $h_File_mnu = _GUICtrlMenu_CreateMenu()

    ; add items to the file menu
    _GUICtrlMenu_AddMenuItem($h_File_mnu, "Add To Menu", $g_id_FileAdd_mnu)
    _GUICtrlMenu_AddMenuItem($h_File_mnu, "Open", $g_id_FileOpen_mnu)
    _GUICtrlMenu_AddMenuItem($h_File_mnu, "")
    _GUICtrlMenu_AddMenuItem($h_File_mnu, "Preferences", $g_id_FilePreferences_mnu)
    _GUICtrlMenu_AddMenuItem($h_File_mnu, "")
    _GUICtrlMenu_AddMenuItem($h_File_mnu, "Exit", $g_id_FileExit_mnu)

    ; set the menu icons
    _GUICtrlMenu_SetItemBmp($h_File_mnu, $g_id_FileAdd_mnu, CreateBitmapFromIcon(@SystemDir & '\imageres.dll', 156, 0), False)
    _GUICtrlMenu_SetItemBmp($h_File_mnu, $g_id_FileOpen_mnu, CreateBitmapFromIcon(@SystemDir & '\imageres.dll', 7, 0), False)
    _GUICtrlMenu_SetItemBmp($h_File_mnu, $g_id_FilePreferences_mnu, CreateBitmapFromIcon(@SystemDir & '\imageres.dll', 64, 0), False)
    _GUICtrlMenu_SetItemBmp($h_File_mnu, $g_id_FileExit_mnu, CreateBitmapFromIcon(@SystemDir & '\shell32.dll', 27, 0), False)

    ; add the file menu to the main menu
    _GUICtrlMenu_AddMenuItem($g_h_MainMenu, 'File', 0, $h_File_mnu)
    #EndRegion #### create the default file menu ####

    #Region #### create the users main menu ####
    MainMenu_CreateDynamic($g_a_MenuEvents)
    #EndRegion #### create the users main menu ####

    ; Set window menu
    _GUICtrlMenu_SetMenu($g_h_Main_GUI, $g_h_MainMenu)
EndFunc   ;==>Main_GUI_Draw

Func Main_GUI_Close()
Exit
EndFunc   ;==>Main_GUI_Close

Func MainMenu_AddItem()
    Local $s_GUITitle = 'Add Menu Item'

    ; get the main guis position
    Local $a_WindowPos = WinGetPos($g_s_DefaultTitle)

    ; create the main gui using main gui window positions
    Local $h_AddItem_GUI = GUICreate($s_GUITitle, 305 * $g_i_Dpi, 300 * $g_i_Dpi, $a_WindowPos[0], $a_WindowPos[1])

    #Region #### select a file group ############################
    GUICtrlCreateGroup("Select a File", 8 * $g_i_Dpi, 5 * $g_i_Dpi, 289 * $g_i_Dpi, 64 * $g_i_Dpi)

    Local $id_FileName_lbl = GUICtrlCreateLabel("", 16 * $g_i_Dpi, 32 * $g_i_Dpi, 230 * $g_i_Dpi, 17 * $g_i_Dpi, $DT_END_ELLIPSIS)

    Local $id_FileSelect_btn = GUICtrlCreateButton("...", 253 * $g_i_Dpi, 28 * $g_i_Dpi, 30 * $g_i_Dpi, 25 * $g_i_Dpi)
    GUICtrlSetFont(-1, 10, 800, 0, "MS Sans Serif")
    GUICtrlSetTip(-1, "Select a file to add to the menu")

    GUICtrlCreateGroup("", -99, -99, 1, 1)
    #EndRegion #### select a file group ############################

    #Region #### select a menu group ############################
    GUICtrlCreateGroup("Select a Menu", 8 * $g_i_Dpi, 72 * $g_i_Dpi, 289 * $g_i_Dpi, 80 * $g_i_Dpi)

    GUICtrlCreateLabel("Current Menu Items", 18 * $g_i_Dpi, 94 * $g_i_Dpi, 96 * $g_i_Dpi, 17 * $g_i_Dpi)

    Local $id_MainMenuList_cbo = GUICtrlCreateCombo("", 133 * $g_i_Dpi, 92 * $g_i_Dpi, 150 * $g_i_Dpi, 25 * $g_i_Dpi, BitOR($CBS_DROPDOWNLIST, $CBS_AUTOHSCROLL))
    GUICtrlSetTip(-1, "Displays list of current menu items")

    ; set the combo data, read the main menu list from the ini
    Local $a_MenuItems = IniReadSection($g_s_INI, 'MainMenu')

    If Not @error Then
        ; loop through the array and add the strings
        For $i = 1 To $a_MenuItems[0][0]
            _GUICtrlComboBox_AddString($id_MainMenuList_cbo, $a_MenuItems[$i][0])
        Next
    EndIf

    Local $s_AddNew = 'Add New Menu..'

    ; add new menu option to end of list
    _GUICtrlComboBox_AddString($id_MainMenuList_cbo, $s_AddNew)

    Local $id_AddSubMenu_chk = GUICtrlCreateCheckbox("Add Sub Menu", 18 * $g_i_Dpi, 123 * $g_i_Dpi, 90 * $g_i_Dpi, 17 * $g_i_Dpi)
    GUICtrlSetTip(-1, "Add the menu item under a sub menu")

    Local $id_AddSubMenu_inp = GUICtrlCreateInput("", 132 * $g_i_Dpi, 121 * $g_i_Dpi, 150 * $g_i_Dpi, 21 * $g_i_Dpi)
    GUICtrlSetState(-1, $GUI_DISABLE)
    GUICtrlSetTip(-1, "Type the name of the sub menu")
    GUICtrlCreateGroup("", -99, -99, 1, 1)
    #EndRegion #### select a menu group ############################

    #Region #### create menu group ##############################
    GUICtrlCreateGroup("Create Menu Item", 8 * $g_i_Dpi, 156 * $g_i_Dpi, 289 * $g_i_Dpi, 80 * $g_i_Dpi)
    GUICtrlCreateLabel("Type a Name", 18 * $g_i_Dpi, 178 * $g_i_Dpi, 68 * $g_i_Dpi, 17 * $g_i_Dpi)

    Local $id_MenuItemText_inp = GUICtrlCreateInput("", 133 * $g_i_Dpi, 176 * $g_i_Dpi, 150 * $g_i_Dpi, 21 * $g_i_Dpi)
    GUICtrlSetTip(-1, "Type the name for the menu item")

    Local $id_AddSeparator_chk = GUICtrlCreateCheckbox("Add Separator Line", 18 * $g_i_Dpi, 207 * $g_i_Dpi, 113 * $g_i_Dpi, 17 * $g_i_Dpi)
    GUICtrlSetTip(-1, "Add a separator line after the menu item")
    GUICtrlCreateGroup("", -99, -99, 1, 1)
    #EndRegion #### create menu group ##############################

    #Region #### action buttons #################################
    Local $id_Add_btn = GUICtrlCreateButton("Add", 70 * $g_i_Dpi, 244 * $g_i_Dpi, 75 * $g_i_Dpi, 25 * $g_i_Dpi)
    GUICtrlSetTip(-1, "Add the menu item")
    GUICtrlSetState(-1, $GUI_DISABLE)

    Local $id_Close_btn = GUICtrlCreateButton("Close", 160 * $g_i_Dpi, 244 * $g_i_Dpi, 75 * $g_i_Dpi, 25 * $g_i_Dpi)
    GUICtrlSetTip(-1, "Fuck It I have changed my mind")
    #EndRegion #### action buttons #################################

    Local $h_StatusBar = _GUICtrlStatusBar_Create($h_AddItem_GUI)
    _GUICtrlStatusBar_SetText($h_StatusBar, 'Idle...')

    ; show the gui
    GUISetState(@SW_SHOW)

    ; set the gui on top of other windows
    WinSetOnTop($h_AddItem_GUI, '', 1)

;~  ; switch the gui to the add menu item one
    Switch_GUI($h_AddItem_GUI, 0, 1, $g_h_Main_GUI)

    Local $s_FileName = ''
    Local $s_SelectedMenuText = ''
    Local $s_SubMenuText = ''
    Local $s_MenuItemText = ''
    Local $s_IniKey = 'menuitem'
    Local $s_IniValue = ''

    Local $a_Filenames = '' ; array holding the selected file name(s) to add to menu

    Local $i_ItemCount = 0 ; menuitems info to add to ini section
    Local $i_NewMenuItems = 1 ; number of items to add
    Local $i_CurrentElement = 0 ; current element of the array holding the selected file name to add
    Local $i_FileAddCount = 1 ; number of files added to the menu

    Local $i_MenuListCurSel = 0

    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE, $id_Close_btn
                ExitLoop

            Case $id_FileSelect_btn
                ; open a file select dialog
                $s_FileName = FileOpenDialog('Please Select The File(s) To Be Added', "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", 'All(*.*)', $FD_MULTISELECT, '', $h_AddItem_GUI)
                If @error Then ContinueLoop

                ; get the file names
                $a_Filenames = StringSplit($s_FileName, '|')

                ; get total number of files to add
                $i_ItemCount = $a_Filenames[0]

                ; check if multiple files
                If Not @error Then ; multiple files
                    ; recreate the file path from the array
                    $s_FileName = $a_Filenames[1] & '\' & $a_Filenames[2]

                    ; set which array element to start from used by add button)
                    $i_CurrentElement = 2

                    ; subtract 1 from file count (ignore folder path)
                    $i_ItemCount = $a_Filenames[0] - 1
                Else ; single file
                    $s_FileName = $a_Filenames[1]

                    ; set which array element to start from used by add button)
                    $i_CurrentElement = 1
                EndIf

                ; update the label with the file path
                GUICtrlSetData($id_FileName_lbl, $s_FileName)
                GUICtrlSetTip($id_FileName_lbl, $s_FileName)

                ; add the file name to the  menu item input
                If GUICtrlRead($id_MainMenuList_cbo) And $s_FileName Then GUICtrlSetState($id_Add_btn, $GUI_ENABLE)
                $s_FileName = File_GetNameFromString($s_FileName)
                GUICtrlSetData($id_MenuItemText_inp, StringTrimRight(File_GetNameFromString($s_FileName), 4))
                _GUICtrlStatusBar_SetText($h_StatusBar, 'Adding (' & $i_FileAddCount & '/' & $i_ItemCount & '): ' & $s_FileName)

            Case $id_MainMenuList_cbo
                ; get the index of the current combo selection
                $i_MenuListCurSel = _GUICtrlComboBox_GetCurSel($id_MainMenuList_cbo)

                ; get the selected menu text
                $s_SelectedMenuText = GUICtrlRead($id_MainMenuList_cbo)

                If $s_SelectedMenuText = 'Add New Menu..' Then
                    $i_MenuListCurSel = -1

                    ; get the add menu item gui position
                    $a_WindowPos = WinGetPos($s_GUITitle)

                    ; prompt for menu text
                    $s_SelectedMenuText = InputBox('Create New Menu', 'Please enter the name of the new menu', '', ' M15', _
                            350 * $g_i_Dpi, 150 * $g_i_Dpi, $a_WindowPos[0], $a_WindowPos[1], 0, $h_AddItem_GUI)

                    ; check if user cancelled the input
                    If Not @error And $s_SelectedMenuText Then
                        ; set the index for the combo selection
                        $i_MenuListCurSel = 0

                        ; add the new menu name to the list
                        _GUICtrlComboBox_InsertString($id_MainMenuList_cbo, $s_SelectedMenuText, 0)
                    EndIf

                    ; select the last user selected menu
                    _GUICtrlComboBox_SetCurSel($id_MainMenuList_cbo, $i_MenuListCurSel)
                EndIf

                ; check if add button is to be enabled
                If $s_SelectedMenuText And GUICtrlRead($id_FileName_lbl) Then
                    GUICtrlSetState($id_Add_btn, $GUI_ENABLE)
                    _GUICtrlStatusBar_SetText($h_StatusBar, 'Press add button')
                Else
                    GUICtrlSetState($id_Add_btn, $GUI_DISABLE)
                EndIf

            Case $id_AddSubMenu_chk
                If GUICtrlRead($id_AddSubMenu_chk) = $GUI_CHECKED Then
                    ; enable the input box
                    GUICtrlSetState($id_AddSubMenu_inp, $GUI_ENABLE)
                Else
                    ; disable the input and clear entered data
                    GUICtrlSetState($id_AddSubMenu_inp, $GUI_DISABLE)
                EndIf

                ; prompt for menu text
                $s_SubMenuText = InputBox('Create Sub Menu', 'Please enter the name of the sub menu', '', ' M15', _
                        350 * $g_i_Dpi, 150 * $g_i_Dpi, $a_WindowPos[0], $a_WindowPos[1], 0, $h_AddItem_GUI)

                If Not @error Then
                    GUICtrlSetData($id_AddSubMenu_inp, $s_SubMenuText)
                Else
                    GUICtrlSetState($id_AddSubMenu_chk, $GUI_UNCHECKED)
                    GUICtrlSetState($id_AddSubMenu_inp, $GUI_DISABLE)
                EndIf

            Case $id_Add_btn

                $s_FileName = GUICtrlRead($id_FileName_lbl) ; get the current file location
                $s_SelectedMenuText = GUICtrlRead($id_MainMenuList_cbo) ; get the user selected menu
                $s_MenuItemText = GUICtrlRead($id_MenuItemText_inp) ; get the name for the menu item
                $s_SubMenuText = '' ; check if a sub menu is required
                If GUICtrlRead($id_AddSubMenu_chk) = $GUI_CHECKED Then $s_SubMenuText = GUICtrlRead($id_AddSubMenu_inp)

                ; decide whether to write a menuitem or a sub menu
                If $s_SubMenuText Then
                    $s_IniKey = 'submenu'
                    $s_IniValue = $s_SubMenuText & '|' & $s_MenuItemText & '|' & $s_FileName
                Else
                    $s_IniKey = 'menuitem'
                    $s_IniValue = $s_MenuItemText & '|' & $s_FileName
                EndIf

                ; get any previous menu item entries for the selected menu (enables writing duplicate keys in ini)
                $a_MenuItems = IniReadSection($g_s_INI, $s_SelectedMenuText)

                If @error Then ; section may not exist or is empty
                    ; add the menu name to the list of menus to show
                    IniWrite($g_s_INI, 'MainMenu', $s_SelectedMenuText, '')

                    ; add the menu item settings to the ini
                    IniWrite($g_s_INI, $s_SelectedMenuText, $s_IniKey, $s_IniValue)
                Else
                    ; get the number of menu items currently in the menu section
                    $i_ItemCount = $a_MenuItems[0][0]

                    ; check if a seperator is required
                    If GUICtrlRead($id_AddSeparator_chk) = $GUI_CHECKED Then $i_NewMenuItems = 2

                    ; resize the array for 1 or 2 new menu items
                    ReDim $a_MenuItems[(($i_ItemCount + $i_NewMenuItems) + 1)][2]

                    ; write the none seperator keys to the array first
                    $a_MenuItems[($i_ItemCount + $i_NewMenuItems)][0] = $s_IniKey
                    $a_MenuItems[($i_ItemCount + $i_NewMenuItems)][1] = $s_IniValue

                    If GUICtrlRead($id_AddSeparator_chk) = $GUI_CHECKED Then
                        ; set the ini key to write (for menuitem)
                        $s_IniValue = ''
                        If $s_SubMenuText Then $s_IniValue = $s_SubMenuText & '|'

                        ; add the seperator info
                        $a_MenuItems[$i_ItemCount + 1][0] = $s_IniKey
                        $a_MenuItems[$i_ItemCount + 1][1] = $s_IniValue
                    EndIf

                    ; update the array row count
                    $a_MenuItems[0][0] = UBound($a_MenuItems) - 1

                    ; rewrite the ini section from the new array
                    IniWriteSection($g_s_INI, $s_SelectedMenuText, $a_MenuItems)
                EndIf

                ; check if all the selected file have been addded
                If $a_Filenames[0] = 1 Or $i_CurrentElement = $a_Filenames[0] Then ExitLoop

                #Region #### set data for next file addition ####
                ; reset how many items are to be added to the array
                $i_NewMenuItems = 1

                ; increase number of files added
                $i_FileAddCount += 1

                ; set next array element to be processed
                $i_CurrentElement += 1

                ; build the file path from the array for the next file
                $s_FileName = $a_Filenames[1] & '\' & $a_Filenames[$i_CurrentElement]

                ; add the next file the file name
                GUICtrlSetData($id_FileName_lbl, $s_FileName)
                GUICtrlSetTip($id_FileName_lbl, $s_FileName)

                ; uncheck the sub menu box
                GUICtrlSetState($id_AddSubMenu_chk, $GUI_UNCHECKED)
                GUICtrlSetState($id_AddSubMenu_inp, $GUI_DISABLE)

                ; trim extension and update label
                GUICtrlSetData($id_MenuItemText_inp, File_GetNameFromString($s_FileName, 0))

                ; uncheck the sub menu box
                GUICtrlSetState($id_AddSeparator_chk, $GUI_UNCHECKED)

                ; update the status bar text
                _GUICtrlStatusBar_SetText($h_StatusBar, 'Adding (' & $i_FileAddCount & '/' & ($a_Filenames[0] - 1) & '): ' & File_GetNameFromString($s_FileName))
                #EndRegion #### set data for next file addition ####
        EndSwitch

        Sleep(10)
    WEnd

    GUISetState(@SW_HIDE, $h_AddItem_GUI)
    GUISetState(@SW_RESTORE, $g_h_Main_GUI)
    Switch_GUI($g_h_Main_GUI, 1, 0, $h_AddItem_GUI, 1)
EndFunc   ;==>MainMenu_AddItem

Func MainMenu_CreateDynamic(ByRef $a_MenuEvents, $s_IniFile = $g_s_INI)
    ; get the menu items for the main menu
    Local $a_MainMenuItems = IniReadSection($s_IniFile, 'MainMenu')

    ; some error occured when reading skip menu creation
    If @error Then Return

    Local $a_MenuItems = '' ; array that holds the menu text and actions
    Local $a_MenuData = '' ; array that holds data about the menu items

    Local $h_MenuID = 0 ; main menu id where other menu are created

    Local $i_ItemID = 2000 ; menu id where the item will be created
    Local $h_SubmenuID = 0 ; submenu id where the menu item will be created
    Local $i_MenuItemCount = 0 ; number of menu items. used to resize array later

    Local $s_MenuText = '' ; text of the menus added to the main menu
    Local $s_MenuItemText = '' ; initially, menu type i.e menuitem or submenu. changes later
    Local $s_MenuItemString = '' ; string linked to the menu item, normally a file path
    Local $s_SubMenus = '' ; string to keep track of created sub menus to stop dupes

    ; loop through the user supplied menus
    For $x = 1 To $a_MainMenuItems[0][0]
        ; set the text for the menu
        $s_MenuText = $a_MainMenuItems[$x][0]

        ; create a menu (this will be where the items are added)
        $h_MenuID = _GUICtrlMenu_CreateMenu()

        ; now add any menu or sub menu items to the current main menu item
        $a_MenuItems = IniReadSection($s_IniFile, $s_MenuText)

        ; some error occured when reading continue with next menu item
        If @error Then ContinueLoop

        ; loop through the current main menus items
        For $y = 1 To $a_MenuItems[0][0]
            $s_MenuItemText = $a_MenuItems[$y][0]
            $s_MenuItemString = $a_MenuItems[$y][1]
            $a_MenuData = StringSplit($s_MenuItemString, '|') ; $a_MenuData[1] is the menu text,  $a_MenuData[2] is the file name

            Switch $s_MenuItemText
                Case 'menuitem'
                    ; create a menu item
                    _GUICtrlMenu_AddMenuItem($h_MenuID, $a_MenuData[1], $i_ItemID)

                    ; check the string isn't blank (item maybe a seperator)
                    If $s_MenuItemString Then
                        ; set the icon for the entry
                        MainMenu_SetItemIcon($h_MenuID, $i_ItemID, $a_MenuData[2])

                        ; check the file is there and disable if missing
                        If Not FileExists($a_MenuData[2]) And Not StringInStr($s_MenuItemString, 'http') Then _
                                _GUICtrlMenu_SetItemDisabled($h_MenuID, $i_ItemID, True, False)
                    EndIf
                Case 'submenu'
                    ; set the text for the sub menu
                    $s_MenuItemText = $a_MenuData[1]

                    ; check if the sub menu already exists
                    If Not String_SearchForWords($s_SubMenus, $s_MenuItemText) Then
                        $h_SubmenuID = _GUICtrlMenu_CreateMenu()

                        ; add the created sub menu to a string, this is checked later to stop the creation of dupe menus
                        $s_SubMenus &= $s_MenuItemText & '|'
                    EndIf

                    ; create the sub menu items
                    _GUICtrlMenu_AddMenuItem($h_SubmenuID, $a_MenuData[2], $i_ItemID) ; add the menu item to the sub menu

                    ; set the icon for the entry
                    MainMenu_SetItemIcon($h_MenuID, $i_ItemID, $a_MenuData[3])

                    ; check the file is there and disable if missing
                    If Not FileExists($a_MenuData[3]) And Not StringInStr($s_MenuItemString, 'http') Then _
                            _GUICtrlMenu_SetItemDisabled($h_SubmenuID, $i_ItemID, True, False)

                    ; add the sub menu to the user selected menu
                    _GUICtrlMenu_AddMenuItem($h_MenuID, $a_MenuData[1], $i_ItemID, $h_SubmenuID)
                Case Else
                    ContinueLoop
            EndSwitch

            ; increase the menu item count
            $i_MenuItemCount += 1

            ; add the item string value to the array
            $a_MenuEvents[$i_MenuItemCount][0] = $i_ItemID
            $a_MenuEvents[$i_MenuItemCount][1] = StringRegExpReplace($s_MenuItemString, "^.*\|", "")

            ; increase the the menu id
            $i_ItemID += 1
        Next

        ; add the created menu to the main menu
        _GUICtrlMenu_AddMenuItem($g_h_MainMenu, $s_MenuText, 0, $h_MenuID)
    Next

    ; update the array total item count
    $a_MenuEvents[0][0] = $i_MenuItemCount

    ; resize array to include only added items
    ReDim $a_MenuEvents[$i_MenuItemCount + 1][2]
;~  _ArrayDisplay($a_MenuEvents, $i_MenuItemCount)
EndFunc   ;==>MainMenu_CreateDynamic

Func MainMenu_DefaultEvents()
    Switch @GUI_CtrlId
        Case $g_id_FileAdd_mnu
            ; draw the Menu editor
            MainMenu_AddItem()

        Case $g_id_FileOpen_mnu
            ; open a file select dialog
            Local $s_FileName = FileOpenDialog('Please Select a File', "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", 'All(*.*)', 0, '', $g_h_Main_GUI)
            If @error Then Return

            ; minimize the main GUI
            GUISetState(@SW_MINIMIZE, $g_h_Main_GUI)

            ; open the file name
            ShellExecute($s_FileName)

        Case $g_id_FilePreferences_mnu
            ; minimize the main GUI
            GUISetState(@SW_MINIMIZE, $g_h_Main_GUI)

            ShellExecute($g_s_INI)
    EndSwitch
EndFunc   ;==>MainMenu_DefaultEvents

Func MainMenu_DynamicEvents($i_ControlID)
    ; minimize the main GUI
    GUISetState(@SW_MINIMIZE, $g_h_Main_GUI)

    ; loop through the array and look for the clicked menu item
    For $i = 1 To $g_a_MenuEvents[0][0]
        If $i_ControlID = $g_a_MenuEvents[$i][0] Then
            ShellExecute($g_a_MenuEvents[$i][1])
            ExitLoop
        EndIf
    Next
EndFunc   ;==>MainMenu_DynamicEvents

Func MainMenu_SetItemIcon($h_Menu, $i_ControlID, $s_FilePath)
    ; set a default icon index (used if exe passsed)
    Local $i_IconIndex = 0

    ; create a bitmap from the file
    Local $h_Bitmap = CreateBitmapFromIcon($s_FilePath, $i_IconIndex)

    ; set the menu icon
    _GUICtrlMenu_SetItemBmp($h_Menu, $i_ControlID, $h_Bitmap, False)
EndFunc   ;==>MainMenu_SetItemIcon

Func StatusBar_SetText($s_Text)
    _GUICtrlStatusBar_SetText($g_h_Status_bar, $s_Text, 1)
EndFunc   ;==>StatusBar_SetText

#Region #### misc functions #######
; #FUNCTION# ====================================================================================================================
; Name ..........: CreateBitmapFromIcon
; Description ...: Create a bitmap image from an icon
; Syntax ........: CreateBitmapFromIcon($iBackground, $sIcon, $iIndex, $iWidth, $iHeight)
; Return values .: Handle to the bitmap
; Author ........: Yashied
; Modified ......: Benners 28/12/2015
; Remarks .......:
; Related .......:
; Link ..........: https://www.autoitscript.com/forum/topic/97365-how-to-convert-a-hicon-to-a-32-bit-hbitmap/?do=findComment&comment=700670
; ===============================================================================================================================
Func CreateBitmapFromIcon($sIcon, $iIndex = 0, $i_UseAssocIcon = 1, $iWidth = 16, $iHeight = 16)
    Local $hDC = _WinAPI_GetDC(0)
    Local $hBackDC = _WinAPI_CreateCompatibleDC($hDC)
    Local $hBitmap = _WinAPI_CreateSolidBitmap(0, _WinAPI_GetSysColor($COLOR_MENU), $iWidth, $iHeight)
    Local $hBackSv = _WinAPI_SelectObject($hBackDC, $hBitmap)
    Local $hIcon = 0

    ; check if specific icons are to be used (i.e from shell32.dll)
    If $i_UseAssocIcon Then
        $hIcon = ExtractAssociatedIcon($g_h_Main_GUI, $sIcon)
    Else
        $hIcon = _WinAPI_ShellExtractIcon($sIcon, $iIndex, $iWidth, $iHeight)
    EndIf

    If Not @error Then
        _WinAPI_DrawIconEx($hBackDC, 0, 0, $hIcon, $iWidth, $iHeight, 0, 0, $DI_NORMAL)
        _WinAPI_DestroyIcon($hIcon)
    EndIf

    _WinAPI_SelectObject($hBackDC, $hBackSv)
    _WinAPI_ReleaseDC(0, $hDC)
    _WinAPI_DeleteDC($hBackDC)

    Return $hBitmap
EndFunc   ;==>CreateBitmapFromIcon

; #FUNCTION# ====================================================================================================================
; Name ..........: ExtractAssociatedIcon
; Description ...: Extract the icon associated with a given file
; Syntax ........: ExtractAssociatedIcon($hWnd, $sFile)
; Parameters ....: $hWnd                - A handle value.
;                  $sFile               - A string value.
; Return values .: Handle to the icon
; Author ........: Rasim
; Modified ......:
; Remarks .......:
; Link ..........: https://www.autoitscript.com/forum/topic/87409-extractassociatedicon/?do=findComment&comment=627538
; ===============================================================================================================================
Func ExtractAssociatedIcon($hWnd, $sFile)
    Local $aRet = DllCall("shell32.dll", "hwnd", "ExtractAssociatedIcon", _
                                                 "hwnd", $hWnd, _
                                                 "str", $sFile, _
                                                 "short*", 0)

    Return $aRet[0]
EndFunc   ;==>ExtractAssociatedIcon

Func File_GetNameFromString($s_Path, $i_Extension = 1)
    If $i_Extension Then Return StringRegExpReplace($s_Path, "^.*\\", "")
    Return StringRegExpReplace($s_Path, "^.*\\|\..*$", "")
EndFunc   ;==>File_GetNameFromString

Func File_GetExtensionFromString($s_Path, $i_Period = 1)
    If $i_Period Then Return StringRegExpReplace($s_Path, "^.*\.", ".$1")
    Return StringRegExpReplace($s_Path, "^.*\.", "")
EndFunc   ;==>File_GetExtensionFromString

Func GetDPI()
    ;; Get the current DPI (dots per inch) setting, and the ratio between it and
    ;; approximately 96 DPI.
    ;;
    ;; Return a 1D array of dimension 3.  Indices zero is the dimension of the array
    ;; minus one.  Indices 1 = the current DPI (an integer).  Indices 2 is the ratio
    ;; should be applied to all GUI dimensions to make the GUI automatically adjust
    ;; to suit the various DPI settings.
    ;;
    ;; Author: Phillip123Adams
    ;; Posted: August, 17, 2005, originally developed 6/04/2004,
    ;; AutoIT 3.1.1.67 (but earlier v3.1.1 versions with DLLCall should work).
    ;;
    ;; Note: The dll calls are based upon code from the AutoIt3 forum from a post
    ;; by this-is-me on Nov 23 2004, 10:29 AM under topic "@Larry, Help!"  Thanks
    ;; to this-is-me and Larry.  Prior to that, I was obtaining the current DPI
    ;; from the Registry:
    ;;  $iDPI = RegRead("HKCU\Control Panel\Desktop\WindowMetrics", "AppliedDPI")
    ;;

    Local $iDPIRat, $Logpixelsy = 90, $hWnd = 0
    Local $hDC = DllCall("user32.dll", "long", "GetDC", "long", $hWnd)
    Local $aRet = DllCall("gdi32.dll", "long", "GetDeviceCaps", "long", $hDC[0], "long", $Logpixelsy)
    Local $iDPI = $aRet[0]

    $hDC = DllCall("user32.dll", "long", "ReleaseDC", "long", $hWnd, "long", $hDC)

    ;; Set a ratio for the GUI dimensions based upon the current DPI value.
    Select
        Case $iDPI = 0
            $iDPI = 96
            $iDPIRat = 94
        Case $iDPI < 84
            $iDPIRat = $iDPI / 105
        Case $iDPI < 121
            $iDPIRat = $iDPI / 96
        Case $iDPI < 145
            $iDPIRat = $iDPI / 95
        Case Else
            $iDPIRat = $iDPI / 94
    EndSelect

    ; Return the DPI Ration
    Return $iDPIRat
EndFunc   ;==>GetDPI

Func String_SearchForWords($sTest, $sSearch)
    Local $sPattern = '(?i)^(?=.*\b' & StringReplace($sSearch, '|', '\b)(?=.*\b') & '\b)'
    Return StringRegExp($sTest, $sPattern)
EndFunc   ;==>String_SearchForWords

Func Switch_GUI($h_NewGUI, $i_EventMode = 0, $i_DisableOldGUI = 0, $h_OldGUI = '', $i_DeleteOldGUI = 0) ; Change current GUI ($hwdGUI = GUI to change to, $iEventMode = Set GUIOnEventMode option 0/1, $iDisableMain = Disable the main OI GUI 0/1)
    Opt("GUIOnEventMode", $i_EventMode) ; Set on event mode.
    GUISwitch($h_NewGUI) ; Switch control to the specified GUI.
    GUISetState(@SW_ENABLE, $h_NewGUI)

    If $i_DisableOldGUI Then GUISetState(@SW_DISABLE, $h_OldGUI) ; Disable the main GUI.
    If $i_DeleteOldGUI Then GUIDelete($i_DeleteOldGUI)
EndFunc   ;==>Switch_GUI

Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $lParam
    Local $i_ControlID = _WinAPI_LoWord($wParam)

    Switch $i_ControlID
        Case $g_id_FileAdd_mnu
            MainMenu_AddItem()

        Case $g_id_FileOpen_mnu
            ; open a file select dialog
            Local $s_FileName = FileOpenDialog('Please Select a File', "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", 'All(*.*)', 0, '', $g_h_Main_GUI)
            If @error Then Return

            ; minimize the main GUI
            GUISetState(@SW_MINIMIZE, $g_h_Main_GUI)

            ; open the file name
            ShellExecute($s_FileName)

        Case $g_id_FilePreferences_mnu
            ShellExecute($g_s_INI);

        Case $g_id_FileExit_mnu
            Main_GUI_Close()

        Case $i_ControlID >= 2000
            MainMenu_DynamicEvents($i_ControlID)
    EndSwitch

    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_COMMAND
#EndRegion #### misc functions #######

 

QuickLaunch.ini

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

Yep, cheers KaFu, I managed to find the udf. The links were down in the original post which is why I went in another direction. I'll have a look through and see if I can make things fit.

Edited by benners

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