GDI+ standard library 1.45 by tic

Post your working scripts, libraries and tools for AHK v1.1 and older
iPhilip
Posts: 791
Joined: 02 Oct 2013, 12:21

Re: GDI+ standard library 1.45 by tic

13 Apr 2019, 01:39

@RazorHalo

As posted, the sample script generates an error.
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
guest3456
Posts: 3453
Joined: 09 Oct 2013, 10:31

Re: GDI+ standard library 1.45 by tic

13 Apr 2019, 05:15

no error for me, just a blank gui

User avatar
RazorHalo
Posts: 45
Joined: 21 Dec 2015, 21:23

Re: GDI+ standard library 1.45 by tic

13 Apr 2019, 12:01

@iPhilip
As posted, the sample script generates an error.
What is the error your getting?

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...
iPhilip
Posts: 791
Joined: 02 Oct 2013, 12:21

Re: GDI+ standard library 1.45 by tic

13 Apr 2019, 12:39

RazorHalo wrote:
13 Apr 2019, 12:01
@iPhilip
As posted, the sample script generates an error.
What is the error your getting?

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...
@RazorHalo
With the same Gdip_All.ahk file (I redownloaded it just to make sure) and the sample script you posted running under Windows 7 and AutoHotkey 1.1.30.03 (AHK_L) A32/U32/U64, I get the following error:

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   
---------------------------
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
User avatar
RazorHalo
Posts: 45
Joined: 21 Dec 2015, 21:23

Re: GDI+ standard library 1.45 by tic

13 Apr 2019, 13:28

It's seems to be failing for you when trying to create the layered Gui but I don't see why. I've looked at a couple of examples of creating a layered Gui to the drawing on and don't see anything out of place there...
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: GDI+ standard library 1.45 by tic

13 Apr 2019, 13:48

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.
That is E0x80000 and parent doesn't work on win7.
User avatar
RazorHalo
Posts: 45
Joined: 21 Dec 2015, 21:23

Re: GDI+ standard library 1.45 by tic

13 Apr 2019, 15:25

I'm now trying to do a hit test to see if the mouse is inside that graphics path using the GDI+ function "GdipIsVisiblePathPoint"
https://docs.microsoft.com/en-us/previous-versions//ms535573(v=vs.85)

And have wrote the wrapper as:

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)
}
But I only get a return result of "2" where I should be getting TRUE or 'FALSE returned for if the point lies within the graphicspath.
I must be trying to put the wrong type or variable into the DllCall as "2" is an invalid parameter.

Anyone see where I'm going wrong?

Here is my testing script - I should be able to move the mouse around and when I cross into the rotating square I should get a positive hit:

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
}
Last edited by RazorHalo on 13 Apr 2019, 16:38, edited 1 time in total.
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: GDI+ standard library 1.45 by tic

13 Apr 2019, 15:37

supply all parameters. https://docs.microsoft.com/en-us/windows/desktop/gdiplus/-gdiplus-graphicspath-flat
signature is GpStatus WINGDIPAPI GdipIsVisiblePathPoint(GpPath* path, REAL x, REAL y, GpGraphics *graphics, BOOL *result)
the overload with the ints works too
User avatar
RazorHalo
Posts: 45
Joined: 21 Dec 2015, 21:23

Re: GDI+ standard library 1.45 by tic

13 Apr 2019, 17:00

Thanks swagfag! I see now what I was missing. so now I have this:

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
}
And I get a result of 0, but no result of 1 when I pass over the square. I stopped the rotation to see if that was it but still no hit. Am I missing something else?
guest3456
Posts: 3453
Joined: 09 Oct 2013, 10:31

Re: GDI+ standard library 1.45 by tic

13 Apr 2019, 20:04

RazorHalo wrote:
13 Apr 2019, 12:01
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...
maybe LearningOne's functions with the NumPuts?

User avatar
RazorHalo
Posts: 45
Joined: 21 Dec 2015, 21:23

Re: GDI+ standard library 1.45 by tic

13 Apr 2019, 21:02

It could be, I've tried updating some of them that are used in this sample script Gdip_StartPathFigure Gdip_ClosePathFigure Gdip_AddPathLine and it works now on x32 but only if I also take out the RotateAtCenter Function, I'm pretty sure its because that function uses the function Gdip_GetPathWorldBounds which contains some numput commands. I'm not quite sure what I need to modify to make that x32 compatible.

I also spoke too soon earlier and with revising the function for Gdip_IsVisiblePathPoint to supply all the parameters I still get a status of 2 (Invalid Parameter). I get a value returned now, which is always 0, never a positive hit value of 1 when the point is inside the square, but I'm guessing that's because the actual function is not working. That one is still baffling me. As far as I can tell I'm supplying a valid pointer to the graphics path, correct values for x & y coords, and a valid pointer to the graphics object. I use the graphicspath pointer and graphics object pointer with other functions that return properly so that's why I believe they are correct.

So which parameter is invalid? Or Am I still calling it wrong?

Updated Functions:

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)
}
GDip_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
}
User avatar
RazorHalo
Posts: 45
Joined: 21 Dec 2015, 21:23

Re: GDI+ standard library 1.45 by tic

14 Apr 2019, 00:17

Ok well, I found the problem. I actually wasn't passing the Pointer to the graphicspath to the GDip_IsVisiblePathPoint Function. I was using OnMessage(0x200, "OnWM_MOUSEMOVE") to continuously detect where the mouse was and didn't realize that when running the hit test from that function I had not declared the mousemove function with Global as the first line. once I put that in everything works.

