Jump to content

Icons.au3


Recommended Posts

I saw a few yahtzee games on the forum, but I didn't see any that looked very good at all, so I decided to update them. It is looking good so far, but I am having a bit of trouble with Icons.au3. I narrowed down the problem lines to these lines in _Icons_SetImage:

$hPrev = _SendMessage($hWnd, $__STM_SETIMAGE, $iType, 0)
    If $hPrev Then
        If $iType = $IMAGE_BITMAP Then
            _WinAPI_DeleteObject($hPrev)
        Else
            _WinAPI_DestroyIcon($hPrev)
        EndIf
    EndIf

If I comment these lines out, I can update my GuiCtrlCreatePics with _SetImage. If I leave these lines in, the image that I am trying to update to doesn't appear and the previous image disappears. I think taking out these lines would cause a memory leak. I don't know if I made this very clear.

Here is my script. Just take a look at it. You will have to comment out the lines that include pictures. There are too many to include here. The problem lines in my script are 58 and 60 unless I comment out the lines specified above.

New AutoIt v3 Script.au3

Edited by dantay9
Link to comment
Share on other sites

I think I fixed it. It works for me. Can anyone confirm this? Here is the replacement function:

Func _SetImage($hWnd, $sImage)

    $hWnd = _Icons_CheckHandle($hWnd)
    If $hWnd = 0 Then Return SetError(1, 0, 0)

    Local $Ret, $hImage, $hBitmap, $hFit

    _WinAPI_DeleteObject(_SendMessage($hWnd, $__STM_GETIMAGE, $IMAGE_BITMAP, 0))

    _GDIPlus_Startup()

    $hImage = _GDIPlus_BitmapCreateFromFile($sImage)
    $hFit = _Icons_FitTo($hWnd, $hImage)
    $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hFit)

    _GDIPlus_ImageDispose($hFit)
    _GDIPlus_Shutdown()

    $Ret = _Icons_SetImage($hWnd, $hBitmap, $IMAGE_BITMAP)
    If $Ret Then
        $hImage = _SendMessage($hWnd, $__STM_GETIMAGE, $IMAGE_BITMAP, 0)
        If (@error) Or ($hBitmap = $hImage) Then $hBitmap = 0
    EndIf
    If $hBitmap Then _WinAPI_DeleteObject($hBitmap)
    Return SetError(1 - $Ret, 0, $Ret)
EndFunc   ;==>_SetImage
Link to comment
Share on other sites

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>
#Include <GDIPlus.au3>
Dim $msg , $SS_REALSIZEIMAGE = 0x00000800

GUICreate(" My GUI Bitmap", 200, 200)

Local $Pic1 = GUICtrlCreateLabel("", 10, 75, 75, 75,$WS_BORDER + $SS_CENTERIMAGE + $SS_REALSIZEIMAGE)
STATIC_SETBITMAP($Pic1,@ScriptDir & "\BMP_1.bmp")

Local $Pic2 = GUICtrlCreateLabel("", 115, 75, 75, 75,$WS_BORDER + $SS_CENTERIMAGE + $SS_REALSIZEIMAGE)
STATIC_SETBITMAP($Pic2,@ScriptDir & "\PNG_1.png")

GUISetState()
    While 1
        $msg = GUIGetMsg()

        If $msg = $GUI_EVENT_CLOSE Then ExitLoop
    WEnd
    GUIDelete()
    Exit


Func STATIC_SETBITMAP($hWnd,$ImageFileName)
Local $GWL_STYLE = (-16) , $SS_BITMAP = 0x0000000E , $SS_ICON   = 0x00000003 ,$STM_SETIMAGE = 0x0172 _

If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd)
if Not BitAND(_WinAPI_GetWindowLong($hWnd, $GWL_STYLE), $SS_BITMAP) = $SS_BITMAP Then
_WinAPI_SetWindowLong($hWnd, $GWL_STYLE, _WinAPI_GetWindowLong($hWnd, $GWL_STYLE) + $SS_BITMAP )
ElseIf  BitAND(_WinAPI_GetWindowLong($hWnd, $GWL_STYLE), $SS_ICON) = $SS_ICON Then
_WinAPI_SetWindowLong($hWnd, $GWL_STYLE, _WinAPI_GetWindowLong($hWnd, $GWL_STYLE) - $SS_ICON)
EndIf

 _GDIPlus_Startup ()
