Jump to content

GUICtrlSetImage from Resource Icon


Go to solution Solved by Nine,

Recommended Posts

I have an icon file with only one image in it, sized 48x48. There are no other image sizes within the file. The icon is named 48x48.ico and is attached to this message.

I have code in the script to load the icon to a Button control either from the .ico file if the script is running uncompiled, or from the stored resource in the .exe if running compiled.

When the icon is loaded from the .ico file, it is displayed on the button correctly sized 48x48. But when the icon is loaded from the resource, it gets scaled down to 32x32. It's not the fact that it's compiled that's causing this, because if I adjust the code so that the compiled version loads the image directly from the external .ico instead of from a resource, the icon is displayed on the button correctly. It's only when it's loaded from the stored resource that it gets scaled down to 32x32. Why?

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Res_Language=1033
#AutoIt3Wrapper_Res_Icon_Add=48x48.ico, 201
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

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

Example()

Func Example()
    
    Local $hGUI = GUICreate("Example", 300, 200)

    ; Create label control.
    Local $idLabel = GUICtrlCreateLabel("@Compiled = " & @Compiled, 10, 10)

    ; Create button controls.
    Local $idButton_Icon = GUICtrlCreateButton("", 117, 67, 66, 66, $BS_ICON)
    If @Compiled Then
        GUICtrlSetImage($idButton_Icon, @AutoItExe, 201)
    Else
        GUICtrlSetImage($idButton_Icon, "48x48.ico")
    EndIf
    Local $idButton_Close = GUICtrlCreateButton("Close", 210, 170, 85, 25)

    ; Display the GUI.
    GUISetState(@SW_SHOW, $hGUI)

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

    ; Delete the previous GUI and all controls.
    GUIDelete($hGUI)

EndFunc   ;==>Example

Screenshots of the results:

image.png.2e5849018974a0c21e0e0b9d982ef615.png         image.png.636f9b78dd8680f91d6144920f44f61c.png

image.png.13860d4a1bd73d6f1d74e908156ace39.png

48x48.ico

Edited by TimRude
Add more info and screen shot from Resource Hacker
Link to post
Share on other sites

@pixelsearch I'm glad I was too busy to post this to the bug tracker until after you pointed out the futility of doing so. Thanks!

Looks like the recommended workaround in the thread you linked was to use the ResourcesEx UDF.

That UDF was suggested by @Melba23 in this post where I asked how to get a resource pic displayed as the background for a listview. @Nine suggested an easier way that I intially went with, but now it looks like I need to see if ResourcesEx can solve this issue too.

Link to post
Share on other sites
  • Solution

Sorry that I suggested a futility, since I was not aware of this issue.  On the other hand, as @pixelsearch pointed out nicely, there is a solution.  Of course (again), you can use the large UDF, but I was curious how to handle it simply and easily :

#AutoIt3Wrapper_Res_File_Add=48x48.ico, RT_ICON, ICON_1

#include <GUIConstants.au3>
#include <WinAPISys.au3>

Example()

Func Example()
  Local $hGUI = GUICreate("Example", 300, 200)
  Local $idLabel = GUICtrlCreateLabel("@Compiled = " & @Compiled, 10, 10)

  Local $idButton_Icon = GUICtrlCreateButton("", 117, 67, 66, 66, $BS_ICON)
  If @Compiled Then
    Local $hInstance = _WinAPI_GetModuleHandle(Null)
    Local $hResource = _WinAPI_LoadImage($hInstance, "ICON_1", $IMAGE_ICON, 0, 0, 0)
    GUICtrlSendMsg($idButton_Icon, $BM_SETIMAGE, $IMAGE_ICON, $hResource)
  Else
    GUICtrlSetImage($idButton_Icon, "48x48.ico")
  EndIf
  Local $idButton_Close = GUICtrlCreateButton("Close", 210, 170, 85, 25)

  GUISetState()

  While 1
    Switch GUIGetMsg()
      Case $GUI_EVENT_CLOSE, $idButton_Close
        ExitLoop
    EndSwitch
  WEnd
EndFunc   ;==>Example

 

Link to post
Share on other sites
40 minutes ago, Nine said:

I was curious how to handle it simply and easily

Another excellent save! I'm always happier to add a few lines of code rather than add a whole UDF. No disrespect to the ResourcesEx UDF. At some point I may need the extra stuff it can do. But for now as long as these 'simple and easy' workarounds are available, I'm happy to use them.

Thanks!

Link to post
Share on other sites

@Nine lines of code remembered me that about 3 years ago, I had some nice couple of emails with @Zedna where I thanked him for his useful script resources.au3 (that he updated in 2015) found in this post.

At the time, I used successfully a part of his script (the bmp part) for pics controls & buttons controls, ending in a script based on the following (just forget the non-english personal comments) :

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
...
#AutoIt3Wrapper_Res_File_Add=D:\Temp\resources\arrow_up 70-84.bmp, rt_bitmap, ARROW_UP
#AutoIt3Wrapper_Res_File_Add=D:\Temp\resources\Ok 52-51.bmp, rt_bitmap, OK
...
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

...
If Not @Compiled Then
    ...
