Jump to content

Clear Pic control


Go to solution Solved by UEZ,

Recommended Posts

I've had this problem where I can't clear an image I set to a picture control in a project I started some time ago, I never figured this out w/o having to do things that seem overly coplicated.

My script deals with a user picking an image and then the script displays a smaller version rendered in the pic control, in the script, a user can then select an option to use no pic and in that moment, I never figured out a way to make the script clear the image after setting it the way I do.

I want to avoid writing files to the hard drive so use functions to deal with the image in memory using functions I've found around the forums.

I made an example showing my problem.

If you click set image, a random colored image will be put in the control like how I do it with other images.

But [acronym='please help :(']I have no idea how to clear it when pressing clear image.....

#AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w- 7

#Include <GDIPlus.au3>
#include <MemoryConstants.au3>
#include <Memory.au3>

#include <GUIConstants.au3>
#include <StaticConstants.au3>

#Region ### START Koda GUI section ### Form=
Global $UI_MAIN = GUICreate("some kind of...", 235, 183, 192, 124)
Global $Image = GUICtrlCreatePic("", 8, 8, 220, 140, $SS_SUNKEN+$SS_CENTERIMAGE)
Global $SetImg = GUICtrlCreateButton("Set Image", 8, 152, 75, 25)
Global $ClearScrn = GUICtrlCreateButton("Clear Image", 152, 152, 75, 25)
GUICtrlCreateLabel("/)(O ) _( O)(\", 88, 160, 63, 17)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

Global $TempImg

_GDIPlus_Startup()

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            _GDIPlus_Shutdown()
            Exit
        Case $SetImg
            $TempImg = Load_BMP_From_Mem(Draw("IDS HABBENING!!"), True)
            _WinAPI_DeleteObject(GUICtrlSendMsg($Image, 0x0172, 0, $TempImg))
            $TempImg = 0
        Case $ClearScrn
            ; do something here to clear the image control
            GUICtrlSetData($Image, "")

    EndSwitch
WEnd


Func Draw($sString = "")
    Local $hGraphic, $hBrush, $hFormat, _
            $hFamily, $hFont, $tLayout, _
            $aInfo, $hBitmap, $FontSize, _
            $iWidth, $iHeight, $fontStyle, _
            $NewImage, $hImage

    $sString = StringProc($sString, 18)
    $iWidth = 220
    $iHeight = 140
    $FontSize = 15
    $fontStyle = 1

    $hImage = _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight)
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hImage)
    $hBrush = _GDIPlus_BrushCreateSolid('0xFF' & Hex(Random(0, 255, 1), 2) & Hex(Random(0, 255, 1), 2) & Hex(Random(0, 255, 1), 2))
    _GDIPlus_GraphicsFillRect($hGraphic, 0, 0, $iWidth, $iHeight, $hBrush)
    _GDIPlus_BrushDispose($hBrush)

    $hFormat = _GDIPlus_StringFormatCreate()
    $hFamily = _GDIPlus_FontFamilyCreate("consolas")
    $hFont = _GDIPlus_FontCreate($hFamily, $FontSize, $fontStyle)
    $tLayout = _GDIPlus_RectFCreate($iWidth/2/5, $iHeight/3, 0, 0)
    $aInfo = _GDIPlus_GraphicsMeasureString($hGraphic, $sString, $hFont, $tLayout, $hFormat)
    $hBrush = _GDIPlus_BrushCreateSolid('0xFF' & Hex(Random(0, 255, 1), 2) & Hex(Random(0, 255, 1), 2) & Hex(Random(0, 255, 1), 2))
    _GDIPlus_GraphicsDrawStringEx($hGraphic, $sString, $hFont, $aInfo[0], $hFormat, $hBrush)
    $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)

    _GDIPlus_FontDispose($hFont)
    _GDIPlus_BrushDispose($hBrush)
    _WinAPI_DeleteObject($hBitmap)
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_FontFamilyDispose($hFamily)
    _GDIPlus_StringFormatDispose($hFormat)

    $NewImage = _GDIPlus_SaveImageToStream($hImage, 100, "png")
    _GDIPlus_ImageDispose($hImage)

    Return $NewImage