So here is a functional example script of creating a layered GUI, creating a square as part of a graphicspath, rotating that square on its center point and detecting if the mouse is inside that square. I have also added in functions to zoom the square in and out with the mouse wheel.

Thanks everyone who helped me understand, I have learned a lot about GDI+ and Dllcalls from working on this.
It still needs some compatibility for U32 and a tweek for the layered GUI on Windows 7 ( I don't have Win7 on a PC to test but as Helgef pointed out it has to do with +E0x80000 and +parent.

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
}
iPhilip
Posts: 791
Joined: 02 Oct 2013, 12:21

Re: GDI+ standard library 1.45 by tic

14 Apr 2019, 02:15

@RazorHalo

The following works on Windows 7 but still requires U64.

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
}
Cheers!

- iPhilip
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
guest3456
Posts: 3453
Joined: 09 Oct 2013, 10:31

Re: GDI+ standard library 1.45 by tic

14 Apr 2019, 15:58

RazorHalo wrote:
13 Apr 2019, 21:02
GDip_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
}
are you sure the RECT items are supposed to be of type "float"? would that affect 32 vs 64bit?

sargearmstrong
Posts: 1
Joined: 17 Apr 2019, 02:25

Re: GDI+ standard library 1.45 by tic

17 Apr 2019, 02:33

Dear Friends. Sorry to interrupt the conversation, but can I ask.. how can we get the bits/bytes size of the pBitmap in memory without writing it to disk first?

To clarify.. our monitoring script fires:
pBitmap := Gdip_BitmapFromScreen()

We then write it to disk:
Gdip_SaveBitmapToFile(pBitmap, saveTempFile)

And then examine its filesize:
FileGetSize, ThisPicSize, %saveTempFile%

But, to reduce disk I/O.. is it possible to get the size of the bitmap before writing it to disk? I've crawled around quite a bit to no avail, perhaps you folks know of an easy way to achieve this? Thank you in advance!
Last edited by sargearmstrong on 02 May 2019, 01:47, edited 1 time in total.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: GDI+ standard library 1.45 by tic

17 Apr 2019, 02:59

@RazorHalo @iPhilip @guest3456 (Edit, hi :wave: ), you need to pass all parameters, ie.

Code: Select all

status := DllCall("gdiplus\GdipGetPathWorldBounds", Ptr, pPath, Ptr, &RectF, ptr, 0, ptr, 0)
rather than

Code: Select all

status := DllCall("gdiplus\GdipGetPathWorldBounds", Ptr, pPath, Ptr, &RectF)
It is useful to use try-catch-throw or check errorlevel when using dllcall.

Cheers.
guest3456
Posts: 3453
Joined: 09 Oct 2013, 10:31

Re: GDI+ standard library 1.45 by tic

17 Apr 2019, 07:04

thanks Helgef, it now works on x32

@RazorHalo feel free to add your functions and create your example file and submit a PR:

https://github.com/mmikeww/AHKv2-Gdip

iPhilip
Posts: 791
Joined: 02 Oct 2013, 12:21

Re: GDI+ standard library 1.45 by tic

17 Apr 2019, 13:28

Thank you @Helgef! :wave:

@RazorHalo, in your Gdip_GetPathWorldBounds(pPath) function you might want to replace

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")
with

Code: Select all

VarSetCapacity(RectF, 16, 0)
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
robodesign
Posts: 932
Joined: 30 Sep 2017, 03:59
Location: Romania
Contact:

Re: GDI+ standard library 1.45 by tic

21 Aug 2019, 08:04

Hello, guys!

I made new a GDI+ library edition. This is a compilation of user contributed functions for the library wrapper made by Tariq Porter [tic] that never were included into it.

I carefully went through those 93 pages on the old forum, and on the 15 here... and collected all the working functions contributed by varying people . I also made my best to fix some of those not working.

This new library includes functions for GraphicsPath, PathGradients, GetProperty [for file metadata], Multiple Display Monitors (MDMF), Apply/Create Effects, and others. For more details, see the repository's read-me. There are about 66 new functions.

This library edition also includes a few functions I made when coding Quick Picto Viewer, most notably for you, perhaps, would be DrawImageFX(), which offers blur, sharpen and other capabilities. And also, a function to generate color matrixes, based on user parameters for color adjustments.

I hope you will find useful this new edition. New examples/tutorials included in the repository.

AHK GDI+ library compilation
a compilation of user contributed functions

Link: https://github.com/marius-sucan/AHK-GDIp-Library-Compilation

If you guys know of other functions, threads related to GDI+ that should be included, please let me know .

Best regards, Marius.
Last edited by robodesign on 29 Aug 2019, 15:52, edited 2 times in total.
-------------------------
KeyPress OSD v4: GitHub or forum. (presentation video)
Quick Picto Viewer: GitHub or forum.
AHK GDI+ expanded / compilation library (on GitHub)
My home page.
User avatar
Learning one
Posts: 173
Joined: 04 Oct 2013, 13:59
Location: Croatia
Contact:

Re: GDI+ standard library 1.45 by tic

22 Aug 2019, 17:05

I haven't tested all of it yet but it looks you made a great job! :)
One suggestion; in updated Gdip_AddPathLines() function, this line;
return DllCall("gdiplus\GdipAddPathLine2", Ptr, pPath, Ptr, &PointF, "int", Points0)
should be replaced with;
return DllCall("gdiplus\GdipAddPathLine2", Ptr, pPath, Ptr, &PointF, "int", Points.Length())

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: sanmaodo, TheNaviator and 86 guests