Jump to content

How to load an image from ico file ?


Recommended Posts

What do you mean by "load"?

Are you trying to display the icon file in a gui? Are you trying to load the image into memory?

Here's a way to load an image into a GDI+ Bitmap object and I commented out the line that would let you convert the GDI+Bitmap to a hBitmap. There are posts all over the forum for converting bitmaps to a binary string.

#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <GUIConstants.au3>

Example()

Func Example()
    _GDIPlus_Startup()
    ; Create a GDI+ Bitmap
    Local $Bitmap = _GDIPlus_ImageLoadFromFile("your icon file.ico")
    ; Create a windows HBitmap object, need to use _WinApi_DeleteObject($hBitmap) when you're done with it
    ;Local $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($Bitmap)
    Local $iWidth = _GDIPlus_ImageGetWidth($Bitmap) + 20
    Local $iHeight = _GDIPlus_ImageGetHeight($Bitmap) + 20
    Local $hGUI = GUICreate("", $iWidth, $iHeight)
    GUISetState(@SW_SHOW, $hGUI)
    Local $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    
    _GDIPlus_GraphicsDrawImage($hGraphic, $Bitmap, 10, 10)

    While (True)
        Switch (GUIGetMsg())
            Case $GUI_EVENT_CLOSE
                ExitLoop
        EndSwitch
    WEnd

    _GDIPlus_ImageDispose($Bitmap)

    _GDIPlus_Shutdown()
EndFunc

 

Edited by InunoTaishou
Link to comment
Share on other sites

Are you sure you have a valid Iconfile? Here's a example:

#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>

Example()

Func Example()
    GUICreate("My GUI") ; will create a dialog box that when displayed is centered

    GUICtrlCreateButton("my picture button", 10, 20, 40, 40, $BS_ICON)
    GUICtrlSetImage(-1, "shell32.dll", 22)

    GUISetState(@SW_SHOW)

    ; Loop until the user exits.
    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ExitLoop

        EndSwitch
    WEnd
EndFunc   ;==>Example

in line 10: just change name Shell32.dll to yours with complete path to file and try numbers 0..9 instead of 22.

Link to comment
Share on other sites

