Jump to content

How to have a line show over an image in GDI+


Recommended Posts

In my code, the mouse wheel causes the line to move up and down. It does move down to where the picture is, but is not seen there. This can be observed by scrolling down to the picture, and then up again: the line reappears as expected.

How can I get the line to show on the picture? This seems to be a matter of transparency, but I have not found a way of getting the background of $graphLine to be transparent.

The code is now:

#include <ButtonConstants.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
Opt('MustDeclareVars',1)

Global Const $MK_SHIFT = 0x4
Global Const $MK_CONTROL = 0x8

GUIRegisterMsg($WM_MOUSEWHEEL, "WM_MOUSEWHEEL")

Global $gY0,$gY1,$gForm1,$glblLine,$glblPic

main()

Func main()
$gForm1 = GUICreate("Form1", 623, 601, 192, 114)
$glblLine = GUICtrlCreateLabel("", 8, 8, 604, 137)
$glblPic = GUICtrlCreateLabel("", 8, 8, 589, 500)
Local $btn = GUICtrlCreateButton("Rotate", 472, 560, 65, 25)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

    Local $oldY0,$oldY1

    _GDIPlus_Startup()


    Local $h = GUICtrlGetHandle($glblLine)  ; limit graphics to area of $label
    Local $GraphicLine = _GDIPlus_GraphicsCreateFromHWND($h)
    Local $hPen = _GDIPlus_PenCreate(0xFF000000,2)
    Local $image = _GDIPlus_ImageLoadFromFile('H:\a\P5130021.jpg')
    Local $h = GUICtrlGetHandle($glblPic)
    Local $GraphicPic = _GDIPlus_GraphicsCreateFromHWND($h)
    _GDIPlus_GraphicsDrawImage($GraphicPic,$image,0,0)
    $gY0 = 67
    $gY1 = 67

    _GDIPlus_GraphicsClear($GraphicLine,0)
    _GDIPlus_GraphicsDrawLine($GraphicLine, 10, $gY0, 350, $gY1, $hPen)

    ; Loop until the user exits.
    While True
        If $gY0<>$oldY0 Or $gY1<>$oldY1 Then
            _GDIPlus_GraphicsClear($GraphicLine,0xFFD4D0C8)
            _GDIPlus_GraphicsDrawLine($GraphicLine, 10, $gY0, 590, $gY1, $hPen)
            $oldY0 = $gY0
            $oldY1 = $gY1
        Else
            Switch GUIGetMsg()
                Case $GUI_EVENT_CLOSE,$btn
                    Exit
            EndSwitch
        EndIf
    WEnd

    ; Clean up resources
    _GDIPlus_PenDispose($hPen)
    _GDIPlus_GraphicsDispose($GraphicLine)
    _GDIPlus_Shutdown()
EndFunc

Func WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam, $lParam
Local Const $ymax=500
    Local $vec = GUIGetCursorInfo($gForm1)
    If $vec[4] = $glblLine Or $vec[4]=$glblPic Then
        Local $iDelta = BitShift($wParam, 16)   ; positive = up
        Local $iKeys = _WinAPI_LoWord($wParam)
        If BitAND($iKeys,$MK_CONTROL)=$MK_CONTROL Then
            If BitAND($iKeys,$MK_SHIFT)=$MK_SHIFT Then
                ; do nothing
            Else
                If $iDelta > 0 And $gY0>3 Then $gY0 -= 1
                If $iDelta < 0 And $gY0<$ymax Then $gY0 += 1
            EndIf
        Else
            If BitAND($iKeys,$MK_SHIFT)=$MK_SHIFT Then
                If $iDelta > 0 And $gY1>3 Then $gY1 -= 1
                If $iDelta < 0  And $gY1<$ymax Then $gY1 += 1
            Else
                If $iDelta > 0 And $gY0>3 Then $gY0 -= 1
                If $iDelta < 0 And $gY0<$ymax Then $gY0 += 1
                If $iDelta > 0 And $gY1>3 Then $gY1 -= 1
                If $iDelta < 0 And $gY1<$ymax Then $gY1 += 1
            EndIf
        EndIf
    EndIf
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_MOUSEWHEEL

