Rotating a Graphics Path in GDI+
Posted: 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.
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
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
}
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