Opened 7 months ago
Closed 7 months ago
#4041 closed Bug (Fixed)
_GUICtrlStatusBar_SetIcon
| Reported by: | Nine | Owned by: | Jpm |
|---|---|---|---|
| Milestone: | 3.3.17.0 | Component: | AutoIt |
| Version: | 3.3.16.1 | Severity: | None |
| Keywords: | Cc: |
Description
Destroying the icon at the end of the function prevents the icon from being shown.
#include <GUIConstants.au3>
#include <GuiStatusBar.au3>
Example()
Func Example()
Local $aPartRightSide[3] = [100, 100, -1]
Local $hGUI = GUICreate("Test", 400, 300)
Local $hStatusBar = _GUICtrlStatusBar_Create($hGUI, $aPartRightSide)
_GUICtrlStatusBar_SetText($hStatusBar, "Part 1")
_GUICtrlStatusBar_SetText($hStatusBar, "Part 2", 1)
_GUICtrlStatusBar_SetIcon($hStatusBar, 0, 23, "shell32.dll") ; not working
_GUICtrlStatusBar_SetIconEx($hStatusBar, 1, 23, "shell32.dll") ; working
GUISetState(@SW_SHOW)
Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE
EndFunc ;==>Example
Func _GUICtrlStatusBar_SetIconEx($hWnd, $iPart, $hIcon = -1, $sIconFile = "")
If $hIcon = -1 Then Return _SendMessage($hWnd, $SB_SETICON, $iPart, $hIcon, 0, "wparam", "handle") <> 0 ; Remove Icon
If StringLen($sIconFile) <= 0 Then Return _SendMessage($hWnd, $SB_SETICON, $iPart, $hIcon) <> 0 ; set icon from icon handle
; set icon from file
Local $tIcon = DllStructCreate("handle")
Local $vResult = DllCall("shell32.dll", "uint", "ExtractIconExW", "wstr", $sIconFile, "int", $hIcon, "ptr", 0, "struct*", $tIcon, "uint", 1)
If @error Then Return SetError(@error, @extended, False)
$vResult = $vResult[0]
If $vResult > 0 Then $vResult = _SendMessage($hWnd, $SB_SETICON, $iPart, DllStructGetData($tIcon, 1), 0, "wparam", "handle")
;DllCall("user32.dll", "bool", "DestroyIcon", "handle", DllStructGetData($tIcon, 1)) ; this needs to be removed
Return $vResult
EndFunc ;==>_GUICtrlStatusBar_SetIconEx
Attachments (0)
Change History (6)
comment:1 Changed 7 months ago by Jpm
comment:2 Changed 7 months ago by anonymous
It is because the GUISetState(@SW_SHOW) appears before the SetIcon calls. But it is not a viable solution.
comment:3 Changed 7 months ago by Nine
If you minimize or hide the GUI afterward, the icons disappear. You simply cannot destroy the icons until you delete the GUI. One solution would be to return the hIcon, so programmer can destroy it at the end of their script
comment:4 Changed 7 months ago by Nine
Here my take on it :
; #AutoIt3Wrapper_UseX64=y ; works both x86 and x64
#include <GUIConstants.au3>
#include <GuiStatusBar.au3>
#include <WinAPIIcons.au3>
Example()
Func Example()
Local $aPartRightSide[3] = [100, 200, -1]
Local $hGUI = GUICreate("Test", 400, 300)
Local $hStatusBar = _GUICtrlStatusBar_Create($hGUI)
_GUICtrlStatusBar_SetParts($hStatusBar, $aPartRightSide)
_GUICtrlStatusBar_SetText($hStatusBar, "Part 1")
_GUICtrlStatusBar_SetText($hStatusBar, "Part 2", 1)
GUISetState(@SW_SHOW)
Local $hIcon = _GUICtrlStatusBar_SetIconEx($hStatusBar, 1, 23, "shell32.dll") ; working
If Not $hIcon Then Exit MsgBox($MB_OK, "Unable to set icon", "@error = " & @error)
GUISetState()
Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE
ConsoleWrite(_WinAPI_DestroyIcon($hIcon) & @CRLF)
EndFunc ;==>Example
; Not changing too much the original code, but solving all issues
; return false if any error
; return true if success or hIcon when $sIconFile is specified
; return @error for additional information when failure with $sIconFile specified
Func _GUICtrlStatusBar_SetIconEx($hWnd, $iPart, $hIcon = -1, $sIconFile = "") ; by Nine
If $hIcon = -1 Then Return _SendMessage($hWnd, $SB_SETICON, $iPart, $hIcon, 0, "wparam", "handle") <> 0 ; Remove Icon
If StringLen($sIconFile) <= 0 Then Return _SendMessage($hWnd, $SB_SETICON, $iPart, $hIcon) <> 0 ; set icon from icon handle
Local $tIcon = DllStructCreate("handle")
Local $vResult = DllCall("shell32.dll", "uint", "ExtractIconExW", "wstr", $sIconFile, "int", $hIcon, "ptr", 0, "struct*", $tIcon, "uint", 1)
If @error Then Return SetError(@error, 0, False)
If Hex($vResult[0], 8) = "FFFFFFFF" Then ; UINT_MAX error (based on MSDN)
$vResult = _WinAPI_GetLastError()
Return SetError(10 + $vResult, 0, False) ; to differentiate from the @error of DllCall
EndIf
If Not $vResult[0] Then Return SetError(-1, 0, False) ; no icon returned
$vResult = _SendMessage($hWnd, $SB_SETICON, $iPart, DllStructGetData($tIcon, 1), 0, "wparam", "handle")
If Not $vResult Then Return SetError(-2, 0, False)
Return DllStructGetData($tIcon, 1)
EndFunc ;==>_GUICtrlStatusBar_SetIconEx
comment:5 Changed 7 months ago by Nine
Forgot to erase first GuiSetState
comment:6 Changed 7 months ago by Jpm
- Milestone set to 3.3.17.0
- Owner set to Jpm
- Resolution set to Fixed
- Status changed from new to closed
Fixed by revision [13105] in version: 3.3.17.0
Guidelines for posting comments:
- You cannot re-open a ticket but you may still leave a comment if you have additional information to add.
- In-depth discussions should take place on the forum.
For more information see the full version of the ticket guidelines here.

In fact your solution will create an non delete icon for ever
I don't really know but the second example of _GUICtrlStatuBar_GetIcon() is working
I will try to find out why