Jump to content

GDI+ DoubleBuffer


 Share

Recommended Posts

Can someone give me a Autoit implementation of GDI+ double buffer i have some code and I want to avoid flickering. I now that it can be done by creating second DC, compatible bitmap and _WinAPI_BitBlt or (second way) by _GDIPlus_BitmapLockBits :) My script is only a example and I can make the entire script in entire diffrent way, I just need a key to solution of this problem:

Code:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <Misc.au3>
#include <Array.au3>
_GDIPlus_Startup()
Opt("MouseCoordMode", 2)
$dll = DllOpen("user32.dll")
   $Gui=GUICreate("GameName",800,600,-1,-1) 
    GUISetBkColor(0x303030, $Gui)
    $pic3=GUICtrlCreatePic("",0,0,800,600)
        $pic2=GUICtrlCreatePic("",10,10,500,500)
    $pic1=GUICtrlCreatePic("",3,110,100,100)

    GUISetState(@SW_SHOW) 
PicSetGraphics($pic3, 800, 600, @ScriptDir&"\gfx\grass.jpg",1,0)
    PicSetGraphics($pic2, 100, 100, @ScriptDir&"\gfx\explosion.png",4,0)
        PicSetGraphics($pic1, 100, 100, @ScriptDir&"\gfx\sprite.png",1,20)
        Local $ii=3
    While 1
        $ii+=1
        if $ii=300 then $ii=0
        ControlMove("GameName","",$pic1,110,$ii)

    _WinAPI_RedrawWindow($Gui,"", "", $RDW_INVALIDATE)
    sleep(15)
        $msg = GUIGetMsg()
        If $msg = $GUI_EVENT_CLOSE Then ExitLoop
    WEnd
    GUIDelete()

Func PicSetGraphics($cID, $img_W, $img_H, $image_file,$scale,$rotate)
    Local $STM_SETIMAGE = 0x0172
    Local $IMAGE_BITMAP = 0
    Local $hWnd, $hBitmap, $hImage, $hGraphic, $hBrush, $hBrush1, $hbmp, $aBmp
    $hWnd = GUICtrlGetHandle($cID)
    ;
    $hGraphicGUI = _GDIPlus_GraphicsCreateFromHWND($hWnd)
    $hImage = _GDIPlus_BitmapCreateFromGraphics(($img_W*$scale)*3, ($img_H*$scale)*3, $hGraphicGUI)
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hImage)
    if $rotate<>0 then
        $hMatrix = _GDIPlus_MatrixCreate()
    _GDIPlus_MatrixRotate($hMatrix, $rotate, "False")
    _GDIPlus_GraphicsSetTransform($hGraphic, $hMatrix)
    endif
    _GDIPlus_GraphicsSetSmoothingMode($hGraphic, 2)
    ;----->  All Graphics Here
if $rotate<>0 then
    $hBitmap = _GDIPlus_ImageLoadFromFile($image_file)
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap,  $img_w,  $img_H, $img_W*$scale, $img_H*$scale)
Else
        $hBitmap = _GDIPlus_ImageLoadFromFile($image_file)
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap,  0,  0, $img_W*$scale, $img_H*$scale)
    endif
    ; -----> End of all Graphics
    $hbmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
    $iX = _GDIPlus_ImageGetWidth ($hImage)
    $iY = _GDIPlus_ImageGetHeight ($hImage)
    $aBmp = DllCall("user32.dll", "hwnd", "SendMessage", "hwnd", $hWnd, "int", $STM_SETIMAGE, "int", $IMAGE_BITMAP, "int", $hbmp)
    _WinAPI_RedrawWindow($Gui, "", "", BitOR($RDW_INVALIDATE, $RDW_UPDATENOW, $RDW_FRAME))
    If $aBmp[0] <> 0 Then _WinAPI_DeleteObject($aBmp[0])
    _WinAPI_DeleteObject($hbmp)
    _WinAPI_DeleteObject($hImage)
    _GDIPlus_BrushDispose($hBrush1)
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_GraphicsDispose($hGraphicGUI)
    _WinAPI_DeleteObject($hBitmap)
EndFunc   ;==>PicSetGraphics
Func _Quit()
    Exit
EndFunc   ;==>_Quit
;
Func ntmem($i_PID = -1)
    If $i_PID <> -1 Then
        Local $ai_Handle = DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', 0x1f0fff, 'int', False, 'int', $i_PID)
        Local $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', $ai_Handle[0])
        DllCall('kernel32.dll', 'int', 'CloseHandle', 'int', $ai_Handle[0])
    Else
        Local $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', -1)
    EndIf
EndFunc   ;==>ntmem
Link to comment
Share on other sites

Here is a double buffer template (i think made by monoceres) that I use all time.

#include <GUIConstants.au3>
#include <GDIplus.au3>

Global Const $width = 600
Global Const $height = 400
Global $title = "GDI+"

; Build your GUI here
Opt("GUIOnEventMode", 1)
$hwnd = GUICreate($title, $width, $height)
GUISetOnEvent($GUI_EVENT_CLOSE, "close")
GUISetState()

; Load your GDI+ resources here:
_GDIPlus_Startup()
$graphics = _GDIPlus_GraphicsCreateFromHWND($hwnd)
$bitmap = _GDIPlus_BitmapCreateFromGraphics($width, $height, $graphics)
$backbuffer = _GDIPlus_ImageGetGraphicsContext($bitmap)


While 1
    _GDIPlus_GraphicsClear($backbuffer)

    ; Draw your GDI+ scene onto $backbuffer here

    _GDIPlus_GraphicsDrawImageRect($graphics, $bitmap, 0, 0, $width, $height)
    Sleep(10)
WEnd

Func close()
    _GDIPlus_GraphicsDispose($backbuffer)
    _GDIPlus_BitmapDispose($bitmap)
    _GDIPlus_GraphicsDispose($graphics)
    _GDIPlus_Shutdown()
    Exit
EndFunc ;==>close
Link to comment
Share on other sites

With all the respect, where is the double buffering in you example? I can only see a normal GraphicsDrawImageRect function with only one DC? Or im wrong, meaby you can make a example with some example moving picture, I would really appreciate that. Thank you :)

Edited by Uriziel01
Link to comment
Share on other sites

Look here: http://www.autoitscript.com/forum/index.php?showtopic=87200

A lot of GDI+ examples or seach in the forum!

UEZ

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

With all the respect, where is the double buffering in you example? I can only see a normal GraphicsDrawImageRect function with only one DC? Or im wrong, meaby you can make a example with some example moving picture, I would really appreciate that. Thank you :)

There are two handles. One to the screen and one to an offscreen buffer that will be drawn to the screen when all drawing is complete.

Broken link? PM me and I'll send you the file!

Link to comment
Share on other sites

Ohhh, sorry everyone :) I did'nt looked it the script correctly, after seeing UEZ link (Enterprise Warp by youknowwho4eva) I have understood double-buffering trick in it ;) Now I have second question, how can I make a one image from (for example) 32 images (tile based game map) ? Because it will need less % of CPU and BM's of RAM when I will render only one big image instead of 32 (or more) small ones, I think? And it will be faster to save this to a file and then read and display? Or meaby leave it in memory ? p.s-Im HORRIBLE sorry for my bad english, if you dont know what im talking about, please say, I will try to do it again more correctly. Thank you for the help! B)

Edited by Uriziel01
Link to comment
Share on other sites

Have a look also to monoceres' excellent example -> http://www.autoitscript.com/forum/index.php?showtopic=81580

This might answer your question partly.

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