Sign in to follow this  
Followers 0
jtsteffen

GDIPlus_Graphics disapper if window is minimized or moved

4 posts in this topic

#1 ·  Posted (edited)

I have been playing with the Graphics commands of AutoIt and trying to learn how they work. At this point I am working with _GDIPlus_GraphicsFillPolygon command. I have successfully built the array and made the graphic show up on my window. However I have noticed that if another window opens on top of the one with the graphics or if I move the window manually some place where the graphics is off the screen for a bit, when I move the window with the graphics back to the top and in full view, the graphics are either gone or only partially drawn.

Is there any way to keep the graphics displayed on the screen after these events? As for the code, I started with the example code for the _GDIPlus_GraphicsFillPolygon.

#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>

Opt('MustDeclareVars', 1)

_Main()

Func _Main()
    Local $hGUI, $hGraphic, $aPoints[4][2]

    ; Create GUI
    $hGUI = GUICreate("GDI+", 400, 300)
    GUISetState()

    ; Draw a polygon
    _GDIPlus_Startup()
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI)

    $aPoints[0][0] = 3
    $aPoints[1][0] = 150
    $aPoints[1][1] = 150
    $aPoints[2][0] = 200
    $aPoints[2][1] = 100
    $aPoints[3][0] = 250
    $aPoints[3][1] = 150

    MsgBox(4096, "Information", "Fill Polygon")

    _GDIPlus_GraphicsFillPolygon($hGraphic, $aPoints)

    ; Loop until user exits
    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE

    ; Clean up resources
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_Shutdown()

EndFunc   ;==>_Main

To test the problem, you can run that code and then move the window off the screen and then back. The triangle disappears.

I've searched the help and the forum, but haven't seen this particular problem discussed.

Thanks

Edited by jtsteffen

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

I was able to solve the problem by changing the location of the "_GDIPlus_GraphicsFillPolygon($hGraphic, $aPoints)" command to inside the While WEnd loop as shown below. I am not sure if this is the best way to do this, but the drawing is then redrawn every time the loop is run. This seems like a ineffienct use of the coding, but it does work. If anyone has a better way of doing this, I would like to know.

#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>

Opt('MustDeclareVars', 1)

_Main()

Func _Main()
    Local $hGUI, $hGraphic, $aPoints[4][2]

    ; Create GUI
    $hGUI = GUICreate("GDI+", 400, 300)
    GUISetState()

    ; Draw a polygon
    _GDIPlus_Startup()
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI)

    $aPoints[0][0] = 3
    $aPoints[1][0] = 150
    $aPoints[1][1] = 150
    $aPoints[2][0] = 200
    $aPoints[2][1] = 100
    $aPoints[3][0] = 250
    $aPoints[3][1] = 150

    MsgBox(4096, "Information", "Fill Polygon")

    ; Loop until user exits
    Do
        _GDIPlus_GraphicsFillPolygon($hGraphic, $aPoints)
    Until GUIGetMsg() = $GUI_EVENT_CLOSE

    ; Clean up resources
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_Shutdown()

EndFunc   ;==>_Main
Edited by jtsteffen

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

You must simply redraw the graphics when Windows tell you to.

Simple examples based on _GDIPlus_GraphicsFillPolygon example=

#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>

Opt('MustDeclareVars', 1)

Global $hGraphic, $aPoints[4][2]

_Main()

Func _Main()
    Local $hGUI

    ; Create GUI
    $hGUI = GUICreate("GDI+", 400, 300)
    GUISetState()

    ; Draw a polygon
    _GDIPlus_Startup()
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI)

    $aPoints[0][0] = 3
    $aPoints[1][0] = 150
    $aPoints[1][1] = 150
    $aPoints[2][0] = 200
    $aPoints[2][1] = 100
    $aPoints[3][0] = 250
    $aPoints[3][1] = 150

    MsgBox(4096, "Information", "Fill Polygon")
    GUIRegisterMsg(0x000F, "_WM_PAINT") ;$WM_PAINT

    _GDIPlus_GraphicsFillPolygon($hGraphic, $aPoints)

    ; Loop until user exits
    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE

    ; Clean up resources
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_Shutdown()

EndFunc   ;==>_Main

Func _WM_PAINT()
    _GDIPlus_GraphicsFillPolygon($hGraphic, $aPoints)
EndFunc

Edit: And if you are interested, there's a GUIRegisterMsg Tutorial on the wiki.

Edited by AdmiralAlkex

Share this post


Link to post
Share on other sites

If you don't like the WM_PAINT approach then you can use a pic which is kept refeshed by Windows

#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>

Opt('MustDeclareVars', 1)

Global   $Pic

Global $hGui
_Main()

Func _Main()


    ; Create GUI
    $hGui = GUICreate("GDI+ draw to Pic", 400, 300)
    $Pic = GUICtrlCreatePic("", 0, 0, 400, 300)
    GUISetState()

   
    _SetPic($hGui, ControlGetHandle($hGui, "", $Pic))

    ; Loop until user exits
    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE


EndFunc   ;==>_Main

Func _SetPic($hWnd, $hPic )
    Local $aBmp, $hbmp,$MainImage, $MainGraphic, $hGraphic, $aPoints[4][2]
    Const $IMAGE_BITMAP = 0
    Const $STM_SETIMAGE = 0x0172
     _GDIPlus_Startup()
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd)

    $MainImage = _GDIPlus_BitmapCreateFromGraphics(400, 300, $hGraphic)
    ;_GDIPlus_BitmapDispose($MainImage)
    $MainGraphic = _GDIPlus_ImageGetGraphicsContext($MainImage)
    _GDIPlus_GraphicsClear($MainGraphic, 0x5577AA);set th ebackground col
 ; Draw a polygon
    $aPoints[0][0] = 3
    $aPoints[1][0] = 150
    $aPoints[1][1] = 150
    $aPoints[2][0] = 200
    $aPoints[2][1] = 100
    $aPoints[3][0] = 250
    $aPoints[3][1] = 150

    MsgBox(4096, "Information", "Fill Polygon")

    _GDIPlus_GraphicsFillPolygon($MainGraphic, $aPoints)

    $hbmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($MainImage)
    $aBmp = DllCall("user32.dll", "hwnd", "SendMessage", "hwnd", $hPic, "int", $STM_SETIMAGE, "int", $IMAGE_BITMAP, "int", $hbmp)
    If $aBmp[0] <> 0 Then _WinAPI_DeleteObject($aBmp[0])
    _WinAPI_DeleteObject($hbmp)

      ; Clean up resources
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_GraphicsDispose($MainImage)
    _GDIPlus_GraphicsDispose($MainGraphic)
    _GDIPlus_Shutdown()

EndFunc   ;==>_refreshPic

;no WM_PAINT!

Using WM_PAINT is not ideal. It's faster than setting the image for a pic I think, but when you drag things over the graphic the repainting can be annoyingly slow and sometimes it never gets finished correctly leaving unsightly gaps. That's my experiance anyway. On th eother hand what I showed is a little bit more complicated.


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

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  
Followers 0