EndFunc   ;==>Draw

Func _GDIPlus_SaveImageToStream($hBitmap, $iQuality = 50, $Encoder = "jpg") ;coded by Andreik, modified by UEZ and me
    Local $tParams
    Local $tData
    Local $pData
    Local $pParams

    Local $sImgCLSID = _GDIPlus_EncodersGetCLSID($Encoder)
    Local $tGUID = _WinAPI_GUIDFromString($sImgCLSID)
    Local $pEncoder = DllStructGetPtr($tGUID)

    If $Encoder == "jpg" Or $Encoder == "jpeg" Then
        $tParams = _GDIPlus_ParamInit(1)
        $tData = DllStructCreate("int Quality")
        DllStructSetData($tData, "Quality", $iQuality) ;quality 0-100
        $pData = DllStructGetPtr($tData)
        _GDIPlus_ParamAdd($tParams, $GDIP_EPGQUALITY, 1, $GDIP_EPTLONG, $pData)
        $pParams = DllStructGetPtr($tParams)
    Else
        $pParams = 0
    EndIf

    Local $hStream = DllCall("ole32.dll", "uint", "CreateStreamOnHGlobal", "ptr", 0, "bool", True, "ptr*", 0)
    If @error Then Return SetError(1, 0, 0)
    $hStream = $hStream[3]
    DllCall($ghGDIPDll, "uint", "GdipSaveImageToStream", "ptr", $hBitmap, "ptr", $hStream, "ptr", $pEncoder, "ptr", $pParams)
    _GDIPlus_BitmapDispose($hBitmap)
    Local $hMemory = DllCall("ole32.dll", "uint", "GetHGlobalFromStream", "ptr", $hStream, "ptr*", 0)
    If @error Then Return SetError(2, 0, 0)

    $hMemory = $hMemory[2]
    Local $iMemSize = _MemGlobalSize($hMemory)
    Local $pMem = _MemGlobalLock($hMemory)

    $tData = DllStructCreate("byte[" & $iMemSize & "]", $pMem)
    Local $bData = DllStructGetData($tData, 1)
    Local $tVARIANT = DllStructCreate("word vt;word r1;word r2;word r3;ptr data;ptr")

    DllCall("oleaut32.dll", "long", "DispCallFunc", "ptr", $hStream, "dword", 8 + 8 * @AutoItX64, "dword", 4, "dword", 23, "dword", 0, "ptr", 0, "ptr", 0, "ptr", DllStructGetPtr($tVARIANT)) ;http://msdn.microsoft.com/en-us/library/windows/desktop/ms221473(v=vs.85).aspx
    _MemGlobalFree($hMemory)

    Return $bData
EndFunc   ;==>_GDIPlus_SaveImageToStream

Func StringProc($StrIn, $SplitMark); i think melba made this
    Local $StrOut = '', $count, $StrSplit, $StrLen
    $StrSplit = StringSplit($StrIn, @CRLF, 2)
    For $X = 0 To UBound($StrSplit) - 1
        $StrLen = StringLen($StrSplit[$X])
        If $StrLen > 17 Then
            $count = Ceiling(StringLen($StrSplit[$X]) / $SplitMark)
            Local $array[$count + 1], $start = 1
            For $I = 0 To $count
                $array[$I] = StringMid($StrSplit[$X], $start, $SplitMark)
                $start += $SplitMark
            Next
            For $I = 0 To $count
                If $array[$I] = "" Or $array[$I] = " " Then ContinueLoop
                If StringInStr($array[$I], " ", 0, 1, 1, 1) Then
                    $StrOut &= StringReplace(StringReplace(StringReplace($array[$I], @LF, ""), @CR, ""), " ", "", 1, 1) & @LF
                Else
                    $StrOut &= StringReplace(StringReplace($array[$I], @LF, ""), @CR, "") & @LF
                EndIf
            Next
        Else
            If $StrSplit[$X] = "" Then ContinueLoop
            $StrOut &= StringReplace(StringReplace($StrSplit[$X], @LF, ""), @CR, "") & @LF
        EndIf
    Next
    Return $StrOut