Else    
    $hBmp = _ResourceGet("ARROW_UP") ; ARROW_UP comme dans la directive en haut #AutoIt3Wrapper_Res_File_Add
    _SetBitmapToCtrl($idArrow, $hBmp, $STM_SETIMAGE) ; $STM_SETIMAGE pour image vers controle statique (comme cette image de flèche)

    $hBmp = _ResourceGet("OK") ; OK comme dans la directive en haut #AutoIt3Wrapper_Res_File_Add
    _SetBitmapToCtrl($idButton_OK, $hBmp, $BM_SETIMAGE) ; $BM_SETIMAGE pour image vers controle bouton
EndIf
...

; #FUNCTION# ====================================================================================================================
; Author ........: Zedna (dans son script resources.au3 2ème version de 2015 (pour nouvelles versions d'AutoIt)
; Modified.......: pixelsearch : allégé pour ne garder QUE la partie .bmp (ne pas utiliser si autre extension !)
; ===============================================================================================================================
Func _ResourceGet($ResName)
    Local $hInstance, $hBitmap

    $hInstance = _WinAPI_GetModuleHandle(Null)
    ; If $hInstance = 0 Then Return SetError(1, 0, 0)

    $hBitmap = _WinAPI_LoadImage($hInstance, $ResName, 0, 0, 0, 0) ; 3eme param = $IMAGE_BITMAP = 0
    ; If @error Then Return SetError(2, 0, 0)
    Return $hBitmap ; returns handle to Bitmap
EndFunc

; #FUNCTION# ====================================================================================================================
; Author ........: Zedna (dans son script resources.au3 2ème version de 2015 (pour nouvelles versions d'AutoIt)
; Modified.......: pixelsearch : allégé et rajouté 3ème paramètre (constante pour controle Pic OU Bouton) . Nb image .bmp seult
; ===============================================================================================================================
Func _SetBitmapToCtrl($CtrlId, $hBitmap, $iCtrl_SETIMAGE)
    Local $hWnd

    $hWnd = GUICtrlGetHandle($CtrlId)
    ; If $hWnd = 0 Then Return SetError(1, 0, 0)

    ; $hPrev  = _SendMessage($hWnd, $iCtrl_SETIMAGE, 0, $hBitmap) ; 3eme param = $IMAGE_BITMAP = 0
    _SendMessage($hWnd, $iCtrl_SETIMAGE, 0, $hBitmap) ; 3eme param = $IMAGE_BITMAP = 0
    ; If @error Then Return SetError(2, 0, 0)

    ; If $hPrev Then _WinAPI_DeleteObject($hPrev) ; Non ! car $hprev sera toujours = 0 dans ce script où chaque controle
                                                  ; (picture ou bouton) n'est attaché qu'à une seule image du début à la fin.
                                                  ; De toute façon, tout dépend de ce qu'on veut faire avec les pics.
                                                  ; Explications complémentaires dans boite aux lettres AutoIt (avec Zedna)
EndFunc

Hope this could help some users... and Zedna, thanks again :thumbsup:

Link to post
Share on other sites

@Nine could it be interesting to combine the 2 functions above (_ResourceGet and _SetBitmapToCtrl) into a single function, then call this function with a 1-liner code per control, with 4 parameters : 
* control id
* resource name
* message [BM_SETIMAGE | STM_SETIMAGE]
* type of image [IMAGE_BITMAP | IMAGE_ICON]

This could be useful for AutoIt users and would result in only 1 line in main (@compiled part) to associate each control (button or static control) with its own image/icon, what do you think ?

Link to post
Share on other sites

I rolled the method from @Nine plus the compiled/uncompiled test into one function. It's a custom function for the specific app but it looks like this:

Global Const $resIcon_Browse = 201
Global Const $resIcon_Screen2On = 202
Global Const $resIcon_Screen2Off = 203
Global Const $resIcon_SlideShow = 204
Global Const $resIcon_Help = 205
Global Const $resIcon_OneScreen = 206

Func MyGUICtrlSetImage($idControl, $iIconNum) ; wrapper for GUICtrlSetImage to work in script or compiled exe
    If @Compiled Then
        Local $hInstance = _WinAPI_GetModuleHandle(Null)
        Local $hResource = _WinAPI_LoadImage($hInstance, $iIconNum, $IMAGE_ICON, 0, 0, 0)
        GUICtrlSendMsg($idControl, $BM_SETIMAGE, $IMAGE_ICON, $hResource)
        ;GUICtrlSetImage($idControl, @AutoItExe, $iIconNum)
    Else
        Local $sIconFile = ""
        Switch $iIconNum
            Case $resIcon_Browse
                $sIconFile = "BrowseFolders.ico"
            Case $resIcon_Screen2On
                $sIconFile = "Screen2On.ico"
            Case $resIcon_Screen2Off
                $sIconFile = "Screen2Off.ico"
            Case $resIcon_SlideShow
                $sIconFile = "SlideShow.ico"
            Case $resIcon_Help
                $sIconFile = "QuestionMark.ico"
            Case $resIcon_OneScreen
                $sIconFile = "OnlyOneScreen.ico"
        EndSwitch
        GUICtrlSetImage($idControl, $sIconFile)
    EndIf
EndFunc   ;==>MyGUICtrlSetImage

Then to use it to assign an icon to a button, I use this:

Local $idBtn_Browse = GUICtrlCreateButton("", 117, 67, 66, 66, $BS_ICON)
MyGUICtrlSetImage($idBtn_Browse, $resIcon_Browse)

 

Edited by TimRude
typo
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
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...