Local $hImage = _GDIPlus_ImageLoadFromFile ($ImageFileName)
Local $Status = DllCall($ghGDIPDll, "int", "GdipCreateHBITMAPFromBitmap", "hwnd", $hImage, "int*", 0, "int", 0)
$HandleImage = $Status[2]
_GDIPlus_ShutDown ()

Return _SendMessage($hWnd, $STM_SETIMAGE, 0, $HandleImage)
EndFunc

صرح السماء كان هنا

 

Link to comment
Share on other sites

I saw a few yahtzee games on the forum, but I didn't see any that looked very good at all, so I decided to update them. It is looking good so far, but I am having a bit of trouble with Icons.au3. I narrowed down the problem lines to these lines in _Icons_SetImage:

$hPrev = _SendMessage($hWnd, $__STM_SETIMAGE, $iType, 0)
    If $hPrev Then
        If $iType = $IMAGE_BITMAP Then
            _WinAPI_DeleteObject($hPrev)
        Else
            _WinAPI_DestroyIcon($hPrev)
        EndIf
    EndIf

If I comment these lines out, I can update my GuiCtrlCreatePics with _SetImage. If I leave these lines in, the image that I am trying to update to doesn't appear and the previous image disappears. I think taking out these lines would cause a memory leak. I don't know if I made this very clear.

Here is my script. Just take a look at it. You will have to comment out the lines that include pictures. There are too many to include here. The problem lines in my script are 58 and 60 unless I comment out the lines specified above.

If you put all the necessary images to run your code, I would look into the problem.

EDIT:

With random images it works perfectly for me.

EDIT2:

My version of autoit was different because i had altered the include files that came with autoit for my own needs. That is why some of the functions didn't work properly in the way you used them. It works now. I just had to restore the include files that came with the original download of autoit.

dantay9, may be here a similar problem.

>_<

Edited by Yashied
Link to comment
Share on other sites

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>
#Include <GDIPlus.au3>
Dim $msg , $SS_REALSIZEIMAGE = 0x00000800

GUICreate(" My GUI Bitmap", 200, 200)

Local $Pic1 = GUICtrlCreateLabel("", 10, 75, 75, 75,$WS_BORDER + $SS_CENTERIMAGE + $SS_REALSIZEIMAGE)
STATIC_SETBITMAP($Pic1,@ScriptDir & "\BMP_1.bmp")

Local $Pic2 = GUICtrlCreateLabel("", 115, 75, 75, 75,$WS_BORDER + $SS_CENTERIMAGE + $SS_REALSIZEIMAGE)
STATIC_SETBITMAP($Pic2,@ScriptDir & "\PNG_1.png")

GUISetState()
    While 1
        $msg = GUIGetMsg()

        If $msg = $GUI_EVENT_CLOSE Then ExitLoop
    WEnd
    GUIDelete()
    Exit


Func STATIC_SETBITMAP($hWnd,$ImageFileName)
Local $GWL_STYLE = (-16) , $SS_BITMAP = 0x0000000E , $SS_ICON   = 0x00000003 ,$STM_SETIMAGE = 0x0172 _

If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd)
if Not BitAND(_WinAPI_GetWindowLong($hWnd, $GWL_STYLE), $SS_BITMAP) = $SS_BITMAP Then
_WinAPI_SetWindowLong($hWnd, $GWL_STYLE, _WinAPI_GetWindowLong($hWnd, $GWL_STYLE) + $SS_BITMAP )
ElseIf  BitAND(_WinAPI_GetWindowLong($hWnd, $GWL_STYLE), $SS_ICON) = $SS_ICON Then
_WinAPI_SetWindowLong($hWnd, $GWL_STYLE, _WinAPI_GetWindowLong($hWnd, $GWL_STYLE) - $SS_ICON)
EndIf

 _GDIPlus_Startup ()
Local $hImage = _GDIPlus_ImageLoadFromFile ($ImageFileName)
Local $Status = DllCall($ghGDIPDll, "int", "GdipCreateHBITMAPFromBitmap", "hwnd", $hImage, "int*", 0, "int", 0)
$HandleImage = $Status[2]
_GDIPlus_ShutDown ()