Some other questions:

  • Do I really need GDI+, or is there a simpler way?
  • My code creates Graphics (canvases?) from labels. Is this legitimate?
  • I have found MSDN to be un-helpful in learning GDI+. Is there a better learning tool?
Edited by c.haslam
Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Link to comment
Share on other sites

On 10/9/2017 at 5:21 AM, c.haslam said:

In my code, the mouse wheel causes the line to move up and down. It does move down to where the picture is, but is not seen there. This can be observed by scrolling down to the picture, and then up again: the line reappears as expected.

How can I get the line to show on the picture? This seems to be a matter of transparency, but I have not found a way of getting the background of $graphLine to be transparent.

The code is now:

#include <ButtonConstants.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
Opt('MustDeclareVars',1)

Global Const $MK_SHIFT = 0x4
Global Const $MK_CONTROL = 0x8

GUIRegisterMsg($WM_MOUSEWHEEL, "WM_MOUSEWHEEL")

Global $gY0,$gY1,$gForm1,$glblLine,$glblPic

main()

Func main()
$gForm1 = GUICreate("Form1", 623, 601, 192, 114)
$glblLine = GUICtrlCreateLabel("", 8, 8, 604, 137)
$glblPic = GUICtrlCreateLabel("", 8, 8, 589, 500)
Local $btn = GUICtrlCreateButton("Rotate", 472, 560, 65, 25)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

    Local $oldY0,$oldY1

    _GDIPlus_Startup()


    Local $h = GUICtrlGetHandle($glblLine)  ; limit graphics to area of $label
    Local $GraphicLine = _GDIPlus_GraphicsCreateFromHWND($h)
    Local $hPen = _GDIPlus_PenCreate(0xFF000000,2)
    Local $image = _GDIPlus_ImageLoadFromFile('H:\a\P5130021.jpg')
    Local $h = GUICtrlGetHandle($glblPic)
    Local $GraphicPic = _GDIPlus_GraphicsCreateFromHWND($h)
    _GDIPlus_GraphicsDrawImage($GraphicPic,$image,0,0)
    $gY0 = 67
    $gY1 = 67

    _GDIPlus_GraphicsClear($GraphicLine,0)
    _GDIPlus_GraphicsDrawLine($GraphicLine, 10, $gY0, 350, $gY1, $hPen)

    ; Loop until the user exits.
    While True
        If $gY0<>$oldY0 Or $gY1<>$oldY1 Then
            _GDIPlus_GraphicsClear($GraphicLine,0xFFD4D0C8)
            _GDIPlus_GraphicsDrawLine($GraphicLine, 10, $gY0, 590, $gY1, $hPen)
            $oldY0 = $gY0
            $oldY1 = $gY1
        Else
            Switch GUIGetMsg()
                Case $GUI_EVENT_CLOSE,$btn
                    Exit
            EndSwitch
        EndIf
    WEnd

    ; Clean up resources
    _GDIPlus_PenDispose($hPen)
    _GDIPlus_GraphicsDispose($GraphicLine)
    _GDIPlus_Shutdown()
EndFunc

Func WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam, $lParam
Local Const $ymax=500
    Local $vec = GUIGetCursorInfo($gForm1)
    If $vec[4] = $glblLine Or $vec[4]=$glblPic Then
        Local $iDelta = BitShift($wParam, 16)   ; positive = up
        Local $iKeys = _WinAPI_LoWord($wParam)
        If BitAND($iKeys,$MK_CONTROL)=$MK_CONTROL Then
            If BitAND($iKeys,$MK_SHIFT)=$MK_SHIFT Then
                ; do nothing
            Else
                If $iDelta > 0 And $gY0>3 Then $gY0 -= 1
                If $iDelta < 0 And $gY0<$ymax Then $gY0 += 1
            EndIf
        Else
            If BitAND($iKeys,$MK_SHIFT)=$MK_SHIFT Then
                If $iDelta > 0 And $gY1>3 Then $gY1 -= 1
                If $iDelta < 0  And $gY1<$ymax Then $gY1 += 1
            Else
                If $iDelta > 0 And $gY0>3 Then $gY0 -= 1
                If $iDelta < 0 And $gY0<$ymax Then $gY0 += 1
                If $iDelta > 0 And $gY1>3 Then $gY1 -= 1
                If $iDelta < 0 And $gY1<$ymax Then $gY1 += 1
            EndIf
        EndIf
    EndIf
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_MOUSEWHEEL

