Modify

Opened 3 days ago

Last modified 38 hours ago

#4041 new Bug

_GUICtrlStatusBar_SetIcon

Reported by: Nine Owned by:
Milestone: 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

Change History (5)

comment:1 Changed 41 hours ago by Jpm

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

comment:2 Changed 40 hours 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 40 hours 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 39 hours 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 38 hours ago by Nine

Forgot to erase first GuiSetState

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.

Add Comment

Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.