Jump to content

GDIplus problem


Wooltown
 Share

Recommended Posts

When I change to another window and back again, the graphics is gone, for example I used the example in the helpfile.

_GDIPlus_GraphicsDrawCurve

Got a tip to use WM_PAINT and GUIRegisterMsg to redraw the graphics, but no success, I have searched the helpfile and on MSDN, anyone that can help me ?

Look at attached file.

Running Beta 3.2.9.8 on Windows 2000 SP4

Link to comment
Share on other sites

I have not latest beta instaled so I can't test it.

I have installed latest beta now and there are problems with this my script:

It shows Fatal Error: AVector: []: Out of bounds. (Subscript used with non-Array variable.<_< at Return in:

Func _GDIPlus_PenCreate($iARGB = 0xFF000000, $nWidth = 1, $iUnit = 2)
    Local $iWidth, $aResult

    $iWidth = _WinAPI_FloatToInt ($nWidth)
    $aResult = DllCall($ghGDIPDll, "int", "GdipCreatePen1", "int", $iARGB, "int", $iWidth, "int", $iUnit, "int*", 0)
    Return SetError($aResult[0], 0, $aResult[4])
EndFunc  ;==>_GDIPlus_PenCreate

I'm running 3.2.9.8 on WINXP.

#include <GuiConstants.au3>
#include <GDIPlus.au3>

Local $hGUI, $hWnd, $hGraphic, $aPoints[5][2]

$hGUI = GUICreate("GDI+", 400, 300)
GUIRegisterMsg($WM_PAINT, "MY_WM_PAINT")
GUISetState()

_GDIPlus_Startup ()
$hGraphic = _GDIPlus_GraphicsCreateFromHWND ($hGUI)

$aPoints[0][0] = 4
$aPoints[1][0] = 0
$aPoints[1][1] = 100
$aPoints[2][0] = 50
$aPoints[2][1] = 50
$aPoints[3][0] = 100
$aPoints[3][1] = 100
$aPoints[4][0] = 150
$aPoints[4][1] = 50

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

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

Func MY_WM_PAINT($hwnd, $msg, $wparam, $lparam)
    _GDIPlus_GraphicsDrawCurve ($hGraphic, $aPoints)
EndFunc

EDIT: fixed header of Func MY_WM_PAINT($hwnd, $msg, $wparam, $lparam)

Edited by Zedna
Link to comment
Share on other sites

I made modification but with no success too:

This runs without errors but curve is not painted and form couldn't be closed.

#include <GuiConstants.au3>
#include <GDIPlus.au3>

Local $hGUI, $hWnd, $hGraphic, $aPoints[5][2]

$hGUI = GUICreate("GDI+", 400, 300)
GUIRegisterMsg($WM_PAINT, "MY_WM_PAINT")
GUISetState()

$aPoints[0][0] = 4
$aPoints[1][0] = 0
$aPoints[1][1] = 100
$aPoints[2][0] = 50
$aPoints[2][1] = 50
$aPoints[3][0] = 100
$aPoints[3][1] = 100
$aPoints[4][0] = 150
$aPoints[4][1] = 50

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

Func MY_WM_PAINT()
    _GDIPlus_Startup ()
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND ($hGUI)

    _GDIPlus_GraphicsDrawCurve ($hGraphic, $aPoints)

    ; Clean up resources
    _GDIPlus_GraphicsDispose ($hGraphic)
    _GDIPlus_Shutdown ()
EndFunc
Link to comment
Share on other sites

Here is third version which works.

But form can't be closed.

EDIT:

I forgot "Return $GUI_RUNDEFMSG"

Now it's fully working

#include <GuiConstants.au3>
#include <GDIPlus.au3>

Local  $hGUI,  $hWnd,  $hGraphic,  $aPoints[5][2]

$aPoints[0][0] =  4
$aPoints[1][0] =  0
$aPoints[1][1] =  100
$aPoints[2][0] =  50
$aPoints[2][1] =  50
$aPoints[3][0] =  100
$aPoints[3][1] =  100
$aPoints[4][0] =  150
$aPoints[4][1] =  50

$hGUI =  GUICreate("GDI+",  400,  300)

_GDIPlus_Startup  ()
$hGraphic = _GDIPlus_GraphicsCreateFromHWND  ($hGUI)

GUIRegisterMsg($WM_PAINT,  "MY_WM_PAINT")
GUISetState()

While 1
    $msg = GuiGetMsg()
    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
WEnd

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

Func MY_WM_PAINT($hwnd,  $msg,  $wparam,  $lparam)
    _GDIPlus_GraphicsDrawCurve  ($hGraphic,  $aPoints)
        Return $GUI_RUNDEFMSG
EndFunc

EDIT:

I noticed that Do Until has 100% CPU usage, so optimized version of main loop is here

;~ Do
;~ Until  GUIGetMsg() =  $GUI_EVENT_CLOSE

While 1
    $msg = GuiGetMsg()
    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
WEnd
Edited by Zedna
Link to comment
Share on other sites

#include <GuiConstants.au3>
#include <GDIPlus.au3>
Opt('MustDeclareVars', 1)


Global $hGUI, $hWnd, $hGraphic, $aPoints[5][2]

; Create GUI
$hGUI = GUICreate("GDI+", 400, 300)
$hWnd = WinGetHandle("GDI+")
; Draw a cardinal spline
_GDIPlus_Startup ()
$hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd)
$aPoints[0][0] = 4
$aPoints[1][0] = 0
$aPoints[1][1] = 100
$aPoints[2][0] = 50
$aPoints[2][1] = 50
$aPoints[3][0] = 100
$aPoints[3][1] = 100
$aPoints[4][0] = 150
$aPoints[4][1] = 50
;~ _GDIPlus_GraphicsDrawCurve ($hGraphic, $aPoints)