Some other questions:

  • Do I really need GDI+, or is there a simpler way?
  • My code creates Graphics (canvases?) from labels. Is this legitimate?
  • I have found MSDN to be un-helpful in learning GDI+. Is there a better learning tool?

 

I used backdraw method to avoid flickering. Check this out:

#include <ButtonConstants.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
Opt('MustDeclareVars',1)

Global Const $MK_SHIFT = 0x4
Global Const $MK_CONTROL = 0x8

GUIRegisterMsg($WM_MOUSEWHEEL, "WM_MOUSEWHEEL")

Global $gY0,$gY1,$gForm1,$glblLine,$glblPic,$iLW,$iLH,$iW,$iH

main()

Func main()
$gForm1 = GUICreate("Form1", 623, 601, 192, 114)
$glblLine = GUICtrlCreateLabel("", 8, 8, 604, 137)
$iLW = 589
$iLH = 500
$glblPic = GUICtrlCreateLabel("", 8, 8, $iLW, $iLH)
Local $btn = GUICtrlCreateButton("Rotate", 472, 560, 65, 25)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

    Local $oldY0,$oldY1

    _GDIPlus_Startup()


    Local $h = GUICtrlGetHandle($glblLine)  ; limit graphics to area of $label
    Local $hPen = _GDIPlus_PenCreate(0xFF000000,2)
    Local $image = _GDIPlus_ImageLoadFromFile('c:\Program Files (x86)\AutoIt3\Examples\GUI\msoobe.jpg')
    Local $h = GUICtrlGetHandle($glblPic)
    Local $GraphicPic = _GDIPlus_GraphicsCreateFromHWND($h)
    $gY0 = 67
    $gY1 = 67
    $iW = _GDIPlus_ImageGetWidth($image)
    $iH = _GDIPlus_ImageGetHeight($image)
    Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH)
    Local $hCanvas = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    _GDIPlus_GraphicsDrawImageRect($hCanvas, $image, 0, 0, $iW, $iH)
    _GDIPlus_GraphicsDrawLine($hCanvas, 10, $gY0, 350, $gY1, $hPen)

    ; Loop until the user exits.
    While True
        If $gY0<>$oldY0 Or $gY1<>$oldY1 Then
            _GDIPlus_GraphicsClear($hCanvas,0xFFD4D0C8)
            _GDIPlus_GraphicsDrawImageRect($hCanvas, $image, ($iLW - $iW) / 2, ($iLH - $iH) / 2, $iW, $iH)
            _GDIPlus_GraphicsDrawLine($hCanvas, 10, $gY0, 590, $gY1, $hPen)
            _GDIPlus_GraphicsDrawImageRect($GraphicPic, $hBitmap, 0, 0, $iW, $iH)
            $oldY0 = $gY0
            $oldY1 = $gY1
        Else
            Switch GUIGetMsg()
                Case $GUI_EVENT_CLOSE,$btn
                    Exit
            EndSwitch
        EndIf
    WEnd

    ; Clean up resources
    _GDIPlus_ImageDispose($hCanvas)
    _GDIPlus_ImageDispose($image)
    _GDIPlus_ImageDispose($hBitmap)
    _GDIPlus_PenDispose($hPen)
    _GDIPlus_GraphicsDispose($GraphicPic)
    _GDIPlus_Shutdown()
EndFunc

