Chance Posted March 31, 2013 Share Posted March 31, 2013 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..... expandcollapse popup#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 More sharing options...
Solution UEZ Posted March 31, 2013 Solution Share Posted March 31, 2013 Try this: expandcollapse popup#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 Chance 1 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 More sharing options...
Chance Posted April 1, 2013 Author Share Posted April 1, 2013 Thank you! I really don't know what to say. But thanks for the help, I really appreciate it. This solved my problem and more Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now