Rotating a Graphics Path in GDI+ Topic is solved

Get help with using AutoHotkey and its commands and hotkeys
User avatar
RazorHalo
Posts: 32
Joined: 21 Dec 2015, 21:23

Rotating a Graphics Path in GDI+

09 Apr 2019, 20:02

Been stumped on this for a few days now, I'm just trying to rotate a Graphics path in GDI+.

I can't seem to do it. I know I can use Gdip_RotateWorldTransform but that rotates all my graphics paths. I just want to rotate one.

I have studied the MSDN docs on the Graphics Transform methods and think that I need to use a Transform function on the graphics path with a Rotate Matrix.
https://docs.microsoft.com/en-us/windows/desktop/api/gdiplusmatrix/nf-gdiplusmatrix-matrix-matrix(constmatrix_)
https://docs.microsoft.com/en-us/windows/desktop/api/gdiplusmatrix/nf-gdiplusmatrix-matrix-rotate
https://docs.microsoft.com/en-us/windows/desktop/api/Gdipluspath/nf-gdipluspath-graphicspath-transform

I have added the those functions to my Gdip_All.ahk but seem to get stuck with creating the matrix. When I create the matrix it seems like I get a pointer to the matrix, but when I try to do anything with it I keep getting a result of 2 - (Invalid Parameter).

Could anyone see what I might be missing or doing wrong and point me in the right direction.

My sample script is as follows. put in your path to gdip_all.ahk.

Code: Select all

#NoEnv
#SingleInstance Force
SetWorkingDir %A_ScriptDir%
SetBatchLines -1

;Need to include your path to Gdip
#Include Gdip_all.ahk

Gui 1: +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs
hGui := WinExist()
Gui 1: Show, NA
w:= 500, h:= 500

pToken := Gdip_Startup()
hbm := CreateDIBSection(w, h), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc), Gdip_SetSmoothingMode(G, 4)

;Create a GraphicsPath
pPath := Gdip_CreatePath() ; creates a Path (GraphicsPath object)

;Add figure to path
Gdip_StartPathFigure(pPath) ; starts a new figure in this Path
Gdip_AddPathLine(pPath, 110,95, 220,95) ; adds a line to the current figure of this path
Gdip_AddPathLine(pPath, 220,95, 220,400) ; adds a line to the current figure of this path
Gdip_AddPathLine(pPath, 220,400, 100,380) ; adds a line to the current figure of this path
Gdip_AddPathLine(pPath, 100,380, 110,95) ; adds a line to the current figure of this path
Gdip_ClosePathFigure(pPath) ; closes the current figure of this path

;Create a Matrix
pMatrix := Gdip_CreateMatrix()

If (pMatrix) {

	rValue1 := Gdip_RotateMatrix(pMatrix, 30)
	rValue2 := Gdip_TransformPath(pPath, pMatrix)
	
	;Show results of rotating the matrix and applying the transform
	Msgbox % rValue1 ", " rValue2

} Else {
	Msgbox "Error Creating Matrix"
}


pPen := Gdip_CreatePen(0xffa5a5a5, 5)
Gdip_DrawPath(G, pPen, pPath) ; draw outline
Gdip_DeletePen(pPen)

UpdateLayeredWindow(hGui, hdc, (A_ScreenWidth-w)//2, (A_ScreenHeight-h)//2, w, h)
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
Gdip_DeleteGraphics(G)
Gdip_Shutdown(pToken)
return


Esc::ExitApp

; #################  Added Matrix Functions to Rotate GraphicsPath

Gdip_RotateMatrix(pMatrix, Angle, MatrixOrder=0)
{
   return DllCall("gdiplus\GdipRotateMatrix", A_PtrSize ? "UPtr*" : "UInt*", pMatrix, "Float", Angle, "Int", MatrixOrder)
}

Gdip_TransformPath(pPath, pMatrix)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"

	return DllCall("gdiplus\GdipTransformPath", Ptr, pPath, Ptr, pMatrix)
}


;#####################################################################################
; GraphicsPath functions added by Learning one
;#####################################################################################

; Function Gdip_AddPathBeziers
; Description Adds a sequence of connected Bézier splines to the current figure of this path.
;
; pPath Pointer to the GraphicsPath
; Points the coordinates of all the points passed as x1,y1|x2,y2|x3,y3.....
;
; return status enumeration. 0 = success

; Notes The first spline is constructed from the first point through the fourth point in the array and uses the second and third points as control points. Each subsequent spline in the sequence needs exactly three more points: the ending point of the previous spline is used as the starting point, the next two points in the sequence are control points, and the third point is the ending point.