Return _SendMessage($hWnd, $STM_SETIMAGE, 0, $HandleImage)
EndFunc

Read this very carefully, please.

Important

In version 6 of the Microsoft Win32 controls, a bitmap passed to a static control using the STM_SETIMAGE message was the same bitmap returned by a subsequent STM_SETIMAGE message. The client is responsible to delete any bitmap sent to a static control.

With Microsoft Windows XP, if the bitmap passed in the STM_SETIMAGE message contains pixels with non-zero alpha, the static control takes a copy of the bitmap. This copied bitmap is returned by the next STM_SETIMAGE message. The client code may independently track the bitmaps passed to the static control, but if it does not check and release the bitmaps returned from STM_SETIMAGE messages, the bitmaps are leaked.

Link to comment
Share on other sites

@Yashied

No, that isn't it. Since that post, I recovered my computer and reinstalled autoit. I didn't change any include files since the recovery. It works now. I think it had to do with the way my images were formatted (some of them were handles, others were loaded with GDI+). That was probably it.

Link to comment
Share on other sites

Read this very carefully, please.

$hPrev = _SendMessage($hWnd, $__STM_SETIMAGE, $iType, 0)
    If $hPrev Then
        If $iType = $IMAGE_BITMAP Then
            _WinAPI_DeleteObject($hPrev)
        Else
            _WinAPI_DestroyIcon($hPrev)
        EndIf
    EndIf

hallo! Yashied

We do not need this operation only we need in

Global Variables Image Handle .

صرح السماء كان هنا

 

Link to comment
Share on other sites

Link to comment
Share on other sites

Link

Hope it was translated correctly.

Thank you, I understand

But what is meant by the word leaked

is meant that ... the image will be

leaked from the static Control

or

remain in the memory of the program

And should be deleted to provide part

of the program memory

صرح السماء كان هنا

 

Link to comment
Share on other sites

remain in the memory of the program

And should be deleted to provide part

of the program memory

Yes, that one. It'll bite you if it occurs on a program that should run for a couple of hours and be stable. For example, screen capture program, etc...

OK another question

When we Call function to send this message

Like previous function And after the completion

of the logic operations And then return the results

The question

are Not be Automatically deleted all Operations function

from the memory

I think the message Returns a False Or True

And I do not know it is Returns Handle to the image

Thank you for this explanation

صرح السماء كان هنا

 

Link to comment
Share on other sites

The message returned value is depended on the content of the control. If the control contain a bitmap object, it'll return a handle to this object when calling $STM_SETIMAGE or $STM_GETIMAGE.

When you return from a function, what is promised to be cleaned is the function local variables that will be garbage collected, not kernel objects or anything, for that matter, called via DllCall(). It's your responsibility to release any allocated block of memory. For example, things that will be garbage collected include, DllStructs, strings, primitives, etc.. Hope I'm not too far from the truth. >_<

Link to comment
Share on other sites

The message returned value is depended on the content of the control. If the control contain a bitmap object, it'll return a handle to this object when calling $STM_SETIMAGE or $STM_GETIMAGE.

When you return from a function, what is promised to be cleaned is the function local variables that will be garbage collected, not kernel objects or anything, for that matter, called via DllCall(). It's your responsibility to release any allocated block of memory. For example, things that will be garbage collected include, DllStructs, strings, primitives, etc.. Hope I'm not too far from the truth. :(

Thank you Mass Spammer! >_<

صرح السماء كان هنا

 

Link to comment
Share on other sites

Mass Spammer!

>_<

Finally, when you understand (thanks Authenticity), let me add. In accordance with the requirements of Microsoft, your code should look something like this.

...
$hBitmap = _SendMessage($hWnd, $STM_SETIMAGE, $IMAGE_BITMAP, $hNewBitmap)
_WinAPI_DeleteObject($hBitmap)
$hBitmap = _SendMessage($hWnd, $STM_GETIMAGE, $IMAGE_BITMAP, 0)
If $hBitmap <> $hNewBitmap Then
    _WinAPI_DeleteObject($hNewBitmap)
EndIf
...

Good luck.

:(

Edited by Yashied
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...