Func WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam, $lParam
Local Const $ymax=500
    Local $vec = GUIGetCursorInfo($gForm1)
    If $vec[4] = $glblLine Or $vec[4]=$glblPic Then
        Local $iDelta = BitShift($wParam, 16)   ; positive = up
        Local $iKeys = _WinAPI_LoWord($wParam)
        If BitAND($iKeys,$MK_CONTROL)=$MK_CONTROL Then
            If BitAND($iKeys,$MK_SHIFT)=$MK_SHIFT Then
                ; do nothing
            Else
                If $iDelta > 0 And $gY0>3 Then $gY0 -= 1
                If $iDelta < 0 And $gY0<$ymax Then $gY0 += 1
            EndIf
        Else
            If BitAND($iKeys,$MK_SHIFT)=$MK_SHIFT Then
                If $iDelta > 0 And $gY1>3 Then $gY1 -= 1
                If $iDelta < 0  And $gY1<$ymax Then $gY1 += 1
            Else
                If $iDelta > 0 And $gY0>3 Then $gY0 -= 1
                If $iDelta < 0 And $gY0<$ymax Then $gY0 += 1
                If $iDelta > 0 And $gY1>3 Then $gY1 -= 1
                If $iDelta < 0 And $gY1<$ymax Then $gY1 += 1
            EndIf
        EndIf
    EndIf
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_MOUSEWHEEL

You cannot delete the canvas and expect that the image is still on the canvas. If you delete the canvas you have to draw everything again.

I learned 90% GDI+ from this forum. There are plenty of examples - just search for it ;). Imho MSDN is not the best starting point to learn GDI+, more for advanced skills.

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

Many thanks for your help. I have spent several hours examining the code on this forum. It helped a bit, but your rewrite of my code really helps.

I tried changing the file loaded to a .jpg which is 1024 x 768. Only the centre of the picture showed.

I changed a line in the message loop to

_GDIPlus_GraphicsDrawImageRect($hCanvas, $image, 0,0, $iLW, $iLH)

The whole picture then showed.

It looks to me as though the lines

_GDIPlus_GraphicsDrawImageRect($hCanvas, $image, 0, 0, $iW, $iH)
    _GDIPlus_GraphicsDrawLine($hCanvas, 10, $gY0, 350, $gY1, $hPen)

before the message loop are not needed. Am I correct?

I have also changed the second argument to _GDIPlus_GraphicsClear(). Zero seems to work. (0xD4D0C8 is the default for a GUI in Koda.)

With this script running from SciTE, I switched to another application which was full screen. When I switched back, the dialog was empty except for the Rotate button. Rotating the mouse wheel brought the picture and line back.

I found WM_PAINT code on the forum. The canvas then repainted.

I no longer need $lblLine.

My code now is:

#include <ButtonConstants.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
Opt('MustDeclareVars',1)

Global Const $MK_SHIFT = 0x4
Global Const $MK_CONTROL = 0x8

GUIRegisterMsg($WM_MOUSEWHEEL, "WM_MOUSEWHEEL")
GUIRegisterMsg($WM_PAINT,'WM_PAINT')

Global $gY0,$gY1,$gForm1,$glblPic,$iLW,$iLH,$iW,$iH
Global $ghCanvas,$gImage,$ghPen,$gGraphicPic,$ghBitmap
main()

Func main()
$gForm1 = GUICreate("Form1", 623, 601, 192, 114)
$iLW = 589
$iLH = 500
$glblPic = GUICtrlCreateLabel("", 8, 8, $iLW, $iLH)
Local $btn = GUICtrlCreateButton("Rotate", 472, 560, 65, 25)
GUISetState(@SW_SHOW)

    Local $oldY0,$oldY1

    _GDIPlus_Startup()

    $ghPen = _GDIPlus_PenCreate(0xFF000000,2)
    $gImage = _GDIPlus_ImageLoadFromFile('H:\b\Jag XJR 2001.jpg')
    Local $h = GUICtrlGetHandle($glblPic)
    $gGraphicPic = _GDIPlus_GraphicsCreateFromHWND($h)
    $gY0 = 400
    $gY1 = 400
    $iW = _GDIPlus_ImageGetWidth($gImage)
    $iH = _GDIPlus_ImageGetHeight($gImage)
    $ghBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH)
    $ghCanvas = _GDIPlus_ImageGetGraphicsContext($ghBitmap)

    ; Loop until the user exits.
    While True
        If $gY0<>$oldY0 Or $gY1<>$oldY1 Then
            Paint()
            $oldY0 = $gY0
            $oldY1 = $gY1
        Else
            Switch GUIGetMsg()
                Case $GUI_EVENT_CLOSE,$btn
                    ExitLoop
            EndSwitch
        EndIf
    WEnd

    ; Clean up resources
    _GDIPlus_ImageDispose($ghCanvas)
    _GDIPlus_ImageDispose($gImage)
    _GDIPlus_ImageDispose($ghBitmap)
    _GDIPlus_PenDispose($ghPen)
    _GDIPlus_GraphicsDispose($gGraphicPic)
    _GDIPlus_Shutdown()