EndFunc   ;==>StringProc

Func _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight, $iStride = 0, $iPixelFormat = 0x0026200A, $pScan0 = 0)
    Local $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateBitmapFromScan0", "int", $iWidth, "int", $iHeight, "int", $iStride, "int", $iPixelFormat, "ptr", $pScan0, "int*", 0)
    If @error Then Return SetError(@error, @extended, 0)
    Return $aResult[6]
EndFunc   ;==>_GDIPlus_BitmapCreateFromScan0

;======================================================================================
; Function Name:        Load_BMP_From_Mem
; Description:          Loads an image which is saved as a binary string and converts it to a bitmap or hbitmap
;
; Parameters:           $bImage:        the binary string which contains any valid image which is supported by GDI+
; Optional:                 $hHBITMAP:      if false a bitmap will be created, if true a hbitmap will be created
;
; Remark:                   hbitmap format is used generally for GUI internal images, $bitmap is more a GDI+ image format
;
; Requirement(s):       GDIPlus.au3, Memory.au3 and _GDIPlus_BitmapCreateDIBFromBitmap() from WinAPIEx.au3
; Return Value(s):  Success: handle to bitmap or hbitmap, Error: 0
; Error codes:          1: $bImage is not a binary string
;                               2: unable to create stream on HGlobal
;                               3: unable to create bitmap from stream
;
; Author(s):                UEZ
; Additional Code:  thanks to progandy for the MemGlobalAlloc and tVARIANT lines
; Version:                  v0.97 Build 2012-01-04 Beta
;=======================================================================================
Func Load_BMP_From_Mem($bImage, $hHBITMAP = False)
    If Not IsBinary($bImage) Then Return SetError(1, 0, 0)
    Local $aResult
    Local Const $memBitmap = Binary($bImage) ;load image  saved in variable (memory) and convert it to binary
    Local Const $len = BinaryLen($memBitmap) ;get length of image
    Local Const $hData = _MemGlobalAlloc($len, $GMEM_MOVEABLE) ;allocates movable memory  ($GMEM_MOVEABLE = 0x0002)
    Local Const $pData = _MemGlobalLock($hData) ;translate the handle into a pointer
    Local $tMem = DllStructCreate("byte[" & $len & "]", $pData) ;create struct
    DllStructSetData($tMem, 1, $memBitmap) ;fill struct with image data
    _MemGlobalUnlock($hData) ;decrements the lock count  associated with a memory object that was allocated with GMEM_MOVEABLE
    $aResult = DllCall("ole32.dll", "int", "CreateStreamOnHGlobal", "handle", $pData, "int", True, "ptr*", 0) ;Creates a stream object that uses an HGLOBAL memory handle to store the stream contents
    If @error Then SetError(2, 0, 0)
    Local Const $hStream = $aResult[3]
    $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateBitmapFromStream", "ptr", $hStream, "int*", 0) ;Creates a Bitmap object based on an IStream COM interface
    If @error Then SetError(3, 0, 0)
    Local Const $hBitmap = $aResult[2]
    Local $tVARIANT = DllStructCreate("word vt;word r1;word r2;word r3;ptr data; ptr")
    DllCall("oleaut32.dll", "long", "DispCallFunc", "ptr", $hStream, "dword", 8 + 8 * @AutoItX64, _
            "dword", 4, "dword", 23, "dword", 0, "ptr", 0, "ptr", 0, "ptr", DllStructGetPtr($tVARIANT)) ;release memory from $hStream to avoid memory leak
    $tMem = 0
    $tVARIANT = 0
    If $hHBITMAP Then
        Local Const $hHBmp = _GDIPlus_BitmapCreateDIBFromBitmap($hBitmap)
        _GDIPlus_BitmapDispose($hBitmap)
        Return $hHBmp
    EndIf
    Return $hBitmap
