Jump to content

Refreshing _GDIPlus_GraphicsDrawImageRect


Recommended Posts

I'm using this method to draw a transparent image inside my window. It works, but not as expected. With that example - without minimize button or anything else and the _GDIPlus_GraphicsDrawImageRect inside the main loop -, it works, but when you need to refresh the window, like restoring it after minimized or when you drag some window above your autoit window, the draw just gone. How can I refresh the image, for example, when I display one MsgBox and minimize and restore the window with the MsgBox opened?

Try the example below. Run the script and the image will show, then minimize and restore. Then click on the button, keep the MsgBox opened, minimize and restore... The image just disappears. How can I keep it?


Link to comment
Share on other sites

#include <GDIPlus.au3>
#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WINAPI.au3>
Opt("GUIOnEventMode", 1)

Global $Image1 = _GDIPlus_ImageLoadFromFile("test.bmp")
$width = _GDIPlus_ImageGetWidth($Image1)
$height = _GDIPlus_ImageGetHeight($Image1)
Global Const $AC_SRC_ALPHA = 1
Global $mainWindow = GUICreate("Setup", 420, 235, @DesktopWidth / 2 - 160, @DesktopHeight / 2 - 145, -1, -1)
$pic = GUICtrlCreatePic("", 0, 0, $width, $height)
$Image1 = ImageColorToTransparent($Image1, 0xff0000)
Global $Graphic = _GDIPlus_GraphicsCreateFromHWND(GUICtrlGetHandle($pic))
_GDIPlus_GraphicsDrawImageRect($Graphic, $Image1, 0, 0, $width, $height)
Global $btnInstall = GUICtrlCreateButton("Click me", 310, 124, 100, 23)
;~ Events
GUICtrlSetOnEvent($btnInstall, "Clickme")

;~ Special Events
GUISetOnEvent($GUI_EVENT_CLOSE, "SpecialEvents")
GUISetOnEvent($GUI_EVENT_MINIMIZE, "SpecialEvents")
GUISetOnEvent($GUI_EVENT_RESTORE, "SpecialEvents")

While 1
    $MSG = GUIGetMsg()
    Switch $MSG
        Case -3

Func Quit()
EndFunc   ;==>Quit

; Draw PNG image
Func MY_WM_PAINT($hWnd, $iMsg, $wParam, $lParam)
    ConsoleWrite("Hola" & @CRLF)
    _WinAPI_RedrawWindow($mainWindow, 0, 0, $RDW_UPDATENOW)
    _GDIPlus_GraphicsDrawImageRect($Graphic, $Image1, 0, 0, $width, $height)
    _WinAPI_RedrawWindow($mainWindow, 0, 0, $RDW_VALIDATE)
EndFunc   ;==>MY_WM_PAINT

Func Clickme()
    MsgBox(0, "Info", "Test")
    Return 0
EndFunc   ;==>Clickme
;$iColor - Colour to be made transparent. Hex colour format 0xRRGGBB. If Default used then top left pixel colour of image
; is used as the transparent colour.
Func ImageColorToTransparent($hImage2, $iColor = Default)
    Local $hBitmap1, $Reslt, $width, $height, $stride, $format, $Scan0, $v_Buffer, $v_Value, $iIW, $iIH

    $GuiSizeX = _GDIPlus_ImageGetWidth($hImage2)
    $GuiSizeY = _GDIPlus_ImageGetHeight($hImage2)
    $hBitmap1 = _GDIPlus_BitmapCloneArea($hImage2, 0, 0, $GuiSizeX, $GuiSizeY, $GDIP_PXF32ARGB)
    If $iColor = Default Then $iColor = GDIPlus_BitmapGetPixel($hBitmap1, 1, 1); Transparent color
    ProgressOn("", "Processing", "0 percent", "", @DesktopHeight - 80, 1)
    $Reslt = _GDIPlus_BitmapLockBits($hBitmap1, 0, 0, $GuiSizeX, $GuiSizeY, BitOR($GDIP_ILMREAD, $GDIP_ILMWRITE), $GDIP_PXF32ARGB)
    ;Get the returned values of _GDIPlus_BitmapLockBits ()
    $width = DllStructGetData($Reslt, "width")
    $height = DllStructGetData($Reslt, "height")
    $stride = DllStructGetData($Reslt, "stride")
    $format = DllStructGetData($Reslt, "format")
    $Scan0 = DllStructGetData($Reslt, "Scan0")
    For $i = 0 To $GuiSizeX - 1
        For $j = 0 To $GuiSizeY - 1
            $v_Buffer = DllStructCreate("dword", $Scan0 + ($j * $stride) + ($i * 4))
            $v_Value = DllStructGetData($v_Buffer, 1)
            If Hex($v_Value, 6) = Hex($iColor, 6) Then
                DllStructSetData($v_Buffer, 1, Hex($iColor, 6)); Sets Transparency here. Alpha Channel = 00, not written to.
        ProgressSet(Int(100 * $i / ($GuiSizeX)), Int(100 * $i / ($GuiSizeX)) & " percent")
    _GDIPlus_BitmapUnlockBits($hBitmap1, $Reslt)
    Return $hBitmap1
EndFunc   ;==>ImageColorToTransparent

;The GetPixel method gets the color of a specified pixel in this bitmap.
Func GDIPlus_BitmapGetPixel($hBitmap, $iX, $iY)
    Local $tArgb, $pArgb, $aRet
    $tArgb = DllStructCreate("dword Argb")
    $pArgb = DllStructGetPtr($tArgb)
    $aRet = DllCall("gdiplus.dll", "int", "GdipBitmapGetPixel", "hwnd", $hBitmap, "int", $iX, "int", $iY, "ptr", $pArgb)
    Return "0x" & Hex(DllStructGetData($tArgb, "Argb"))
EndFunc   ;==>GDIPlus_BitmapGetPixel

;~ Function for the special events (Close, Minimise and Maximize)
Func SpecialEvents()
        Case @GUI_CtrlId = $GUI_EVENT_CLOSE
        Case @GUI_CtrlId = $GUI_EVENT_MINIMIZE
            WinSetState($mainWindow, "", @SW_MINIMIZE)
        Case @GUI_CtrlId = $GUI_EVENT_RESTORE
;~       We can use the line below, but it doesn't solve all the poblems like if the MsgBox is opened
;~       _GDIPlus_GraphicsDrawImageRect($Graphic, $Image1, 0, 0, $width, $height)
EndFunc   ;==>SpecialEvents


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

  • Create New...