If you have multiple icons in an icon file then you would need to define the area to extract the icon. (I'm assuming that you're working with a .ico file). If you wanted to go down this route then you can use GDI+ to extract the icon from the file and then using GUICtrlSendMessage to set the pic control (Check out this topic to see how to do that.

Link to comment
Share on other sites

I make a small .ico file contains 6 icons inside and write here a little example to test. How can load or add all icon as i want?

#include <GUIConstantsEx.au3>
#include <ButtonConstants.au3>
#include <Constants.au3>
#include <WinAPI.au3>

Example()

Func Example()
 GUICreate("", 400, 380, -1, -1)
 GUICtrlCreateButton("icon image", 10, 20, 40, 40, $BS_ICON)
 GUICtrlSetImage(-1, "test.ico", -1)
 GUICtrlCreateButton("icon image", 50, 20, 40, 40, $BS_ICON)
 GUICtrlSetImage(-1, "test.ico", "-2")
 GUICtrlCreateButton("icon image", 90, 20, 40, 40, $BS_ICON)
 GUICtrlSetImage(-1, "test.ico", 3)

 GUISetState()

 While 1
  $msg = GUIGetMsg()
  If $msg = $GUI_EVENT_CLOSE Then ExitLoop
 WEnd
EndFunc   ;==>Example

 

test.ico

Link to comment
Share on other sites

I don't know what it is about your icon file but it will not load the images properly. I think it might not have been saved properly or created properly. The only image it will load correctly is the 6, 1-5 fail completely. Here's the code I used to check this. (Please note, the $BS_ICON or $BS_BITMAP don't matter, as long as one is used. Once it's going to turn into a bitmap either way once it's extracted.)

#include <GUIConstantsEx.au3>
#include <GuiButton.au3>

Local $hGUI = GUICreate("Image List", 116, 84)
Local $btnTest[6]

For $i = 0 To 2
    $btnTest[$i] = GUICtrlCreateButton("", 10 + ($i * 32), 10, 32, 32, $BS_BITMAP)
    $btnTest[$i + 3] = GUICtrlCreateButton("", 10 + ($i * 32), 42, 32, 32, $BS_BITMAP)
    ConsoleWrite("Set image for Button " & $i + 1 & " returned: " & _GUICtrlButton_SetImage($btnTest[$i], @ScriptDir & "\test.ico", $i, True) & " | ")
    ConsoleWrite("Set image for Button " & $i + 1 & " returned: " & _GUICtrlButton_SetImage($btnTest[$i + 3], @ScriptDir & "\test.ico", $i + 3, True) & @LF)
Next

GUISetState(@SW_SHOW)

While (True)
    Switch (GUIGetMsg())
        Case $GUI_EVENT_CLOSe
            GUIDelete($hGUI)
            Exit 0
    EndSwitch
WEnd

I also tried to open up your icon file, it will load correctly in photoshop and let me select which image to load. I tried using IcoFX too but it only recognized 1 image, the number 1.

Maybe I was doing it wrong, who knows. I tried using _GUIImageList as well but that failed. Try using a dll with your images or just create one png file with all of your images and use GDI+ to extract the image you want.

Link to comment
Share on other sites

As Microsoft guide and I learned, the normal image viewer and normal icon software can only view 1 image in multiple icons file, and just only the icon software professional can view all images in multiple icons file.

But the problem still is the same when i make a resource dll. Here my .dll, anybody can explain why?

#include <GUIConstantsEx.au3>
#include <ButtonConstants.au3>
#include <Constants.au3>
#include <WinAPI.au3>

Example()

Func Example()
 GUICreate("", 400, 380, -1, -1)
 GUICtrlCreateButton("icon", 10, 20, 40, 40, $BS_ICON)
 GUICtrlSetImage(-1, "test.dll", 1)
 GUICtrlCreateButton("icon", 50, 20, 40, 40, $BS_ICON)
 GUICtrlSetImage(-1, "test.dll", 2)
 GUICtrlCreateButton("icon", 90, 20, 40, 40, $BS_ICON)
 GUICtrlSetImage(-1, "test.dll", -2)
 GUICtrlCreateButton("icon", 10, 80, 40, 40, $BS_ICON)
 GUICtrlSetImage(-1, "test.dll", "2")
 GUICtrlCreateButton("icon", 50, 80, 40, 40, $BS_ICON)
 GUICtrlSetImage(-1, "test.dll", "-2")
 GUICtrlCreateButton("icon", 90, 80, 40, 40, $BS_ICON)
 GUICtrlSetImage(-1, "test.dll", -1)

 GUISetState()

EndFunc   ;==>Example

 While 1
  $msg = GUIGetMsg()
  If $msg = $GUI_EVENT_CLOSE Then ExitLoop
 WEnd

 

test.dll

Link to comment
Share on other sites

Here a hack to display all icons from the ICO file.

;~ #include <Array.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <WinAPIFiles.au3>
#include <WinAPIRes.au3>


;~ Global Const $sPath = "c:\Program Files (x86)\AutoIt3\Aut2Exe\Icons\AutoIt_Old1.ico"
Global $sPath = FileOpenDialog("Select an ICO file", "", "Icon (*.ico)")
If @error Then Exit

_GDIPlus_Startup()
Global $aRes = _EnumIconFile($sPath), $iSumW, $iMaxH, $i, $iDist = 16
Global $aIcons[$aRes[0][0]]

For $i = 1 To $aRes[0][0]
    $iSumW += $aRes[$i][0]
    $iMaxH = $aRes[$i][1] > $iMaxH ? $aRes[$i][1] : $iMaxH
    Switch $aRes[$i][3]
        Case 0
            Switch $aRes[$i][2]
                Case 0 To 8
                    $aIcons[$i - 1] = _GDIPlus_BitmapCreateFromHICON($aRes[$i][4])
                Case Else
                    $aIcons[$i - 1] = _GDIPlus_BitmapCreateFromHICON32($aRes[$i][4])
            EndSwitch
            _WinAPI_DestroyIcon($aRes[$i][4])
        Case 1
            $aIcons[$i - 1] = $aRes[$i][4]
    EndSwitch
Next


Global $hGUI = GUICreate("Test", $iSumW + ($aRes[0][0]) * $iDist, $iMaxH + $iDist)
GUISetBkColor(0xFFFFFF)
GUISetState()
Global $hGfx = _GDIPlus_GraphicsCreateFromHWND($hGUI)
$iSumW = 0
For $i = 0 To UBound($aIcons) - 1
    $aDim = _GDIPlus_ImageGetDimension($aIcons[$i])
    If @error Then ContinueLoop
    _GDIPlus_GraphicsDrawImageRect($hGfx, $aIcons[$i], $iSumW, 0, $aDim[0], $aDim[1])
    $iSumW += $aDim[0] + $iDist
Next

Do
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            For $i = 0 To UBound($aIcons) - 1
                _GDIPlus_ImageDispose($aIcons[$i])
            Next
            _GDIPlus_GraphicsDispose($hGfx)
            _GDIPlus_Shutdown()
            GUIDelete()
            Exit
    EndSwitch
Until False


; #FUNCTION# ====================================================================================================================
; Name...........: _EnumIconFile
; Description....: Enumerates an icons from the specified .ico file.
; Syntax.........: _EnumIconFile ( $sFile )
; Parameters.....: $sFile  - The path to the .ico file whose icons are to be enumerated.
; Return values..: Success - The 2D array containing the following information:
;
;                            [0][0] - Number of rows in array (n)
;                            [0][i] - Unused
;                            [n][0] - The width of the icon, in pixels.
;                            [n][1] - The heigth of the icon, in pixels.
;                            [n][2] - The color depth of the icon, in bits-per-pixel.
;                            [n][3] - 1 (TRUE) if the icon has a PNG compression (Windows Vista+), or 0 (FALSE) otherwise.
;                            [n][4] - Handle -> either a bitmap will be created if [n][3] = 1 or an Icon
;
;                  Failure - 0 and sets the @error flag to non-zero.
; Author.........: Yashied
; Modified.......: UEZ
; Remarks........: Do not forget to clean-up resources in [n][4] when done
; Related........:
; Link...........:
; Example........:
; ===============================================================================================================================
Func _EnumIconFile($sFile)
    Local $hFile, $tEntry, $tHeader, $tData, $pData, $pIcon, $Bytes, $Count, $Offset, $Enum = 0

    $hFile = _WinAPI_CreateFileEx($sFile, 3, 0x80000000, 0x03)
    If @Error Then
        Return SetError(1, 0, 0)
    EndIf
    Do
        $Bytes = _WinAPI_GetFileSizeEx($hFile)
        If Not $Bytes Then
            ExitLoop
        EndIf
        $tData = DllStructCreate('byte[' & $Bytes & ']')
        $pData = DllStructGetPtr($tData)
        If Not _WinAPI_ReadFile($hFile, $pData, $Bytes, $Bytes) Then
            ExitLoop
        EndIf
        $tHeader = DllStructCreate('ushort;ushort;ushort', $pData)
        $Count = DllStructGetData($tHeader, 3)
        If Not $Count Then
            ExitLoop
        EndIf
        Local $hBitmap
        Dim $Enum[$Count + 1][5] = [[$Count]]
        For $i = 1 To $Count
            $tEntry = DllStructCreate('byte;byte;byte;byte;ushort;ushort;long;long', $pData + 6 + 16 * ($i - 1))
            $Offset = DllStructGetData($tEntry, 8)
            $pIcon = $pData + $Offset
            $Enum[$i][2] = DllStructGetData($tEntry, 6)
            If DllStructGetData(DllStructCreate('byte[8]', $pIcon), 1) = Binary('0x89504E470D0A1A0A') Then
                ; PNG => Retrieve IHDR chunk data (always first chunk, offset = 8)
                $tHeader = DllStructCreate('dword;dword;byte;byte;byte;byte;byte', $pIcon + 16)
                $Enum[$i][0] = _WinAPI_SwapDWord(DllStructGetData($tHeader, 1))
                $Enum[$i][1] = _WinAPI_SwapDWord(DllStructGetData($tHeader, 2))
                $Enum[$i][3] = 1
                $Enum[$i][4] = _GDIPlus_BitmapCreateFromMemory(Binary(DllStructGetData(DllStructCreate("byte[" & DllStructGetData($tEntry, 7) & "]", $pIcon), 1)))
            Else
                ; ICO => Retrieve BITMAPINFOHEADER structure
                $tHeader = DllStructCreate($tagBITMAPINFOHEADER, $pIcon)
                $Enum[$i][0] = DllStructGetData($tHeader, 2)
                $Enum[$i][1] = DllStructGetData($tHeader, 3) / 2
                $Enum[$i][3] = 0
                $Enum[$i][4] = _WinAPI_CreateIconFromResourceEx($pIcon, DllStructGetData($tEntry, 7), True, $Enum[$i][0], $Enum[$i][1])
            EndIf
        Next
    Until 1
    _WinAPI_CloseHandle($hFile)
    If Not IsArray($Enum) Then
        Return SetError(1, 0, 0)
    EndIf
    Return $Enum
EndFunc   ;==>_EnumIconFile

Not fully tested!

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

I want to ask 1 more question. Can we add a big icon with the Function "GUICtrlSetImage" or "_GUIImageList_AddIcon" ? Because when i use these function it only can add a max 32x32 px icon, the bigger icon will be auto resize to smaller. So that when display the bigger of 32px icon, the image is broken. Any solution for it?

Link to comment
Share on other sites

I just checked your .ICO and .DLL files and I really got no idea how you did manage to add the same resolution icons into a same ico file...

Use St. Google and search for IMAGE to ICO online converters, theres plenty and free out there.

One .ico file is made of 1-n images with specific resolutions and bith depth, none of the resolutions "must" be duplicated.

What I think you may want to achieve is to create an icon library (.icl), which is a container for several .ico files.

In my experience I use negative numbers for the indexed icons, ie. -1, -2, -3 and so. althought in rare cases like the code below, the 1st icon worked with a positive index number.

Download the .icl file and test this code:

#include <GUIConstantsEx.au3>
#include <ButtonConstants.au3>
#include <Constants.au3>
#include <WinAPI.au3>

Example()

Func Example()
 GUICreate("", 400, 380, -1, -1)
 GUICtrlCreateButton("icon 1", 10, 20, 40, 40, $BS_ICON)
 GUICtrlSetImage(-1, "1-6.icl", 1)
 GUICtrlCreateButton("icon 2", 50, 20, 40, 40, $BS_ICON)
 GUICtrlSetImage(-1, "1-6.icl", -2)
 GUICtrlCreateButton("icon 3", 90, 20, 40, 40, $BS_ICON)
 GUICtrlSetImage(-1, "1-6.icl", -3)
 GUICtrlCreateButton("icon 4", 10, 80, 40, 40, $BS_ICON)
 GUICtrlSetImage(-1, "1-6.icl", -4)
 GUICtrlCreateButton("icon 5", 50, 80, 40, 40, $BS_ICON)
 GUICtrlSetImage(-1, "1-6.icl", -5)
 GUICtrlCreateButton("icon 6", 90, 80, 40, 40, $BS_ICON)
 GUICtrlSetImage(-1, "1-6.icl", -6)

 GUISetState()

EndFunc   ;==>Example

 While 1
  $msg = GUIGetMsg()
  If $msg = $GUI_EVENT_CLOSE Then ExitLoop
 WEnd

 

1-6.icl

Link to comment
Share on other sites

I didn't see where you stated how you created your ico file (i.e. what process or program)?

An ico file generally only has one icon.

To store multiple icons together, you generally use an icon library file (.icl). Or they can be stored in DLL or EXE etc files.

To be true icons in a file, they generally have to fit the criteria of appropriate bit depth and sizing (16x16, 32x32, 48x48).

You should be able to use negative numbers, as has been previously suggested.

Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.

Spoiler

What is the Secret Key? Life is like a Donut

If I put effort into communication, I expect you to read properly & fully, or just not comment.
Ignoring those who try to divert conversation with irrelevancies.
If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it.
I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage)

userbar.png

Link to comment
Share on other sites

Thanks. The number index work correctly with .icl file. But still remain the problem with display size. although the icon size is bigger than 32x32, it seem only display max 32x32 icon size. There are just only 2 choices 16x16, 32x32 to display when i try to display icon on button or toolbar. Are there any way to display bigger icon?

Here my little example to test. My .icl file have icon 1-6 in 48x48 and 7-9 in 96x96, but all icons still display 32x32.

#include <GUIConstantsEx.au3>
#include <ButtonConstants.au3>
#include <Constants.au3>
#include <WinAPI.au3>

Example()

Func Example()
 GUICreate("", 400, 380, -1, -1)
 GUICtrlCreateButton("icon", 10, 20, 50, 50, $BS_ICON)
 GUICtrlSetImage(-1, "Test2.icl", 1)
 GUICtrlCreateButton("icon", 60, 20, 50, 50, $BS_ICON)
 GUICtrlSetImage(-1, "Test2.icl", 2)
 GUICtrlCreateButton("icon", 110, 20, 50, 50, $BS_ICON)
 GUICtrlSetImage(-1, "Test2.icl", 3)
 GUICtrlCreateButton("icon", 10, 80, 50, 50, $BS_ICON)
 GUICtrlSetImage(-1, "Test2.icl", 4)
 GUICtrlCreateButton("icon", 60, 80, 50, 50, $BS_ICON)
 GUICtrlSetImage(-1, "Test2.icl", 5)
 GUICtrlCreateButton("icon", 110, 80, 50, 50, $BS_ICON)
 GUICtrlSetImage(-1, "Test2.icl", 6,1)
 GUICtrlCreateButton("icon", 10, 150, 100, 100, $BS_ICON)
 GUICtrlSetImage(-1, "Test2.icl", 7)
 GUICtrlCreateButton("icon", 110, 150, 100, 100, $BS_ICON)
 GUICtrlSetImage(-1, "Test2.icl", 8)
 GUICtrlCreateButton("icon", 210, 150, 100, 100, $BS_ICON)
 GUICtrlSetImage(-1, "Test2.icl", 9,1)

 GUISetState()

EndFunc   ;==>Example

 While 1
  $msg = GUIGetMsg()
  If $msg = $GUI_EVENT_CLOSE Then ExitLoop
 WEnd

 

Test2.icl

Edited by hiepkhachsg
Link to comment
Share on other sites

Have a look at your Microsoft Windows' settings.

I know I can display 48x48 on my Win 7 desktop, but in folders the current maximum is 32x32. I imagine that is either a permanent limitation or a Windows' setting.

You can change many Windows' settings from the Display Properties menus.

Never come across 96x96.

Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.

Spoiler

What is the Secret Key? Life is like a Donut

If I put effort into communication, I expect you to read properly & fully, or just not comment.
Ignoring those who try to divert conversation with irrelevancies.
If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it.
I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage)

userbar.png

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...