EndFunc   ;==>Load_BMP_From_Mem

Func _GDIPlus_BitmapCreateDIBFromBitmap($hBitmap)
    Local $tBIHDR, $Ret, $tData, $pBits, $hResult = 0
    $Ret = DllCall($ghGDIPDll, 'uint', 'GdipGetImageDimension', 'ptr', $hBitmap, 'float*', 0, 'float*', 0)
    If (@error) Or ($Ret[0]) Then Return 0
    $tData = _GDIPlus_BitmapLockBits($hBitmap, 0, 0, $Ret[2], $Ret[3], $GDIP_ILMREAD, $GDIP_PXF32ARGB)
    $pBits = DllStructGetData($tData, 'Scan0')
    If Not $pBits Then Return 0
    $tBIHDR = DllStructCreate('dword;long;long;ushort;ushort;dword;dword;long;long;dword;dword')
    DllStructSetData($tBIHDR, 1, DllStructGetSize($tBIHDR))
    DllStructSetData($tBIHDR, 2, $Ret[2])
    DllStructSetData($tBIHDR, 3, $Ret[3])
    DllStructSetData($tBIHDR, 4, 1)
    DllStructSetData($tBIHDR, 5, 32)
    DllStructSetData($tBIHDR, 6, 0)
    $hResult = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', 'hwnd', 0, 'ptr', DllStructGetPtr($tBIHDR), 'uint', 0, 'ptr*', 0, 'ptr', 0, 'dword', 0)
    If (Not @error) And ($hResult[0]) Then
        DllCall('gdi32.dll', 'dword', 'SetBitmapBits', 'ptr', $hResult[0], 'dword', $Ret[2] * $Ret[3] * 4, 'ptr', DllStructGetData($tData, 'Scan0'))
        $hResult = $hResult[0]
    Else
        $hResult = 0
    EndIf
    _GDIPlus_BitmapUnlockBits($hBitmap, $tData)
    Return $hResult
EndFunc   ;==>_GDIPlus_BitmapCreateDIBFromBitmap
Link to comment
Share on other sites

  • Solution

Try this:

#AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w- 7

#Include <GDIPlus.au3>
#include <MemoryConstants.au3>
#include <Memory.au3>

#include <GUIConstants.au3>
#include <StaticConstants.au3>

#Region ### START Koda GUI section ### Form=
Global $UI_MAIN = GUICreate("some kind of...", 235, 183, 192, 124)
Global $Image = GUICtrlCreatePic("", 8, 8, 220, 140, $SS_SUNKEN+$SS_CENTERIMAGE)
Global $SetImg = GUICtrlCreateButton("Set Image", 8, 152, 75, 25)
Global $ClearScrn = GUICtrlCreateButton("Clear Image", 152, 152, 75, 25)
GUICtrlCreateLabel("/)(O ) _( O)(\", 88, 160, 63, 17)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

Global $TempImg

_GDIPlus_Startup()
Global $hBmp_Empty = _GDIPlus_BitmapCreateFromScan0(220, 140)
Global $hCtx_Empty = _GDIPlus_ImageGetGraphicsContext($hBmp_Empty)
_GDIPlus_GraphicsClear($hCtx_Empty, 0xFFF0F0F0)
Global $hHBmp_Empty = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBmp_Empty)
_GDIPlus_GraphicsDispose($hCtx_Empty)
_GDIPlus_BitmapDispose($hBmp_Empty)

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            _WinAPI_DeleteObject($hHBmp_Empty)
            _GDIPlus_Shutdown()
            Exit
        Case $SetImg
            $TempImg = Draw("IDS HABBENING!!")
            _WinAPI_DeleteObject(GUICtrlSendMsg($Image, 0x0172, 0, $TempImg))
            _WinAPI_DeleteObject($TempImg)
        Case $ClearScrn
            ; do something here to clear the image control
            _WinAPI_DeleteObject(GUICtrlSendMsg($Image, 0x0172, 0, $hHBmp_Empty))

    EndSwitch