GUIRegisterMsg($WM_PAINT, "MY_WM_PAINT")
GUISetState()
; Loop until user exits
While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop
    EndSwitch
WEnd

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

Func MY_WM_PAINT($hwnd, $msg, $wparam, $lparam)
    _GDIPlus_GraphicsDrawCurve($hGraphic, $aPoints)
    Return $GUI_RUNDEFMSG
EndFunc

Exit

Add a "Return $GUI_RUNDEFMSG" to GuiRegisterMsg function. There is a bug with using functions inside msg handler function, which makes it not to return properly, and it's still not fixed. So it's a good idea to explicitly state the default return when you want so.

This will solve high CPU usage and GUI not responding issue.

"be smart, drink your wine"

Link to comment
Share on other sites

Add a "Return $GUI_RUNDEFMSG" to GuiRegisterMsg function. There is a bug with using functions inside msg handler function, which makes it not to return properly, and it's still not fixed. So it's a good idea to explicitly state the default return when you want so.

This will solve high CPU usage and GUI not responding issue.

You are right. I forgot "Return $GUI_RUNDEFMSG"

Thanks siao!

Link to comment
Share on other sites

One BIG note:

When you need painting over some other controls in GUI (for example picture control) then this will not work

because code in WM_PAINT is executed before internal WM_PAINT (and not after).

If somebody know how to do such painting in WM_PAINT over picture control in GUI, please tell me.

In mentioned BlackJack I did it by copying whole content of GUI into memory bitmap then painted my graphic at memory bitmap and

in the end BitBlt from memory bitmap onto visible GUI.

I would be happy If there is some more elegant way.

EDIT: Here is link to BlackJack

Edited by Zedna
Link to comment
Share on other sites

I would be happy If there is some more elegant way.

The easiest way probably would be this:

#include <GuiConstants.au3>
#include <GDIPlus.au3>
Opt('MustDeclareVars', 0)
Global $hGUI, $hWnd, $hGraphic, $aPoints[5][2]

; Create GUI
$hGUI = GUICreate("GDI+", 400, 300)
$cPic = GUICtrlCreatePic(@Systemdir & "\oobe\images\mslogo.jpg", 200,150, 200,150)
$hPic = GUICtrlGetHandle($cPic)
; Draw a cardinal spline
_GDIPlus_Startup()
$hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI)
$hGraphic2 = _GDIPlus_GraphicsCreateFromHWND($hPic)
;~ cw(Hex($hGraphic2))

$aPoints[0][0] = 4
$aPoints[1][0] = 0
$aPoints[1][1] = 100
$aPoints[2][0] = 50
$aPoints[2][1] = 50
$aPoints[3][0] = 100
$aPoints[3][1] = 100
$aPoints[4][0] = 150
$aPoints[4][1] = 50
;~ _GDIPlus_GraphicsDrawCurve ($hGraphic, $aPoints)

GUIRegisterMsg($WM_PAINT, "MY_WM_PAINT")
GUISetState()
; Loop until user exits
While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop
    EndSwitch
WEnd

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

Func MY_WM_PAINT($hWnd, $Msg, $wParam, $lParam)
    _GDIPlus_GraphicsDrawCurve($hGraphic, $aPoints)
    _WinAPI_RedrawWindow($hPic, 0, 0, $RDW_UPDATENOW) ;force redraw of pic
    _GDIPlus_GraphicsDrawCurve($hGraphic2, $aPoints) ;then draw your stuff on top
    _WinAPI_RedrawWindow($hPic, 0, 0, $RDW_VALIDATE) ;then force no-redraw of pic
    Return $GUI_RUNDEFMSG
EndFunc

Exit
Edited by Siao

"be smart, drink your wine"

Link to comment
Share on other sites

The easiest way probably would be this:

Func MY_WM_PAINT($hWnd, $Msg, $wParam, $lParam)
    _GDIPlus_GraphicsDrawCurve($hGraphic, $aPoints)
    _WinAPI_RedrawWindow($hPic, 0, 0, $RDW_UPDATENOW) ;force redraw of pic
    _GDIPlus_GraphicsDrawCurve($hGraphic2, $aPoints) ;then draw your stuff on top
    _WinAPI_RedrawWindow($hPic, 0, 0, $RDW_VALIDATE) ;then force no-redraw of pic
    Return $GUI_RUNDEFMSG
EndFuncoÝ÷ Ûú®¢×©ä³}÷ß}÷Ý8b²+D@ë-+(®·¶*'~*ì´`È>[¬¶©',¶°
êïz+'¢ÙÞy×jëh×6Func MY_WM_PAINT($hWnd, $Msg, $wParam, $lParam)
;    _GDIPlus_GraphicsDrawCurve($hGraphic, $aPoints)
    _WinAPI_RedrawWindow($hPic, 0, 0, $RDW_UPDATENOW) ;force redraw of pic
    _GDIPlus_GraphicsDrawCurve($hGraphic2, $aPoints) ;then draw your stuff on top
    _WinAPI_RedrawWindow($hPic, 0, 0, $RDW_VALIDATE) ;then force no-redraw of pic
    Return $GUI_RUNDEFMSG
EndFunc
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...