Re: GDI+ standard library 1.45 by tic
Posted: 13 Apr 2019, 01:39
@RazorHalo
As posted, the sample script generates an error.
As posted, the sample script generates an error.
Let's help each other out
https://www.autohotkey.com/boards/
What is the error your getting?As posted, the sample script generates an error.
@RazorHaloRazorHalo wrote: ↑13 Apr 2019, 12:01@iPhilipWhat is the error your getting?As posted, the sample script generates an error.
I'm using the Gdip_All.ahk file from the first post of this thread and only the functions defined within the sample script itself as far as I can tell.
On my system it generates a Gui with a rotating square in the center. Ahkx64 and Windows 10. I do notice when I try to run it on x32 it just has a blank Gui. I guess there is a function in there somewhere missing the compatibility...
Code: Select all
---------------------------
Rotate.ahk
---------------------------
Error: Could not create window.
Line#
2708: char_count := DllCall("MultiByteToWideChar", "uint", Encoding, "uint", 0, "uint", Address, "int", Length, "uint", &String, "int", char_count * 2)
2709: String := StrGetB(&String, char_count, 1200)
2710: }
2712: Return,String
2713: }
009: Gui,Mapper: New,hWndhMap -DPIScale +OwnDialogs
010: Gui,Show,NA w600 h600,Mapper
---> 012: Gui,1: +E0x80000 +LastFound -Caption -DPIScale +ParentMapper
013: hGui := WinExist()
014: Gui,1: Show,NA
015: w:= A_ScreenWidth, h:= A_ScreenHeight
017: pToken := Gdip_Startup()
018: hbm := CreateDIBSection(w, h), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
019: G := Gdip_GraphicsFromHDC(hdc), Gdip_SetSmoothingMode(G, 4)
022: pPath := Gdip_CreatePath()
The current thread will exit.
---------------------------
OK
---------------------------
That is E0x80000 and parent doesn't work on win7.msdn wrote:Windows 8: The WS_EX_LAYERED style is supported for top-level windows and child windows. Previous Windows versions support WS_EX_LAYERED only for top-level windows.
Code: Select all
Gdip_IsVisiblePathPoint(pPath, x, y, pGraphics)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipIsVisiblePathPoint", Ptr, pPath, "float", x, "float", y, Ptr, pGraphics)
}
Code: Select all
;Tested on A_AhkVersion 1.1.27.06 - Windows 10 Home x64 1809
#NoEnv
#SingleInstance Force
SetWorkingDir %A_ScriptDir%
SetBatchLines -1
;Need to include your path to Gdip or have in the same directory as script
#Include Gdip_all.ahk
OnMessage(0x200, "OnWM_MOUSEMOVE")
Gui Mapper: New, hWndhMap -DPIScale +OwnDialogs
Gui Show, NA w600 h600, Mapper
Gui 1: +E0x80000 +LastFound -Caption -DPIScale +ParentMapper
hGui := WinExist()
Gui 1: Show, NA
w:= A_ScreenWidth, h:= A_ScreenHeight
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, 200, 200, 400, 200)
Gdip_AddPathLine(pPath, 400, 200, 400, 400)
Gdip_AddPathLine(pPath, 400, 400, 200, 400)
Gdip_AddPathLine(pPath, 200, 400, 200, 200)
Gdip_ClosePathFigure(pPath) ; closes the current figure of this path
;Create a Pen to draw with
pPen := Gdip_CreatePen(0xff000000, 3)
;Rotate the graphic until exit
Loop {
Gdip_GraphicsClear(G) ; Clear the graphics
RotateAtCenter(pPath, 5) ; Rotate the path by 5deg on its center
Gdip_DrawPath(G, pPen, pPath) ; draw rectangle
UpdateLayeredWindow(hGui, hdc, 0, 0, w, h) ; Update the layred window
Sleep 100
}
Esc::
MapperGuiEscape:
MapperGuiClose:
;Cleanup and Exit
Gdip_DeletePen(pPen)
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
Gdip_DeleteGraphics(G)
Gdip_Shutdown(pToken)
Gui Mapper: Destroy
ExitApp
;HitTest if the mouse in inside the graphicspath
OnWM_MOUSEMOVE(wParam, lParam, msg, hWnd) {
mX := lParam & 0xFFFF ;get low order
mY := lParam >> 16 ;get high order
hit := Gdip_IsVisiblePathPoint(pPath, mX, mY, G)
Tooltip % "Hit? " hit
}
;#####################################################################################
; HitTest Function by RazorHalo
;#####################################################################################
Gdip_IsVisiblePathPoint(pPath, x, y, pGraphics)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipIsVisiblePathPoint", Ptr, pPath, "float", x, "float", y, Ptr, pGraphics)
}
;#####################################################################################
; RotateAtCenter Function by RazorHalo
;#####################################################################################
;The Matrix order has to be "Append" for the transformations to be applied in the correct order - instead of the default "Prepend"
RotateAtCenter(pPath, Angle, MatrixOrder=1) {
;Get bouinding rectangle of the graphics path
;returns array x,y,w,h
Rect := Gdip_GetPathWorldBounds(pPath)
;Calcualte center of bounding rectangle which will be the center of the graphics path
cX := Rect.x + (Rect.w / 2)
cY := Rect.y + (Rect.h / 2)
;Create a Matrix for the transformations
pMatrix := Gdip_CreateMatrix()
;Move the GraphicsPath center to the origin (0, 0) of the graphics object
Gdip_TranslateMatrix(pMatrix, -cX , -cY)
;Rotate matrix on graphics object origin
Gdip_RotateMatrix(pMatrix, Angle, MatrixOrder)
;Move the GraphicsPath origin point back to its original position
Gdip_TranslateMatrix(pMatrix, cX, cY, MatrixOrder)
;Apply the transformations
Gdip_TransformPath(pPath, pMatrix)
;Reset Matrix? Delete Matrix? Do I still need it for future rotations?
GDip_DeleteMatrix(pMatrix)
}
;#####################################################################################
; GraphicsPath functions added by RazorHalo
;#####################################################################################
; NOTE: Be aware of the order that transoformations are applied. You may need to pass MatrixOrder as 1 for "Append"
; the (default is 0 for "Prepend") to get the correct results.
Gdip_ResetMatrix(pMatrix)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipResetMatrix", Ptr, pMatrix)
}
Gdip_RotateMatrix(pMatrix, Angle, MatrixOrder=0)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipRotateMatrix", Ptr, pMatrix, "float", Angle, "Int", MatrixOrder)
}
Gdip_GetPathWorldBounds(pPath)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
rData := {}
VarSetCapacity(RectF, 16)
NumPut(0, RectF, 0, "float"), NumPut(0, RectF, 4, "float"), NumPut(0, RectF, 8, "float"), NumPut(0, RectF, 12, "float")
status := DllCall("gdiplus\GdipGetPathWorldBounds", Ptr, pPath, Ptr, &RectF)
If (!status) {
rData.x := NumGet(RectF, 0, "float")
, rData.y := NumGet(RectF, 4, "float")
, rData.w := NumGet(RectF, 8, "float")
, rData.h := NumGet(RectF, 12, "float")
} Else {
Return status
}
return rData
}
Gdip_ScaleMatrix(pMatrix, scaleX, scaleY, MatrixOrder=0)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipScaleMatrix", Ptr, pMatrix, "float", scaleX, "float", scaleY, "Int", MatrixOrder)
}
Gdip_TranslateMatrix(pMatrix, offsetX, offsetY, MatrixOrder=0)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipTranslateMatrix", Ptr, pMatrix, "float", offsetX, "float", offsetY, "Int", MatrixOrder)
}
Gdip_TransformPath(pPath, pMatrix)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipTransformPath", Ptr, pPath, Ptr, pMatrix)
}
Gdip_SetMatrixElements(pMatrix, m11, m12, m21, m22, x, y)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipSetMatrixElements", Ptr, pMatrix, "float", m11, "float", m12, "float", m21, "float", m22, "float", x, "float", y)
}
Gdip_GetLastStatus(pMatrix)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipGetLastStatus", 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
}
Code: Select all
;#####################################################################################
; HitTest Function by RazorHalo
;#####################################################################################
Gdip_IsVisiblePathPoint(pPath, x, y, pGraphics)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
DllCall("gdiplus\GdipIsVisiblePathPoint", Ptr, pPath, "float", x, "float", y, Ptr, pGraphics, A_PtrSize ? "UPtr*" : "UInt*", result)
return result
}
maybe LearningOne's functions with the NumPuts?
Code: Select all
Gdip_AddPathLine(pPath, x1, y1, x2, y2)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipAddPathLine", Ptr, pPath, "float", x1, "float", y1, "float", x2, "float", y2)
}
Gdip_StartPathFigure(pPath) ; Starts a new figure without closing the current figure. Subsequent points added to this path are added to the new figure.
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipStartPathFigure", Ptr, pPath)
}
Gdip_ClosePathFigure(pPath) ; Closes the current figure of this path.
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipClosePathFigure", Ptr, pPath)
}
Code: Select all
Gdip_GetPathWorldBounds(pPath)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
rData := {}
VarSetCapacity(RectF, 16)
NumPut(0, RectF, 0, "float"), NumPut(0, RectF, 4, "float"), NumPut(0, RectF, 8, "float"), NumPut(0, RectF, 12, "float")
status := DllCall("gdiplus\GdipGetPathWorldBounds", Ptr, pPath, Ptr, &RectF)
If (!status) {
rData.x := NumGet(RectF, 0, "float")
, rData.y := NumGet(RectF, 4, "float")
, rData.w := NumGet(RectF, 8, "float")
, rData.h := NumGet(RectF, 12, "float")
} Else {
Return status
}
return rData
}
Code: Select all
;Tested on A_AhkVersion U64 1.1.27.06 - Windows 10 Home x64 1809
#NoEnv
#SingleInstance Force
SetWorkingDir %A_ScriptDir%
SetBatchLines -1
;Need to include your path to Gdip or have in the same directory as script
#Include Gdip_all.ahk
OnMessage(0x200, "OnWM_MOUSEMOVE")
OnMessage(0x20A, "OnWM_MOUSEWHEEL")
;Create a GUI
Gui Mapper: New, hWndhMap -DPIScale +OwnDialogs
Gui Show, NA w600 h600, Mapper
;Create a Layered window ontop if the GUI to draw on with the GDI+ functions
Gui 1: +E0x80000 +LastFound -Caption -DPIScale +ParentMapper
hGui := WinExist()
Gui 1: Show, NA
w:= 600, h:= 600
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, 200, 200, 400, 200)
Gdip_AddPathLine(pPath, 400, 200, 400, 400)
Gdip_AddPathLine(pPath, 400, 400, 200, 400)
Gdip_AddPathLine(pPath, 200, 400, 200, 200)
Gdip_ClosePathFigure(pPath) ; closes the current figure of this path
;Create a Pen to draw with
pPen := Gdip_CreatePen(0xff000000, 5)
;Rotate the graphic until exit
Loop {
Gdip_GraphicsClear(G) ; Clear the graphics
RotateAtCenter(pPath, 5) ; Rotate the path by 5deg on its center
Gdip_DrawPath(G, pPen, pPath) ; draw rectangle
UpdateLayeredWindow(hGui, hdc, 0, 0, w, h) ; Update the layred window
Sleep 100
}
Esc::
MapperGuiEscape:
MapperGuiClose:
;Cleanup and Exit
Gdip_DeletePen(pPen)
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
Gdip_DeleteGraphics(G)
Gdip_Shutdown(pToken)
Gui Mapper: Destroy
ExitApp
;HitTest if the mouse in inside the graphicspath
OnWM_MOUSEMOVE(wParam, lParam, msg, hWnd) {
Global
mX := lParam & 0xFFFF ;get low order
mY := lParam >> 16 ;get high order
hit := Gdip_IsVisiblePathPoint(pPath, mX, mY, G)
Tooltip % "Hit= " hit
}
OnWM_MOUSEWHEEL(wParam, lParam, msg, hWnd) {
Global
mX := lParam & 0xFFFF ;get low order
mY := lParam >> 16 ;get high order
delta := wParam >> 16 ;120 for zoom in, 65416 for zoom out
Scale := Delta = 120 ? 0.9 : 1.1 ;Adjust scale factor
;TODO - Factor in the mouse coords to zoom in and out at that point
Gdip_GraphicsClear(G)
pMatrix := Gdip_CreateMatrix()
;Calcualte center of Window which will be the center of the graphics path
cX := w / 2
cY := h / 2
;Move Centre point of square to origin of graphics object, then scale and then move back to original center point of square
GDip_TranslateMatrix(pMatrix, -cX, -cY, 1)
Gdip_ScaleMatrix(pMatrix, Scale, Scale, 1)
GDip_TranslateMatrix(pMatrix, cX, cY, 1)
;Apply the transformations
Gdip_TransformPath(pPath, pMatrix)
;Redraw the path and update the window
Gdip_DrawPath(G, pPen, pPath)
UpdateLayeredWindow(hGui, hdc, 0, 0, w, h)
}
;#####################################################################################
; HitTest Function by RazorHalo
;#####################################################################################
Gdip_IsVisiblePathPoint(pPath, x, y, pGraphics)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
DllCall("gdiplus\GdipIsVisiblePathPoint", Ptr, pPath, "float", x, "float", y, Ptr, pGraphics, A_PtrSize ? "UPtr*" : "UInt*", result)
return result
}
;#####################################################################################
; RotateAtCenter Function by RazorHalo
;#####################################################################################
;The Matrix order has to be "Append" for the transformations to be applied in the correct order - instead of the default "Prepend"
RotateAtCenter(pPath, Angle, MatrixOrder=1) {
;Get bouinding rectangle of the graphics path
;returns array x,y,w,h
Rect := Gdip_GetPathWorldBounds(pPath)
;Calcualte center of bounding rectangle which will be the center of the graphics path
cX := Rect.x + (Rect.w / 2)
cY := Rect.y + (Rect.h / 2)
;Create a Matrix for the transformations
pMatrix := Gdip_CreateMatrix()
;Move the GraphicsPath center to the origin (0, 0) of the graphics object
Gdip_TranslateMatrix(pMatrix, -cX , -cY)
;Rotate matrix on graphics object origin
Gdip_RotateMatrix(pMatrix, Angle, MatrixOrder)
;Move the GraphicsPath origin point back to its original position
Gdip_TranslateMatrix(pMatrix, cX, cY, MatrixOrder)
;Apply the transformations
Gdip_TransformPath(pPath, pMatrix)
;Reset Matrix? Delete Matrix? Do I still need it for future rotations?
GDip_DeleteMatrix(pMatrix)
}
;#####################################################################################
; GraphicsPath functions added by RazorHalo
;#####################################################################################
; NOTE: Be aware of the order that transoformations are applied. You may need to pass MatrixOrder as 1 for "Append"
; the (default is 0 for "Prepend") to get the correct results.
Gdip_ResetMatrix(pMatrix)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipResetMatrix", Ptr, pMatrix)
}
Gdip_RotateMatrix(pMatrix, Angle, MatrixOrder=0)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipRotateMatrix", Ptr, pMatrix, "float", Angle, "Int", MatrixOrder)
}
Gdip_GetPathWorldBounds(pPath)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
rData := {}
VarSetCapacity(RectF, 16)
NumPut(0, RectF, 0, "float"), NumPut(0, RectF, 4, "float"), NumPut(0, RectF, 8, "float"), NumPut(0, RectF, 12, "float")
status := DllCall("gdiplus\GdipGetPathWorldBounds", Ptr, pPath, Ptr, &RectF)
If (!status) {
rData.x := NumGet(RectF, 0, "float")
, rData.y := NumGet(RectF, 4, "float")
, rData.w := NumGet(RectF, 8, "float")
, rData.h := NumGet(RectF, 12, "float")
} Else {
Return status
}
return rData
}
Gdip_ScaleMatrix(pMatrix, scaleX, scaleY, MatrixOrder=0)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipScaleMatrix", Ptr, pMatrix, "float", scaleX, "float", scaleY, "Int", MatrixOrder)
}
Gdip_TranslateMatrix(pMatrix, offsetX, offsetY, MatrixOrder=0)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipTranslateMatrix", Ptr, pMatrix, "float", offsetX, "float", offsetY, "Int", MatrixOrder)
}
Gdip_TransformPath(pPath, pMatrix)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipTransformPath", Ptr, pPath, Ptr, pMatrix)
}
Gdip_SetMatrixElements(pMatrix, m11, m12, m21, m22, x, y)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipSetMatrixElements", Ptr, pMatrix, "float", m11, "float", m12, "float", m21, "float", m22, "float", x, "float", y)
}
Gdip_GetLastStatus(pMatrix)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipGetLastStatus", 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)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipAddPathLine", Ptr, 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.
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipStartPathFigure", Ptr, pPath)
}
Gdip_ClosePathFigure(pPath) ; Closes the current figure of this path.
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipClosePathFigure", Ptr, 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
}
Code: Select all
; Tested on A_AhkVersion U64 1.1.30.03 - Windows 7 & 10 x64
#NoEnv
#SingleInstance Force
SetWorkingDir %A_ScriptDir%
SetBatchLines -1
;Need to include your path to Gdip or have in the same directory as script
#Include Gdip_all.ahk
OnMessage(0x200, "OnWM_MOUSEMOVE")
OnMessage(0x20A, "OnWM_MOUSEWHEEL")
;Create a Layered window
Gui 1: +E0x80000 +LastFound -Caption -DPIScale
hGui := WinExist()
Gui 1: Show, NA
w:= 600, h:= 600
pToken := Gdip_Startup()
hbm := CreateDIBSection(w, h), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc), Gdip_SetSmoothingMode(G, 4)
pBrush := Gdip_BrushCreateSolid(0xFFFFFFFF)
;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, 200, 200, 400, 200)
Gdip_AddPathLine(pPath, 400, 200, 400, 400)
Gdip_AddPathLine(pPath, 400, 400, 200, 400)
Gdip_AddPathLine(pPath, 200, 400, 200, 200)
Gdip_ClosePathFigure(pPath) ; closes the current figure of this path
;Create a Pen to draw with
pPen := Gdip_CreatePen(0xff000000, 5)
;Rotate the graphic until exit
Loop {
Gdip_GraphicsClear(G) ; Clear the graphics
Gdip_FillRectangle(G, pBrush, 0, 0, w, h)
RotateAtCenter(pPath, 5) ; Rotate the path by 5deg on its center
Gdip_DrawPath(G, pPen, pPath) ; draw rectangle
UpdateLayeredWindow(hGui, hdc, 0, 0, w, h) ; Update the layred window
Sleep 100
}
Esc::
Gdip_DeletePen(pPen)
Gdip_DeleteBrush(pBrush)
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
Gdip_DeleteGraphics(G)
Gdip_Shutdown(pToken)
ExitApp
;HitTest if the mouse in inside the graphicspath
OnWM_MOUSEMOVE(wParam, lParam, msg, hWnd) {
Global
mX := lParam & 0xFFFF ;get low order
mY := lParam >> 16 ;get high order
hit := Gdip_IsVisiblePathPoint(pPath, mX, mY, G)
Tooltip % "Hit= " hit
}
OnWM_MOUSEWHEEL(wParam, lParam, msg, hWnd) {
Global
mX := lParam & 0xFFFF ;get low order
mY := lParam >> 16 ;get high order
delta := wParam >> 16 ;120 for zoom in, 65416 for zoom out
Scale := Delta = 120 ? 0.9 : 1.1 ;Adjust scale factor
;TODO - Factor in the mouse coords to zoom in and out at that point
Gdip_GraphicsClear(G)
pMatrix := Gdip_CreateMatrix()
;Calcualte center of Window which will be the center of the graphics path
cX := w / 2
cY := h / 2
;Move Centre point of square to origin of graphics object, then scale and then move back to original center point of square
GDip_TranslateMatrix(pMatrix, -cX, -cY, 1)
Gdip_ScaleMatrix(pMatrix, Scale, Scale, 1)
GDip_TranslateMatrix(pMatrix, cX, cY, 1)
;Apply the transformations
Gdip_TransformPath(pPath, pMatrix)
;Redraw the path and update the window
Gdip_DrawPath(G, pPen, pPath)
UpdateLayeredWindow(hGui, hdc, 0, 0, w, h)
}
;#####################################################################################
; HitTest Function by RazorHalo
;#####################################################################################
Gdip_IsVisiblePathPoint(pPath, x, y, pGraphics)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
DllCall("gdiplus\GdipIsVisiblePathPoint", Ptr, pPath, "float", x, "float", y, Ptr, pGraphics, A_PtrSize ? "UPtr*" : "UInt*", result)
return result
}
;#####################################################################################
; RotateAtCenter Function by RazorHalo
;#####################################################################################
;The Matrix order has to be "Append" for the transformations to be applied in the correct order - instead of the default "Prepend"
RotateAtCenter(pPath, Angle, MatrixOrder=1) {
;Get bouinding rectangle of the graphics path
;returns array x,y,w,h
Rect := Gdip_GetPathWorldBounds(pPath)
;Calcualte center of bounding rectangle which will be the center of the graphics path
cX := Rect.x + (Rect.w / 2)
cY := Rect.y + (Rect.h / 2)
;Create a Matrix for the transformations
pMatrix := Gdip_CreateMatrix()
;Move the GraphicsPath center to the origin (0, 0) of the graphics object
Gdip_TranslateMatrix(pMatrix, -cX , -cY)
;Rotate matrix on graphics object origin
Gdip_RotateMatrix(pMatrix, Angle, MatrixOrder)
;Move the GraphicsPath origin point back to its original position
Gdip_TranslateMatrix(pMatrix, cX, cY, MatrixOrder)
;Apply the transformations
Gdip_TransformPath(pPath, pMatrix)
;Reset Matrix? Delete Matrix? Do I still need it for future rotations?
GDip_DeleteMatrix(pMatrix)
}
;#####################################################################################
; GraphicsPath functions added by RazorHalo
;#####################################################################################
; NOTE: Be aware of the order that transoformations are applied. You may need to pass MatrixOrder as 1 for "Append"
; the (default is 0 for "Prepend") to get the correct results.
Gdip_ResetMatrix(pMatrix)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipResetMatrix", Ptr, pMatrix)
}
Gdip_RotateMatrix(pMatrix, Angle, MatrixOrder=0)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipRotateMatrix", Ptr, pMatrix, "float", Angle, "Int", MatrixOrder)
}
Gdip_GetPathWorldBounds(pPath)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
rData := {}
VarSetCapacity(RectF, 16)
NumPut(0, RectF, 0, "float"), NumPut(0, RectF, 4, "float"), NumPut(0, RectF, 8, "float"), NumPut(0, RectF, 12, "float")
status := DllCall("gdiplus\GdipGetPathWorldBounds", Ptr, pPath, Ptr, &RectF)
If (!status) {
rData.x := NumGet(RectF, 0, "float")
, rData.y := NumGet(RectF, 4, "float")
, rData.w := NumGet(RectF, 8, "float")
, rData.h := NumGet(RectF, 12, "float")
} Else {
Return status
}
return rData
}
Gdip_ScaleMatrix(pMatrix, scaleX, scaleY, MatrixOrder=0)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipScaleMatrix", Ptr, pMatrix, "float", scaleX, "float", scaleY, "Int", MatrixOrder)
}
Gdip_TranslateMatrix(pMatrix, offsetX, offsetY, MatrixOrder=0)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipTranslateMatrix", Ptr, pMatrix, "float", offsetX, "float", offsetY, "Int", MatrixOrder)
}
Gdip_TransformPath(pPath, pMatrix)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipTransformPath", Ptr, pPath, Ptr, pMatrix)
}
Gdip_SetMatrixElements(pMatrix, m11, m12, m21, m22, x, y)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipSetMatrixElements", Ptr, pMatrix, "float", m11, "float", m12, "float", m21, "float", m22, "float", x, "float", y)
}
Gdip_GetLastStatus(pMatrix)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipGetLastStatus", 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)
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipAddPathLine", Ptr, 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.
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipStartPathFigure", Ptr, pPath)
}
Gdip_ClosePathFigure(pPath) ; Closes the current figure of this path.
{
Ptr := A_PtrSize ? "UPtr" : "UInt"
return DllCall("gdiplus\GdipClosePathFigure", Ptr, 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
}
are you sure the RECT items are supposed to be of type "float"? would that affect 32 vs 64bit?RazorHalo wrote: ↑13 Apr 2019, 21:02GDip_GetPathWorldBounds Function I don't know how to make x32 compatible:Code: Select all
Gdip_GetPathWorldBounds(pPath) { Ptr := A_PtrSize ? "UPtr" : "UInt" rData := {} VarSetCapacity(RectF, 16) NumPut(0, RectF, 0, "float"), NumPut(0, RectF, 4, "float"), NumPut(0, RectF, 8, "float"), NumPut(0, RectF, 12, "float") status := DllCall("gdiplus\GdipGetPathWorldBounds", Ptr, pPath, Ptr, &RectF) If (!status) { rData.x := NumGet(RectF, 0, "float") , rData.y := NumGet(RectF, 4, "float") , rData.w := NumGet(RectF, 8, "float") , rData.h := NumGet(RectF, 12, "float") } Else { Return status } return rData }
Code: Select all
status := DllCall("gdiplus\GdipGetPathWorldBounds", Ptr, pPath, Ptr, &RectF, ptr, 0, ptr, 0)
Code: Select all
status := DllCall("gdiplus\GdipGetPathWorldBounds", Ptr, pPath, Ptr, &RectF)
Code: Select all
VarSetCapacity(RectF, 16)
NumPut(0, RectF, 0, "float"), NumPut(0, RectF, 4, "float"), NumPut(0, RectF, 8, "float"), NumPut(0, RectF, 12, "float")
Code: Select all
VarSetCapacity(RectF, 16, 0)