Jump to content

Using _GDIPlus_BitmapCreateFromGraphics question


Recommended Posts

When using the aforementioned function for storing temporarily bitmap of the window I get a black rectangle instead of actual window contents.

All drawing on the window is performed using Gdiplus functions.

Is there any other way to capture window contents as bitmap to be redrawn later on a WM_PAINT event?

I need this because I found that redrawing the window all over creates some shadows on letters being redrawn and if I use _GDIPlus_GraphicsFillRect to refill the window with

background color I get flickering .

Is there any example on how to use _GDIPlus_BitmapCreateFromGraphics properly or maybe some other way to copy window contents?

I did search the forum for that function , but I saw it only used with window whose contents are created by regular control creation functions as opposed to GDIplus calls.

Edited by matrix200
Link to comment
Share on other sites

Ok I was able to somehow alleviate the problem with flicker by checking the actual window getting WM_PAINT and redrawing only that window.

Now I have a different problem though.

If I take some window with dynamic content (like winamp or video playing window of bsplayer) and drag it over my application sometimes (usually if I drag really fast ) one or more windows are not redrawn anymore and lose their contents.

Now I was able to reproduce it by sending a WM_PAINT event to a single window if InvalidateRectangle is called on it before WM_PAINT is sent.

For some reason unknown to me a window with changing content is invalidating parts of my windows even though it shouldn't

Is there anyway to intercept that rectangle structure being passed so I can decide for myself whether a certain region is validated or not?

To show an example of what I think is the problem I have that small program.

CODE

#include <GDIPlus.au3>

#include <GUIConstants.au3>

#Include <WinAPI.au3>

Global $myBlackPen

InitGraphics()

$GUI = GUICreate("WinNutClient", 640, 380, -1 , -1,Bitor($GUI_SS_DEFAULT_GUI,$WS_CLIPCHILDREN))

$GUI_Indicator = GUICreate ("", 150, 120, 10, 10, BitOR ($WS_CHILD, $WS_DLGFRAME,$WS_EX_TOPMOST),$WS_EX_CLIENTEDGE,$GUI)

GuiSetState(@SW_SHOW,$GUI)

GuiSetState(@SW_SHOW,$GUI_Indicator)

GUISetBkColor (0x00FFFF)

$hWnd = WinGetHandle($GUI_Indicator)

$hGraphic = _GDIPlus_GraphicsCreateFromHWND ($hWnd)

AllThatGoodStuff()

AdlibEnable("test",3000)

GuiRegisterMsg(0x000F,"rePaint")

Do

Until GUIGetMsg() = $GUI_EVENT_CLOSE

Func InitGraphics()

_GDIPlus_Startup ()

$myBlackPen = _GDIPlus_PenCreate(0xFF000000, 1)

EndFunc

Func rePaint($window )

if $window == $hWnd then

AllThatGoodStuff()

EndIf

return $GUI_RUNDEFMSG

EndFunc

Func test()

_WinAPI_InvalidateRect($GUI_Indicator)

_WinAPI_UpdateWindow($GUI)

_WinAPI_UpdateWindow($GUI_Indicator)

EndFunc

Func AllThatGoodStuff()

_GDIPlus_GraphicsDrawString($hGraphic, "hello world",10,10)

EndFunc

Func OnAutoItExit()

_GDIPlus_GraphicsDispose ($hGraphic)

_GDIPlus_Shutdown ()

EndFunc

The adlib function invalidates the child window contents and calls WM_PAINT

Then the child window contents dissappear.

I believe this is what is causing my problem

Edited by matrix200
Link to comment
Share on other sites

Ok forget what I have written in the first two posts :)

After rewriting the whole drawing functions using plain gdi and seeing it didn't help I have a different idea.

Is it possible to consume WM_PAINT event internally?

What I mean is I don't want to rely on internal AuotIt handler regarding these windows.

Anyway I don't have any controls and everything drawn on them is something I draw myself.

Now if I don't return $GUI_RUNDEFMSG my WM_PAINT event gets "stuck"

That is I keep receiving it over and over again and program becomes unresponsive.

Is there a way to have the WM_PAINT event deleted after I have redrawn the window contents?

Link to comment
Share on other sites

Ok problem solved fully :)

The right way to make sure WM_PAINT doesn't get stuck is to call ValidateRect function on the window for which drawing is complete and no additonal paitning is required.

Other things that others might find useful , I do not recommend using GDIplus library at all because it is leaking memory as hell (if you decide to reuse same brushes , pens and other drawing resources and don't want to recreate them for each drawing).

The painting with GDIplus seems to be slower then plain GDI (There was some article I found on the Internet with direct comparisons).

GDIplus created an additional thread inside the program which I find alarming (regular GDI doesn't do that).

Of course GDIplus is fine if you draw a line or two .

But if you decide to use it for something reasonably heavy like the dials (see my dial gauge example script) then GDIplus is probably a bad idea.

And just by the way it seems the native WM_PAINT handler of Autoit is somewhat buggy .

The part that decides which window part is visible and needs to be redrawn anyway.

If you cover your window with winamp or another similar application quite often the window will remain corrupted after internal handler.

That was the problem all along and getting rid of internal WM_PAINT handler is indeed solving all redrawing issues.

Edited by matrix200
Link to comment
Share on other sites

  • 2 years later...

Ok problem solved fully :x

The right way to make sure WM_PAINT doesn't get stuck is to call ValidateRect function on the window for which drawing is complete and no additonal paitning is required.

I am spending hours to find out how to avoid this problem and I can not make a sigle example work ! Could you please post your modified code ?

Thanks !

Laurent

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