Jump to content
Sign in to follow this  
Uriziel01

GDI+ DoubleBuffer

Recommended Posts

Uriziel01

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

Share this post


Link to post
Share on other sites
dantay9

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

[font="Verdana"] [size="2"]"[/size][/font]Failure is not an option -- it comes packaged with Windows"[font="Verdana"][size="2"] Gecko Web Browser[/size][/font][font="Verdana"][size="2"], [/size][/font][font="Verdana"][size="2"]Yahtzee![/size][/font][font="Verdana"][size="2"], Toolbar Launcher (like RocketDock)[/size][/font][font="Verdana"][size="2"]Internet Blocker, Simple Calculator, Local Weather, Easy GDI+ GUI [/size][/font][font="Verdana"][size="2"]Triangle Solver, TCP File Transfer, [/size][/font][font="Verdana"][size="2"]Valuater's Autoit Wrappers[/size][/font][font="Verdana"][size="3"][size="2"][size="2"]OOP In AutoIt[/size][/size][/size][/font][font="Verdana"][size="2"][size="1"]Using Windows XP SP3, 1GB RAM, AMD Athlon Processor @ 2.1 GHzCheck me out at gadgets.freehostrocket.com[/size][/size][/font]

Share this post


Link to post
Share on other sites
Uriziel01

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

Share this post


Link to post
Share on other sites
UEZ

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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites
dantay9

It isn't a working example. It was just a template to build on. I thought it would be easier if you had a clean example of how double buffering should work.


[font="Verdana"] [size="2"]"[/size][/font]Failure is not an option -- it comes packaged with Windows"[font="Verdana"][size="2"] Gecko Web Browser[/size][/font][font="Verdana"][size="2"], [/size][/font][font="Verdana"][size="2"]Yahtzee![/size][/font][font="Verdana"][size="2"], Toolbar Launcher (like RocketDock)[/size][/font][font="Verdana"][size="2"]Internet Blocker, Simple Calculator, Local Weather, Easy GDI+ GUI [/size][/font][font="Verdana"][size="2"]Triangle Solver, TCP File Transfer, [/size][/font][font="Verdana"][size="2"]Valuater's Autoit Wrappers[/size][/font][font="Verdana"][size="3"][size="2"][size="2"]OOP In AutoIt[/size][/size][/size][/font][font="Verdana"][size="2"][size="1"]Using Windows XP SP3, 1GB RAM, AMD Athlon Processor @ 2.1 GHzCheck me out at gadgets.freehostrocket.com[/size][/size][/font]

Share this post


Link to post
Share on other sites
monoceres

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!

Share this post


Link to post
Share on other sites
Uriziel01

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

Share this post


Link to post
Share on other sites
UEZ

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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
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
Sign in to follow this  

×