EndFunc

Func WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam, $lParam
Local Const $kYmax=$iLH-1,$kDelta=2
    Local $vec = GUIGetCursorInfo($gForm1)
    If $vec[4] = $vec[4]=$glblPic Then
        Local $iDelta = BitShift($wParam, 16)   ; positive = up
        Local $iKeys = _WinAPI_LoWord($wParam)
        If BitAND($iKeys,$MK_CONTROL)=$MK_CONTROL Then
            If BitAND($iKeys,$MK_SHIFT)=$MK_SHIFT Then
                ; do nothing
            Else
                If $iDelta > 0 And $gY0>3 Then $gY0 -= $kDelta
                If $iDelta < 0 And $gY0<$kYmax Then $gY0 += $kDelta
            EndIf
        Else
            If BitAND($iKeys,$MK_SHIFT)=$MK_SHIFT Then
                If $iDelta > 0 And $gY1>3 Then $gY1 -= $kDelta
                If $iDelta < 0  And $gY1<$kYmax Then $gY1 += $kDelta
            Else
                If $iDelta > 0 And $gY0>3 Then $gY0 -= $kDelta
                If $iDelta < 0 And $gY0<$kYmax Then $gY0 += $kDelta
                If $iDelta > 0 And $gY1>3 Then $gY1 -= $kDelta
                If $iDelta < 0 And $gY1<$kYmax Then $gY1 += $kDelta
            EndIf
        EndIf
    EndIf
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_MOUSEWHEEL

Func Paint()
    _GDIPlus_GraphicsClear($ghCanvas,0)
    _GDIPlus_GraphicsDrawImageRect($ghCanvas, $gImage, 0,0, $iLW, $iLH)
    _GDIPlus_GraphicsDrawLine($ghCanvas, 10, $gY0, 590, $gY1, $ghPen)
    _GDIPlus_GraphicsDrawImageRect($gGraphicPic, $ghBitmap, 0, 0, $iW, $iH)
EndFunc

Func WM_PAINT()
    _WinAPI_RedrawWindow($gForm1, 0, 0, $RDW_UPDATENOW)
    Paint()
    _WinAPI_RedrawWindow($gForm1, 0, 0, $RDW_VALIDATE)
EndFunc

Perhaps you would explain backbuffering.

This code is a prototype for a script which annotates photographs: it will be able to straighten them, so level is level: I am often off by about 2 degrees!

It will, I hope, be possible to rotate a jpeg per the angle of the line. More fun! (I may need your help there too.)

Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Link to comment
Share on other sites

Try this:

#include <ButtonConstants.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
Opt('MustDeclareVars',1)

Global Const $MK_SHIFT = 0x4
Global Const $MK_CONTROL = 0x8
Global Const $fPi = ACos(-1), $fPi2 = $fPi / 2, $fRad = 180 / $fPi

GUIRegisterMsg($WM_MOUSEWHEEL, "WM_MOUSEWHEEL")
GUIRegisterMsg($WM_PAINT,'WM_PAINT')

Global $gX0=10,$gX1=580,$gY0,$gY1,$gForm1,$glblPic,$iLW,$iLH,$iW,$iH
Global $ghCanvas,$ghImage,$ghPen,$gGraphicPic,$ghBitmap,$ghMatrix,$ghImageClone,$ghGfxClone
main()