WEnd


Func Draw($sString = "")
    Local $hGraphic, $hBrush, $hFormat, _
            $hFamily, $hFont, $tLayout, _
            $aInfo, $hBitmap, $FontSize, _
            $iWidth, $iHeight, $fontStyle, _
            $hImage

    $sString = StringProc($sString, 18)
    $iWidth = 220
    $iHeight = 140
    $FontSize = 15
    $fontStyle = 1

    $hImage = _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight)
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hImage)
    $hBrush = _GDIPlus_BrushCreateSolid('0xFF' & Hex(Random(0, 255, 1), 2) & Hex(Random(0, 255, 1), 2) & Hex(Random(0, 255, 1), 2))
    _GDIPlus_GraphicsFillRect($hGraphic, 0, 0, $iWidth, $iHeight, $hBrush)
    _GDIPlus_BrushDispose($hBrush)

    $hFormat = _GDIPlus_StringFormatCreate()
    $hFamily = _GDIPlus_FontFamilyCreate("consolas")
    $hFont = _GDIPlus_FontCreate($hFamily, $FontSize, $fontStyle)
    $tLayout = _GDIPlus_RectFCreate($iWidth/2/5, $iHeight/3, 0, 0)
    $aInfo = _GDIPlus_GraphicsMeasureString($hGraphic, $sString, $hFont, $tLayout, $hFormat)
    $hBrush = _GDIPlus_BrushCreateSolid('0xFF' & Hex(Random(0, 255, 1), 2) & Hex(Random(0, 255, 1), 2) & Hex(Random(0, 255, 1), 2))
    _GDIPlus_GraphicsDrawStringEx($hGraphic, $sString, $hFont, $aInfo[0], $hFormat, $hBrush)
    $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)

    _GDIPlus_FontDispose($hFont)
    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_BitmapDispose($hImage)
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_FontFamilyDispose($hFamily)
    _GDIPlus_StringFormatDispose($hFormat)

    Return $hBitmap
EndFunc   ;==>Draw

Func StringProc($StrIn, $SplitMark); i think melba made this
    Local $StrOut = '', $count, $StrSplit, $StrLen
    $StrSplit = StringSplit($StrIn, @CRLF, 2)
    For $X = 0 To UBound($StrSplit) - 1
        $StrLen = StringLen($StrSplit[$X])
        If $StrLen > 17 Then
            $count = Ceiling(StringLen($StrSplit[$X]) / $SplitMark)
            Local $array[$count + 1], $start = 1
            For $I = 0 To $count
                $array[$I] = StringMid($StrSplit[$X], $start, $SplitMark)
                $start += $SplitMark
            Next
            For $I = 0 To $count
                If $array[$I] = "" Or $array[$I] = " " Then ContinueLoop
                If StringInStr($array[$I], " ", 0, 1, 1, 1) Then
                    $StrOut &= StringReplace(StringReplace(StringReplace($array[$I], @LF, ""), @CR, ""), " ", "", 1, 1) & @LF
                Else
                    $StrOut &= StringReplace(StringReplace($array[$I], @LF, ""), @CR, "") & @LF
                EndIf
            Next
        Else
            If $StrSplit[$X] = "" Then ContinueLoop
            $StrOut &= StringReplace(StringReplace($StrSplit[$X], @LF, ""), @CR, "") & @LF
        EndIf
    Next
    Return $StrOut
EndFunc   ;==>StringProc

Func _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight, $iStride = 0, $iPixelFormat = 0x0026200A, $pScan0 = 0)
    Local $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateBitmapFromScan0", "int", $iWidth, "int", $iHeight, "int", $iStride, "int", $iPixelFormat, "ptr", $pScan0, "int*", 0)
    If @error Then Return SetError(@error, @extended, 0)
    Return $aResult[6]
EndFunc   ;==>_GDIPlus_BitmapCreateFromScan0

I cleaned up your code a little bit by removing unneeded functions.

Br,

UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

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...