Gdip_AddPathBeziers(pPath, Points) {
StringSplit, Points, Points, |
VarSetCapacity(PointF, 8*Points0)
Loop, %Points0%
{
StringSplit, Coord, Points%A_Index%, `,
NumPut(Coord1, PointF, 8*(A_Index-1), "float"), NumPut(Coord2, PointF, (8*(A_Index-1))+4, "float")
}
return DllCall("gdiplus\GdipAddPathBeziers", "uint", pPath, "uint", &PointF, "int", Points0)
}

Gdip_AddPathBezier(pPath, x1, y1, x2, y2, x3, y3, x4, y4) { ; Adds a Bézier spline to the current figure of this path
return DllCall("gdiplus\GdipAddPathBezier", "uint", pPath
, "float", x1, "float", y1, "float", x2, "float", y2
, "float", x3, "float", y3, "float", x4, "float", y4)
}

; Function Gdip_AddPathLines
; Description Adds a sequence of connected lines to the current figure of this path.
;
; pPath Pointer to the GraphicsPath
; Points the coordinates of all the points passed as x1,y1|x2,y2|x3,y3.....
;
; return status enumeration. 0 = success

Gdip_AddPathLines(pPath, Points) {
StringSplit, Points, Points, |
VarSetCapacity(PointF, 8*Points0)
Loop, %Points0%
{
StringSplit, Coord, Points%A_Index%, `,
NumPut(Coord1, PointF, 8*(A_Index-1), "float"), NumPut(Coord2, PointF, (8*(A_Index-1))+4, "float")
}
return DllCall("gdiplus\GdipAddPathLine2", "uint", pPath, "uint", &PointF, "int", Points0)
}

Gdip_AddPathLine(pPath, x1, y1, x2, y2) {
return DllCall("gdiplus\GdipAddPathLine", "uint", pPath
, "float", x1, "float", y1, "float", x2, "float", y2)
}

Gdip_AddPathArc(pPath, x, y, w, h, StartAngle, SweepAngle) {
return DllCall("gdiplus\GdipAddPathArc", "uint", pPath, "float", x, "float", y, "float", w, "float", h, "float", StartAngle, "float", SweepAngle)
}

Gdip_AddPathPie(pPath, x, y, w, h, StartAngle, SweepAngle) {
return DllCall("gdiplus\GdipAddPathPie", "uint", pPath, "float", x, "float", y, "float", w, "float", h, "float", StartAngle, "float", SweepAngle)
}

Gdip_StartPathFigure(pPath) { ; Starts a new figure without closing the current figure. Subsequent points added to this path are added to the new figure.
return DllCall("gdiplus\GdipStartPathFigure", "uint", pPath)
}

Gdip_ClosePathFigure(pPath) { ; Closes the current figure of this path.
return DllCall("gdiplus\GdipClosePathFigure", "uint", pPath)
}

; Function Gdip_DrawPath
; Description draws a sequence of lines and curves defined by a GraphicsPath object
;
; pGraphics Pointer to the Graphics of a bitmap
; pPen Pointer to a pen
; pPath Pointer to a Path
;
; return status enumeration. 0 = success

Gdip_DrawPath(pGraphics, pPen, pPath) {
return DllCall("gdiplus\GdipDrawPath", "uint", pGraphics, "uint", pPen, "uint", pPath)
}

Gdip_WidenPath(pPath, pPen, Matrix=0, Flatness=1) { ; Replaces this path with curves that enclose the area that is filled when this path is drawn by a specified pen. This method also flattens the path.
return DllCall("gdiplus\GdipWidenPath", "uint", pPath, "uint", pPen, "uint", Matrix, "float", Flatness)
}

Gdip_ClonePath(pPath) {
DllCall("gdiplus\GdipClonePath", "uint", pPath, "uint*", pPathClone)
return pPathClone
}
I have tried to add functions to get the elements in the matrix and verify the status:
https://docs.microsoft.com/en-us/windows/desktop/api/gdiplusmatrix/nf-gdiplusmatrix-matrix-getelements
https://docs.microsoft.com/en-us/windows/desktop/api/gdiplusmatrix/nf-gdiplusmatrix-matrix-getlaststatus

But keep getting the "Invalid Parameter" code returned. I must be missing some step or doing something wong.

Thanks
-RH
iPhilip
Posts: 459
Joined: 02 Oct 2013, 12:21

Re: Rotating a Graphics Path in GDI+

09 Apr 2019, 21:26

Does this post help?
Windows 10 Pro (64 bit) - AutoHotkey v1.1+ (Unicode 32-bit)
User avatar
RazorHalo
Posts: 32
Joined: 21 Dec 2015, 21:23

Re: Rotating a Graphics Path in GDI+

09 Apr 2019, 22:10

I have read that post. I have searched for quite a while but not found an answer.

That post uses RotateWorldTransfom,which will rotate the entire layered window and all the graphics paths that are drawn on it. I have displayed several shapes with graphics paths and used RotateWorldTransform function without any issues but I only want to rotate one of the graphics paths. Not the entire layer.
User avatar
RazorHalo
Posts: 32
Joined: 21 Dec 2015, 21:23

Re: Rotating a Graphics Path in GDI+  Topic is solved

13 Apr 2019, 00:22

I have figured it out. It turns out I was using A_PtrSize ? "UPtr*" : "UInt*" with the asterisk when it should have been A_PtrSize ? "UPtr" : "UInt"

I have posted the completed Matrix functions and sample script in the GDI+ main thread here
https://www.autohotkey.com/boards/viewtopic.php?f=6&t=6517&p=272419#p272419

Return to “Ask For Help”

Who is online

Users browsing this forum: AHKStudent, barbaque, Bing [Bot], boiler, Chiefkes, Google [Bot], Ian, Jrdixon_, lucasstella, Rafaews, vsub, yuyu and 304 guests