Func main()
$gForm1 = GUICreate("Form1", 623, 601, 192, 114)
$iLW = 589
$iLH = 500
$glblPic = GUICtrlCreateLabel("", 8, 8, $iLW, $iLH)
Local $btn = GUICtrlCreateButton("Rotate", 472, 560, 65, 25)
GUISetState(@SW_SHOW)

    Local $oldY0,$oldY1,$fAngle

    _GDIPlus_Startup()

    $ghPen = _GDIPlus_PenCreate(0xFF000000,2)
    $ghImage = _GDIPlus_ImageLoadFromFile('H:\b\Jag XJR 2001.jpg')
    Local $h = GUICtrlGetHandle($glblPic)
    $gGraphicPic = _GDIPlus_GraphicsCreateFromHWND($h)
    $gY0 = 400
    $gY1 = 400
    $iW = _GDIPlus_ImageGetWidth($ghImage)
    $iH = _GDIPlus_ImageGetHeight($ghImage)
    $ghBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH)
    $ghCanvas = _GDIPlus_ImageGetGraphicsContext($ghBitmap)
    $ghMatrix = _GDIPlus_MatrixCreate()
    ; Loop until the user exits.
    While True
        If $gY0<>$oldY0 Or $gY1<>$oldY1 Then
            Paint()
            $oldY0 = $gY0
            $oldY1 = $gY1
        Else
            Switch GUIGetMsg()
                Case $GUI_EVENT_CLOSE
                    ExitLoop
                Case $btn
                    $ghImageClone=_GDIPlus_BitmapCreateFromScan0($iW, $iH)
                    $ghGfxClone=_GDIPlus_ImageGetGraphicsContext($ghImageClone)
                    _GDIPlus_MatrixTranslate($ghMatrix, $iW/2, $iH/2)
                    _GDIPlus_MatrixRotate($ghMatrix, Angle($gY1-$gY0, $gX1-$gX0))
                    _GDIPlus_MatrixTranslate($ghMatrix, -$iW/2, -$iH/2)
                    _GDIPlus_GraphicsSetTransform($ghGfxClone, $ghMatrix)
                    _GDIPlus_GraphicsDrawImageRect($ghGfxClone,$ghImage,0,0,$iW,$iH)
                    _GDIPlus_GraphicsDispose($ghGfxClone)
                    $ghGfxClone=_GDIPlus_ImageGetGraphicsContext($ghImage)
                    _GDIPlus_GraphicsClear($ghImage)
                    _GDIPlus_GraphicsDrawImageRect($ghGfxClone,$ghImageClone,0,0,$iW,$iH)
                    _GDIPlus_GraphicsDispose($ghGfxClone)
                    _GDIPlus_ImageDispose($ghImageClone)
                    Paint()
            EndSwitch
        EndIf
    WEnd

    ; Clean up resources
    _GDIPlus_MatrixDispose($ghMatrix)
    _GDIPlus_ImageDispose($ghCanvas)
    _GDIPlus_ImageDispose($ghImage)
    _GDIPlus_ImageDispose($ghBitmap)
    _GDIPlus_PenDispose($ghPen)
    _GDIPlus_GraphicsDispose($gGraphicPic)
    _GDIPlus_Shutdown()
EndFunc

Func WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam, $lParam
    Local Const $kYmax=$iLH-1,$kDelta=2
    Local $vec = GUIGetCursorInfo($gForm1)
    If $vec[4] = $vec[4]=$glblPic Then
        Local $iDelta = BitShift($wParam, 16)   ; positive = up
        Local $iKeys = _WinAPI_LoWord($wParam)
        If BitAND($iKeys,$MK_CONTROL)=$MK_CONTROL Then
            If BitAND($iKeys,$MK_SHIFT)=$MK_SHIFT Then
                ; do nothing
            Else
                If $iDelta > 0 And $gY0>3 Then $gY0 -= $kDelta
                If $iDelta < 0 And $gY0<$kYmax Then $gY0 += $kDelta
            EndIf
        Else
            If BitAND($iKeys,$MK_SHIFT)=$MK_SHIFT Then
                If $iDelta > 0 And $gY1>3 Then $gY1 -= $kDelta
                If $iDelta < 0  And $gY1<$kYmax Then $gY1 += $kDelta
            Else
                If $iDelta > 0 And $gY0>3 Then $gY0 -= $kDelta
                If $iDelta < 0 And $gY0<$kYmax Then $gY0 += $kDelta
                If $iDelta > 0 And $gY1>3 Then $gY1 -= $kDelta
                If $iDelta < 0 And $gY1<$kYmax Then $gY1 += $kDelta
            EndIf
        EndIf
    EndIf
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_MOUSEWHEEL

