Modify ↓
Opened 11 months ago
Closed 10 months ago
#4041 closed Bug (Fixed)
_GUICtrlStatusBar_SetIcon
| Reported by: | Nine | Owned by: | J-Paul Mesnage |
|---|---|---|---|
| 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 by , 11 months ago
comment:2 by , 11 months ago
It is because the GUISetState(@SW_SHOW) appears before the SetIcon calls. But it is not a viable solution.
comment:3 by , 11 months ago
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 by , 11 months ago
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:6 by , 10 months ago
| Milestone: | → 3.3.17.0 |
|---|---|
| Owner: | set to |
| Resolution: | → Fixed |
| Status: | new → closed |
Fixed by revision [13105] in version: 3.3.17.0
Note:
See TracTickets
for help on using tickets.

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