Func Paint()
    _GDIPlus_GraphicsClear($ghCanvas,0)
    _GDIPlus_GraphicsDrawImageRect($ghCanvas, $ghImage, 0,0, $iLW, $iLH)
    _GDIPlus_GraphicsDrawLine($ghCanvas, $gX0, $gY0, $gX1, $gY1, $ghPen)
    _GDIPlus_GraphicsDrawImageRect($gGraphicPic, $ghBitmap, 0, 0, $iW, $iH)
EndFunc

Func WM_PAINT()
    _WinAPI_RedrawWindow($gForm1, 0, 0, $RDW_UPDATENOW)
    Paint()
    _WinAPI_RedrawWindow($gForm1, 0, 0, $RDW_VALIDATE)
EndFunc

Func Angle($y, $x) ;return value is in degree
    Local Const $fPi = ACos(-1), $fPi2 = ACos(-1) / 2, $fRad = 180 / $fPi
    Switch $x
        Case ($x > 0)
            Return ATan($y / $x) * $fRad
        Case ($x < 0 And $y >= 0)
            Return ATan($y / $x + $fPi) * $fRad
        Case ($x < 0 And $y < 0)
            Return ATan($y / $x - $fPi) * $fRad
        Case ($x = 0 And $y > 0)
            Return $fPi2 * $fRad
        Case ($x = 0 And $y < 0)
            Return -$fPi2 * $fRad
        Case ($x = 0 And $y = 0)
            Return 0
    EndSwitch
EndFunc

 

Backbuffering means that you draw everything to the bitmap first before you copy the bitmap to the visible canvas (graphic) to avoid flickering.

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

Thank you. Works fine, except I needed to change one line which is now

_GDIPlus_MatrixRotate($ghMatrix, -Angle($gY1-$gY0, $gX1-$gX0))

Added the minus sign.

I also added

$gy0 = 400
$gy1 = 400

after

_GDIPlus_ImageDispose($ghImageClone)

so the line returns to horizontal.

I will be studying your code. Perhaps one day I will master GDI+!

Edit: I made one other change: in Angle() I changed

Switch $x

to

Switch True

 

Edited by c.haslam
Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Link to comment
Share on other sites

I am looking at the Paint() function. I see two calls to _GDIPlus_GraphicsDrawImageRect():

_GDIPlus_GraphicsDrawImageRect($ghCanvas, $ghImage, 0,0, $iLW, $iLH)

and

_GDIPlus_GraphicsDrawImageRect($gGraphicPic, $ghBitmap, 0, 0, $iW, $iH)

$ghCanvas was returned by   _GDIPlus_ImageGetGraphicsContext(), so appears to a bitmap (per the Help for this function), and $ghImage was returned by  _GDIPlus_ImageLoadFromFile() so appears also to be a bitmap. So _GDIPlus_GraphicsDrawImageRect() is here copying from bitmap $ghImage to bitmap $ghCanvas. (0 .. $iLW, 0 .. $iLH) are copied, i.e. the whole of the loaded jpeg.

Then _GDIPlus_GraphicsDrawLine() draws to $ghCanvas, so both the picture and the line are in bitmap $ghCanvas.

Then _GDIPlus_GraphicsDrawImageRect() copies bitmap $gBitmap to $GraphicPic which the Help for _GDIPlus_GraphicsCreateFromHWND() says returns a graphics object.

So in one case the destination is a bitmap and in the other case it is a graphics object.

So I am confused! Please explain.

Is $ghGfxClone a Graphics object or is it a Graphics context? The Help (and most likely MSDN) says that the parameter of _GDIPlus_GraphicsDispose() is a Graphics object, but GDIPlus_ImageGetGraphicsContext($ghImageClone), per the Help, "Get the graphics context of the image"?

Or does a Graphics object have a context?

Edited by c.haslam
Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

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

×
×
  • Create New...