La idea era crear un programa que cambiando la variable "Lados" dibuje un polígono de cualquier número de lados.
El caso es que al introducir la "variable1" en la función, no funciona. Sin embargo, las variables 2, 3 y 4, sí.
No entiendo por qué el resto de variables funcionan y la "variable1" no, ya que a mi parecer son idénticas.
Soy bastante novato con las funciones, sé que estoy haciendo algo mal pero no sé el que.
Code: Select all
;INICIO DEL PROGRAMA------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CoordMode, Mouse, Screen
#include classCanvas.ahk
RED_pen := new Canvas.Pen(0xFFFF0000, 2)
gui, -Caption +HwndMyGui1Hwnd +AlwaysOnTop +ToolWindow +E0x20
gui, Add, text, w1922 h1082 x-1 y-1 vmainbox hwndMainBox border
gui, Color, 808080 ;262626
gui, show, NA x0 y0 w1920 h1080, Ventana principal
WinSet, Transparent, 255, ahk_id %MyGui1Hwnd%
WinSet, TransColor, 808080, ahk_id %MyGui1Hwnd%
surface1 := new Canvas.Surface(1920,1080)
surface1.Clear(0xFF808080)
surface1.Smooth := "Best"
Viewport := new Canvas.Viewport(MainBox).Attach(Surface1)
ClonedSurface:=Surface1.clone().draw(Surface1)
Viewport.Refresh()
X0 := 960
Y0 := 540
Radio := 20
Lados := 4
pi := 3.14159265
Grados := 360 / Lados
Incremento := Grados
IndexLados := Lados
loop, %Lados%
{
GradosToRad := Grados * (pi / 180)
Coseno := Cos(GradosToRad)
Seno := Sin(GradosToRad)
X%IndexLados% := (Coseno * Radio) + X0
XIndexLados := X%IndexLados%
Y%IndexLados% := (Seno * Radio) + Y0
YIndexLados := Y%IndexLados%
;------------------------------------------------
string := "[" XIndexLados "," YIndexLados "]"
if (Lados = IndexLados)
string%IndexLados% := string
if (Lados > IndexLados)
string%IndexLados% := string "," stringIndexLados
stringIndexLados := string%IndexLados%
;------------------------------------------------
Grados := Grados + Incremento
IndexLados := IndexLados - 1
}
msgbox, X1 = %X1%`nY1 = %Y1%`n`nX2 = %X2%`nY2 = %Y2%`n`nX3 = %X3%`nY3 = %Y3%`n`nX4 = %X4%`nY4 = %Y4%`n`n
stringInicial := "["
stringFinal := "]"
variable1 := stringInicial stringIndexLados stringFinal ;No funciona <------
variable2 := [[X1,Y1],[X2,Y2],[X3,Y3],[X4,Y4]] ;Si funciona
variable3 := [[980,540],[960,520],[940,540],[960,560]] ;Si funciona
variable4 := [[980.000000,540.000000],[960.000000,520.000000],[940.000000,540.000000],[960.000000,560.000000]] ;Si funciona
msgbox, variable1 = %variable1%
ClonedSurface:=Surface1.clone().draw(Surface1)
Surface1.DrawPolygon(Red_pen,[[X1,Y1],[X2,Y2],[X3,Y3],[X4,Y4]]) ;Si funciona
;Surface1.DrawPolygon(Red_pen,variable1) ;No funciona <------
;Surface1.DrawPolygon(Red_pen,variable2) ;Si funciona
;Surface1.DrawPolygon(Red_pen,variable3) ;Si funciona
;Surface1.DrawPolygon(Red_pen,variable4) ;Si funciona
Viewport.Refresh()
;FIN DEL PROGRAMA------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Code: Select all
;INICIO DE classCanvas.ahk------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#NoEnv
/*
Copyright 2012 Anthony Zhang <[email protected]>
This file is part of Canvas-AHK. Source code is available at <https://github.com/Uberi/Canvas-AHK>.
Canvas-AHK is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
TODO
----
* console output module with colors by reading the bitmap, console functions at http://msdn.microsoft.com/en-us/library/windows/desktop/ms682073(v=vs.85).aspx
* consider color transformations using http://msdn.microsoft.com/en-us/library/windows/desktop/ms533875(v=vs.85).aspx
* effects support with http://msdn.microsoft.com/en-us/library/windows/desktop/ms533971(v=vs.85).aspx
* GpStatus WINGDIPAPI GdipDrawImageFX(GpGraphics *graphics, GpImage *image, GpRectF *source, GpMatrix *xForm, CGpEffect *effect, GpImageAttributes *imageAttributes, GpUnit srcUnit)
* GpStatus WINGDIPAPI GdipBitmapApplyEffect(GpBitmap* bitmap, CGpEffect *effect, RECT *roi, BOOL useAuxData, VOID **auxData, INT *auxDataSize)
* Status __stdcall GdipCreateEffect(const GUID guid, CGpEffect **effect)
* opengl backend
* ASCII backend with drawing functions here: http://free.pages.at/easyfilter/bresenham.html
* combine the draw* and fill* functions: DrawPie(Pen) and FillPie(Brush) -> Pie(Pen) and Pie(Brush)
* fold pens into brushes; allow brushes to define widths, fills, etc.
* add hatch brush, texture brush, and linear/radial gradient brush capabilities to Brush class
* use CachedBitmap for animations or faster drawing: http://msdn.microsoft.com/en-us/library/ms533975(v=vs.85).aspx
*/
/*
#Warn All
#Warn LocalSameAsGlobal, Off
i := new Canvas.Surface
i.Load(A_ScriptDir . "\Earthrise.jpg")
s := new Canvas.Surface(400,400)
s.Draw(i)
f := new Canvas.Font("Georgia",18)
s.Text(new Canvas.Brush(0xFFFFFFFF),f,"Earthrise: Dawn of a new era",30,80)
Gui, +LastFound
v := new Canvas.Viewport(WinExist()).Attach(s)
p := new Canvas.Pen(0x80FF0000,10)
t := new Canvas.Pen(0xFF00FF00,1)
b := new Canvas.Brush(0xAA0000FF)
Gui, Show, w400 h400, Canvas Demo
Return
GuiClose:
ExitApp
Tab::
f.Measure("Earthrise: Dawn of a new era",W,H)
s.DrawRectangle(t,30,80,W,H)
v.Refresh()
Return
Space::
s.Clear(0xFFFFFF00)
.Push()
.Translate(50,50)
.Rotate(60)
.FillRectangle(b,0,0,50,50)
.Pop()
.DrawEllipse(p,70,70,100,100)
.DrawCurve(t,[[10,10],[50,10],[10,50]],True)
.FillPie(b,100,100,50,50,0,270)
v.Refresh()
Return
*/
class Canvas
{
static _ := Canvas.Initialize()
Initialize()
{
this.hModule := DllCall("LoadLibrary","Str","gdiplus","UPtr")
;initialize the GDI+ library
VarSetCapacity(StartupInformation,A_PtrSize + 12)
NumPut(1,StartupInformation,0,"UInt") ;GDI+ version (version 1)
NumPut(0,StartupInformation,4) ;debug callback (disabled)
NumPut(0,StartupInformation,A_PtrSize + 4) ;suppress background thread (disabled)
NumPut(0,StartupInformation,A_PtrSize + 8) ;suppress external image codecs (disabled)
Token := 0
this.CheckStatus(DllCall("gdiplus\GdiplusStartup","UPtr*",Token,"UPtr",&StartupInformation,"UPtr",0)
,"GdiplusStartup","Could not initialize GDI+ library")
this.Token := Token
}
__Delete()
{
;shut down the GDI+ library
DllCall("gdiplus\GdiplusShutdown","UPtr",this.Token)
}
Lenient()
{
this.Surface.CheckStatus := this.Surface.StubCheckStatus
this.Surface.CheckPen := this.Surface.StubCheckPen
this.Surface.CheckBrush := this.Surface.StubCheckBrush
this.Surface.CheckFormat := this.Surface.StubCheckFormat
this.Surface.CheckLine := this.Surface.StubCheckLine
this.Surface.CheckRectangle := this.Surface.StubCheckRectangle
this.Surface.CheckSector := this.Surface.StubCheckSector
this.Surface.CheckPoint := this.Surface.StubCheckPoint
this.Surface.CheckPoints := this.Surface.StubCheckPoints
this.Viewport.CheckStatus := this.Viewport.StubCheckStatus
this.Pen.CheckStatus := this.Pen.StubCheckStatus
this.Brush.CheckStatus := this.Brush.StubCheckStatus
this.Font.CheckStatus := this.Font.StubCheckStatus
}
class Viewport
{
__New(hWindow)
{
this.hWindow := hWindow
;create a memory device context for double buffering use
this.hMemoryDC := DllCall("CreateCompatibleDC","UPtr",0,"UPtr")
If !this.hMemoryDC
throw Exception("INTERNAL_ERROR",A_ThisFunc,"Could not create memory device context (error in CreateCompatibleDC)")
;subclass window to override WM_PAINT
this.pCallback := RegisterCallback(this.PaintCallback,"Fast",6)
If !DllCall("Comctl32\SetWindowSubclass"
,"UPtr",hWindow ;window handle
,"UPtr",this.pCallback ;callback pointer
,"UPtr",hWindow ;subclass ID
,"UPtr",0) ;arbitrary data to pass to this particular subclass callback and ID
throw Exception("INTERNAL_ERROR",A_ThisFunc,"Could not subclass window (error in SetWindowSubclass)")
}
__Delete()
{
;remove subclass of window
If !DllCall("Comctl32\RemoveWindowSubclass","UPtr",this.hWindow,"UPtr",this.pCallback,"UPtr",this.hWindow)
throw Exception("INTERNAL_ERROR",A_ThisFunc,"Could not remove subclass from window (error in RemoveWindowSubclass)")
;free paint callback
DllCall("GlobalFree","UPtr",this.pCallback,"UPtr")
}
Attach(Surface)
{
If !DllCall("Comctl32\SetWindowSubclass"
,"UPtr",this.hWindow ;window handle
,"UPtr",this.pCallback ;callback pointer
,"UPtr",this.hWindow ;subclass ID
,"UPtr",&this) ;arbitrary data to pass to this particular subclass callback and ID
throw Exception("INTERNAL_ERROR",A_ThisFunc,"Could not update window subclass (error in SetWindowSubclass)")
this.Surface := Surface
this.Width := Surface.Width
this.Height := Surface.Height
Return, this
}
Detach()
{
this.Surface := False
Return, this
}
Refresh(X = 0,Y = 0,W = 0,H = 0)
{
If (X < 0 || X > this.Width)
throw Exception("INVALID_INPUT",A_ThisFunc,"Invalid X-axis coordinate: " . X)
If (Y < 0 || Y > this.Height)
throw Exception("INVALID_INPUT",A_ThisFunc,"Invalid Y-axis coordinate: " . Y)
If (W < 0 || W > this.Width)
throw Exception("INVALID_INPUT",A_ThisFunc,"Invalid width: " . W)
If (H < 0 || H > this.Height)
throw Exception("INVALID_INPUT",A_ThisFunc,"Invalid height: " . W)
If W = 0
W := this.Width
If H = 0
H := this.Height
;flush the GDI+ drawing batch
this.CheckStatus(DllCall("gdiplus\GdipFlush","UPtr",this.Surface.pGraphics,"UInt",1) ;FlushIntention.FlushIntentionSync
,"GdipFlush","Could not flush GDI+ pending rendering operations")
;set up rectangle structure representing area to redraw
VarSetCapacity(Rect,16)
NumPut(X,Rect,0,"UInt")
NumPut(Y,Rect,4,"UInt")
NumPut(X + W,Rect,8,"UInt")
NumPut(Y + H,Rect,12,"UInt")
;trigger redrawing of the window
If !DllCall("InvalidateRect","UPtr",this.hWindow,"UPtr",&Rect,"UInt",0)
throw Exception("INTERNAL_ERROR",A_ThisFunc,"Could not add rectangle to update region (error in InvalidateRect)")
If !DllCall("UpdateWindow","UPtr",this.hWindow)
throw Exception("INTERNAL_ERROR",A_ThisFunc,"Could not update window (error in UpdateWindow)")
Return, this
}
PaintCallback(Message,wParam,lParam,hWindow,pInstance)
{
If Message != 0xF ;WM_PAINT
Return, DllCall("Comctl32\DefSubclassProc","UPtr",hWindow,"UInt",Message,"UPtr",wParam,"UPtr",lParam,"UPtr") ;call the next handler in the window's subclass chain
;prepare window for painting
VarSetCapacity(PaintStruct,A_PtrSize + 60)
hWindowDC := DllCall("BeginPaint","UPtr",hWindow,"UPtr",&PaintStruct,"UPtr")
If !hWindowDC
throw Exception("INTERNAL_ERROR",A_ThisFunc,"Could not prepare window for painting (error in BeginPaint)")
this := Object(pInstance) ;obtain the instance
If this.Surface ;surface attached
{
;obtain dimensions of update region
X := NumGet(PaintStruct,A_PtrSize + 4,"UInt")
Y := NumGet(PaintStruct,A_PtrSize + 8,"UInt")
W := NumGet(PaintStruct,A_PtrSize + 12,"UInt") - X
H := NumGet(PaintStruct,A_PtrSize + 16,"UInt") - Y
;create the GDI bitmap
hBitmap := 0
this.CheckStatus(DllCall("gdiplus\GdipCreateHBITMAPFromBitmap","UPtr",this.Surface.pBitmap,"UPtr*",hBitmap,"UInt",0x000000)
,"GdipCreateHBITMAPFromBitmap","Could not convert GDI+ bitmap to GDI bitmap")
;select the bitmap into the memory device context
hOriginalBitmap := DllCall("SelectObject","UPtr",this.hMemoryDC,"UPtr",hBitmap,"UPtr")
If !hOriginalBitmap
throw Exception("INTERNAL_ERROR",A_ThisFunc,"Could not select bitmap into memory device context (error in SelectObject)")
;transfer bitmap from memory device context to window device context
If !DllCall("BitBlt","UPtr",hWindowDC,"Int",X,"Int",Y,"Int",W,"Int",H,"UPtr",this.hMemoryDC,"Int",X,"Int",Y,"UInt",0xCC0020) ;SRCCOPY
throw Exception("INTERNAL_ERROR",A_ThisFunc,"Could not transfer bitmap data from memory device context to window device context (error in BitBlt)")
;deselect the bitmap from the memory device context
If !DllCall("SelectObject","UPtr",this.hMemoryDC,"UPtr",hOriginalBitmap,"UPtr")
throw Exception("INTERNAL_ERROR",A_ThisFunc,"Could not deselect bitmap from memory device context (error in SelectObject)")
;delete the bitmap
If !DllCall("DeleteObject","UPtr",hBitmap)
throw Exception("INTERNAL_ERROR",A_ThisFunc,"Could not delete bitmap (error in DeleteObject)")
}
;finish painting window
DllCall("EndPaint","UPtr",hWindow,"UPtr",&PaintStruct)
Return, 0
}
StubCheckStatus(Result,Name,Message)
{
Return, this
}
CheckStatus(Result,Name,Message)
{
static StatusValues := ["Status.GenericError"
,"Status.InvalidParameter"
,"Status.OutOfMemory"
,"Status.ObjectBusy"
,"Status.InsufficientBuffer"
,"Status.NotImplemented"
,"Status.Win32Error"
,"Status.WrongState"
,"Status.Aborted"
,"Status.FileNotFound"
,"Status.ValueOverflow"
,"Status.AccessDenied"
,"Status.UnknownImageFormat"
,"Status.FontFamilyNotFound"
,"Status.FontStyleNotFound"
,"Status.NotTrueTypeFont"
,"Status.UnsupportedGdiplusVersion"
,"Status.GdiplusNotInitialized"
,"Status.PropertyNotFound"
,"Status.PropertyNotSupported"
,"Status.ProfileNotFound"]
If Result != 0 ;Status.Ok
throw Exception("INTERNAL_ERROR",-1,Message . " (GDI+ error " . StatusValues[Result] . " in " . Name . ")")
Return, this
}
}
class Surface
{
__New(Width = 1,Height = 1)
{
ObjInsert(this,"",Object())
If Width < 1
throw Exception("INVALID_INPUT",-1,"Invalid width: " . Width)
If Height < 1
throw Exception("INVALID_INPUT",-1,"Invalid height: " . Height)
pBitmap := 0
this.CheckStatus(DllCall("gdiplus\GdipCreateBitmapFromScan0","Int",Width,"Int",Height,"Int",0,"Int",0x26200A,"UPtr",0,"UPtr*",pBitmap) ;PixelFormat32bppARGB
,"GdipCreateBitmapFromScan0","Could not create bitmap")
this.pBitmap := pBitmap
;create a graphics object
pGraphics := 0
this.CheckStatus(DllCall("gdiplus\GdipGetImageGraphicsContext","UPtr",this.pBitmap,"UPtr*",pGraphics)
,"GdipGetImageGraphicsContext","Could not obtain graphics object")
this.pGraphics := pGraphics
this.States := []
this.Width := Width
this.Height := Height
this.Interpolation := "None"
this.Smooth := "None"
this.Compositing := "Blend"
}
__Get(Key)
{
If (Key != "" && Key != "base")
Return, this[""][Key]
}
__Set(Key,Value)
{
static InterpolationStyles := {None: 5 ;InterpolationMode.InterpolationModeNearestNeighbor
,Linear: 6 ;InterpolationMode.InterpolationModeHighQualityBilinear
,Cubic: 7} ;InterpolationMode.InterpolationModeHighQualityBicubic
static SmoothStyles := {None: 3 ;SmoothingMode.SmoothingModeNone
,Good: 4 ;SmoothingMode.SmoothingModeAntiAlias8x4
,Best: 5} ;SmoothingMode.SmoothingModeAntiAlias8x8
static CompositingStyles := {Blend: 0 ;CompositingMode.CompositingModeSourceOver
,Overwrite: 1} ;CompositingMode.CompositingModeSourceCopy
If (Key = "Interpolation")
{
If !InterpolationStyles.HasKey(Value)
throw Exception("INVALID_INPUT",-1,"Invalid interpolation mode: " . Value)
this.CheckStatus(DllCall("gdiplus\GdipSetInterpolationMode","UPtr",this.pGraphics,"UInt",InterpolationStyles[Value])
,"GdipSetInterpolationMode","Could not set interpolation mode")
}
Else If (Key = "Smooth")
{
If !SmoothStyles.HasKey(Value)
throw Exception("INVALID_INPUT",-1,"Invalid smooth mode: " . Value)
this.CheckStatus(DllCall("gdiplus\GdipSetSmoothingMode","UPtr",this.pGraphics,"UInt",SmoothStyles[Value])
,"GdipSetSmoothingMode","Could not set smooth mode")
}
Else If (Key = "Compositing")
{
If !CompositingStyles.HasKey(Value)
throw Exception("INVALID_INPUT",-1,"Invalid compositing mode: " . Value)
this.CheckStatus(DllCall("gdiplus\GdipSetCompositingMode","UPtr",this.pGraphics,"UInt",CompositingStyles[Value])
,"GdipSetCompositingMode","Could not set compositing mode")
}
this[""][Key] := Value
Return, Value
}
__Delete()
{
;delete graphics object
Result := DllCall("gdiplus\GdipDeleteGraphics","UPtr",this.pGraphics)
If Result != 0 ;Status.Ok
{
DllCall("gdiplus\GdipDisposeImage","UPtr",this.pBitmap) ;delete bitmap object
this.CheckStatus(Result,"GdipDeleteGraphics","Could not delete graphics object")
}
;delete bitmap object
this.CheckStatus(DllCall("gdiplus\GdipDisposeImage","UPtr",this.pBitmap)
,"GdipDisposeImage","Could not delete bitmap pointer")
}
Load(Path) ;wip: document this
{
Attributes := FileExist(Path)
If !Attributes ;path does not exist
throw Exception("INVALID_INPUT",-1,"Invalid path: " . Path)
If InStr(Attributes,"D") ;path is not a file
throw Exception("INVALID_INPUT",-1,"Invalid file: " . Path)
;create bitmap and obtain dimensions
pBitmap := 0
this.CheckStatus(DllCall("gdiplus\GdipCreateBitmapFromFile", "WStr",Path,"UPtr*",pBitmap) ;wip: should use higher level of exception as should CreateBitmap()
,"GdipCreateBitmapFromFile","Could not create bitmap from file")
Width := 0
this.CheckStatus(DllCall("gdiplus\GdipGetImageWidth","UPtr",pBitmap,"UInt*",Width)
,"GdipGetImageWidth","Could not obtain image width")
Height := 0
this.CheckStatus(DllCall("gdiplus\GdipGetImageHeight","UPtr",pBitmap,"UInt*",Height)
,"GdipGetImageHeight","Could not obtain image height")
this.pBitmap := pBitmap
this.Width := Width
this.Height := Height
Return, this
}
Save(Path)
{
;wip: implement and document this
Return, this
}
Clone(Width = "",Height = "")
{
Copy := new this.base(this.Width,this.Height)
;wip: clone the bitmap contents and settings and resize it
Return, Copy
}
Clear(Color = 0x00000000)
{
If Color Is Not Integer
throw Exception("INVALID_INPUT",-1,"Invalid color: " . Color)
Return, this.CheckStatus(DllCall("gdiplus\GdipGraphicsClear","UPtr",this.pGraphics,"UInt",Color)
,"GdipGraphicsClear","Could not clear graphics")
}
Text(Brush,Font,Value,X,Y,W = "",H = "")
{
this.CheckBrush(Brush)
this.CheckFont(Font)
;determine dimensions automatically if not specified
If (W = "")
W := 0
If (H = "")
H := 0
;create bounding rectangle
this.CheckRectangle(X,Y,W,H)
VarSetCapacity(Rectangle,16)
NumPut(X,Rectangle,0,"Float")
NumPut(Y,Rectangle,4,"Float")
NumPut(W,Rectangle,8,"Float")
NumPut(H,Rectangle,12,"Float")
Return, this.CheckStatus(DllCall("gdiplus\GdipDrawString"
,"UPtr",this.pGraphics ;graphics handle
,"WStr",Value ;string value
,"Int",-1 ;null terminated
,"UPtr",Font.hFont ;font handle
,"UPtr",&Rectangle ;bounding rectangle
,"UPtr",Font.hFormat ;string format
,"UPtr",Brush.pBrush) ;fill brush
,"GdipDrawString","Could not draw text")
}
GetPixel(X,Y,ByRef Color)
{
this.CheckPoint(X,Y)
If (X < 0 || X > this.Width)
throw Exception("INVALID_INPUT",-1,"Invalid X-axis coordinate: " . X)
If (Y < 0 || Y > this.Height)
throw Exception("INVALID_INPUT",-1,"Invalid Y-axis coordinate: " . Y)
Return, this.CheckStatus(DllCall("gdiplus\GdipBitmapGetPixel","UPtr",this.pBitmap,"Int",X,"Int",Y,"UInt*",Color)
,"GdipBitmapGetPixel","Could not obtain pixel from bitmap")
}
SetPixel(X,Y,Color)
{
this.CheckPoint(X,Y)
If (X < 0 || X > this.Width)
throw Exception("INVALID_INPUT",-1,"Invalid X-axis coordinate: " . X)
If (Y < 0 || Y > this.Height)
throw Exception("INVALID_INPUT",-1,"Invalid Y-axis coordinate: " . Y)
If Color Is Not Integer
throw Exception("INVALID_INPUT",-1,"Invalid color: " . Color)
Return, this.CheckStatus(DllCall("gdiplus\GdipBitmapSetPixel","UPtr",this.pBitmap,"Int",X,"Int",Y,"UInt",Color)
,"GdipBitmapSetPixel","Could not set bitmap pixel")
}
Draw(Surface,X = 0,Y = 0,W = "",H = "",SourceX = 0,SourceY = 0,SourceW = "",SourceH = "")
{
If !Surface.pBitmap
throw Exception("INVALID_INPUT",-1,"Invalid surface: " . Surface)
If (W = "")
W := this.Width
If (H = "")
H := this.Height
If (SourceW = "")
SourceW := Surface.Width
If (SourceH = "")
SourceH := Surface.Height
this.CheckRectangle(X,Y,W,H)
this.CheckRectangle(SourceX,SourceY,SourceW,SourceH)
Return, this.CheckStatus(DllCall("gdiplus\GdipDrawImageRectRect","UPtr",this.pGraphics,"UPtr",Surface.pBitmap
,"Float",X,"Float",Y,"Float",W,"Float",H
,"Float",SourceX,"Float",SourceY,"Float",SourceW,"Float",SourceH
,"Int",2,"UPtr",0,"UPtr",0,"UPtr",0) ;Unit.UnitPixel
,"GdipDrawImageRectRect","Could not transfer image data to surface")
}
DrawArc(Pen,X,Y,W,H,Start,Sweep)
{
this.CheckPen(Pen)
this.CheckSector(X,Y,W,H,Start,Sweep)
Return, this.CheckStatus(DllCall("gdiplus\GdipDrawArc","UPtr",this.pGraphics,"UPtr",Pen.pPen,"Float",X,"Float",Y,"Float",W,"Float",H,"Float",Start - 90,"Float",Sweep)
,"GdipDrawArc","Could not draw arc")
}
DrawCurve(Pen,Points,Closed = False,Tension = 1)
{
this.CheckPen(Pen)
Length := this.CheckPoints(Points,PointArray)
If Tension Not Between 0 And 1
throw Exception("INVALID_INPUT",-1,"Invalid curve tension: " . Tension)
If Closed
Return, this.CheckStatus(DllCall("gdiplus\GdipDrawClosedCurve2","UPtr",this.pGraphics,"UPtr",Pen.pPen,"UPtr",&PointArray,"Int",Length,"Float",Tension)
,"GdipDrawClosedCurve2","Could not draw curve")
Return, this.CheckStatus(DllCall("gdiplus\GdipDrawCurve2","UPtr",this.pGraphics,"UPtr",Pen.pPen,"UPtr",&PointArray,"Int",Length,"Float",Tension)
,"GdipDrawCurve2","Could not draw curve")
}
DrawEllipse(Pen,X,Y,W,H)
{
this.CheckPen(Pen)
this.CheckRectangle(X,Y,W,H)
Return, this.CheckStatus(DllCall("gdiplus\GdipDrawEllipse","UPtr",this.pGraphics,"UPtr",Pen.pPen,"Float",X,"Float",Y,"Float",W,"Float",H)
,"GdipDrawEllipse","Could not draw ellipse")
}
DrawPie(Pen,X,Y,W,H,Start,Sweep)
{
this.CheckPen(Pen)
this.CheckSector(X,Y,W,H,Start,Sweep)
Return, this.CheckStatus(DllCall("gdiplus\GdipDrawPie","UPtr",this.pGraphics,"UPtr",Pen.pPen,"Float",X,"Float",Y,"Float",W,"Float",H,"Float",Start - 90,"Float",Sweep)
,"GdipDrawPie","Could not draw pie")
}
DrawPolygon(Pen,Points)
{
this.CheckPen(Pen)
Length := this.CheckPoints(Points,PointArray)
Return, this.CheckStatus(DllCall("gdiplus\GdipDrawPolygon","UPtr",this.pGraphics,"UPtr",Pen.pPen,"UPtr",&PointArray,"Int",Length)
,"GdipDrawPolygon","Could not draw polygon")
}
DrawRectangle(Pen,X,Y,W,H)
{
this.CheckPen(Pen)
this.CheckRectangle(X,Y,W,H)
Return, this.CheckStatus(DllCall("gdiplus\GdipDrawRectangle","UPtr",this.pGraphics,"UPtr",Pen.pPen,"Float",X,"Float",Y,"Float",W,"Float",H)
,"GdipDrawRectangle","Could not draw rectangle")
}
FillCurve(Brush,Points)
{
this.CheckBrush(Brush)
Length := this.CheckPoints(Points,PointArray)
Return, this.CheckStatus(DllCall("gdiplus\GdipFillClosedCurve","UPtr",this.pGraphics,"UPtr",Brush.pBrush,"UPtr",&PointArray,"Int",Length)
,"GdipFillClosedCurve","Could not fill curve")
}
FillEllipse(Brush,X,Y,W,H)
{
this.CheckBrush(Brush)
this.CheckRectangle(X,Y,W,H)
Return, this.CheckStatus(DllCall("gdiplus\GdipFillEllipse","UPtr",this.pGraphics,"UPtr",Brush.pBrush,"Float",X,"Float",Y,"Float",W,"Float",H)
,"GdipFillEllipse","Could not fill ellipse")
}
FillPie(Brush,X,Y,W,H,Start,Sweep)
{
this.CheckBrush(Brush)
this.CheckSector(X,Y,W,H,Start,Sweep)
Return, this.CheckStatus(DllCall("gdiplus\GdipFillPie","UPtr",this.pGraphics,"UPtr",Brush.pBrush,"Float",X,"Float",Y,"Float",W,"Float",H,"Float",Start - 90,"Float",Sweep)
,"GdipFillPie","Could not fill pie")
}
FillPolygon(Brush,Points)
{
this.CheckBrush(Brush)
Length := this.CheckPoints(Points,PointArray)
Return, this.CheckStatus(DllCall("gdiplus\GdipFillPolygon","UPtr",this.pGraphics,"UPtr",Brush.pBrush,"UPtr",&PointArray,"Int",Length)
,"GdipFillPolygon","Could not fill polygon")
}
FillRectangle(Brush,X,Y,W,H)
{
this.CheckBrush(Brush)
this.CheckRectangle(X,Y,W,H)
Return, this.CheckStatus(DllCall("gdiplus\GdipFillRectangle","UPtr",this.pGraphics,"UPtr",Brush.pBrush,"Float",X,"Float",Y,"Float",W,"Float",H)
,"GdipFillRectangle","Could not fill rectangle")
}
Line(Pen,X1,Y1,X2,Y2)
{
this.CheckPen(Pen)
this.CheckLine(X1,Y1,X2,Y2)
Return, this.CheckStatus(DllCall("gdiplus\GdipDrawLine","UPtr",this.pGraphics,"UPtr",Pen.pPen,"Float",X1,"FLoat",Y1,"Float",X2,"Float",Y2)
,"GdipDrawLine","Could not draw line")
}
Lines(Pen,Points)
{
this.CheckPen(Pen)
Length := this.CheckPoints(Points,PointArray)
Return, this.CheckStatus(DllCall("gdiplus\GdipDrawLines","UPtr",this.pGraphics,"UPtr",Pen.pPen,"UPtr",&PointArray,"Int",Length)
,"GdipDrawLines","Could not draw lines")
}
Push()
{
State := 0
this.CheckStatus(DllCall("gdiplus\GdipSaveGraphics","UPtr",this.pGraphics,"UInt*",State) ;GraphicsState
,"GdipSaveGraphics","Could not save graphics state")
this.States.Insert(State)
Return, this
}
Pop()
{
If !this.States.HasKey(1) ;stack is empty
throw Exception("INVALID_INPUT",-1,"Invalid transformation stack entries")
State := this.States.Remove()
this.CheckStatus(DllCall("gdiplus\GdipRestoreGraphics","UPtr",this.pGraphics,"UInt",State) ;GraphicsState
,"GdipRestoreGraphics","Could not restore graphics state")
Return, this
}
Translate(X,Y)
{
this.CheckPoint(X,Y)
Return, this.CheckStatus(DllCall("gdiplus\GdipTranslateWorldTransform","UPtr",this.pGraphics,"Float",X,"Float",Y,"UInt",0) ;MatrixOrder.MatrixOrderPrepend
,"GdipTranslateWorldTransform","Could not apply translation matrix")
}
Rotate(Angle)
{
If Angle Is Not Number
throw Exception("INVALID_INPUT",-1,"Invalid angle: " . Angle)
Return, this.CheckStatus(DllCall("gdiplus\GdipRotateWorldTransform","UPtr",this.pGraphics,"Float",Angle,"UInt",0) ;MatrixOrder.MatrixOrderPrepend
,"GdipRotateWorldTransform","Could not apply rotation matrix")
}
Scale(X,Y)
{
this.CheckPoint(X,Y)
Return, this.CheckStatus(DllCall("gdiplus\GdipScaleWorldTransform","UPtr",this.pGraphics,"Float",X,"Float",Y,"UInt",0) ;MatrixOrder.MatrixOrderPrepend
,"GdipScaleWorldTransform","Could not apply scale matrix")
}
StubCheckStatus(Result,Name,Message)
{
Return, this
}
StubCheckPen(Pen)
{
}
StubCheckBrush(Brush)
{
}
StubCheckFormat(Brush)
{
}
StubCheckLine(X1,Y1,X2,Y2)
{
}
StubCheckRectangle(X,Y,W,H)
{
}
StubCheckSector(X,Y,W,H,Start,Sweep)
{
}
StubCheckPoint(X,Y)
{
}
StubCheckPoints(Points,ByRef PointArray)
{
Length := Points.MaxIndex()
VarSetCapacity(PointArray,Length << 3)
Offset := 0
Loop, %Length%
{
Point := Points[A_Index]
NumPut(Point[1],PointArray,Offset,"Float"), Offset += 4
NumPut(Point[2],PointArray,Offset,"Float"), Offset += 4
}
Return, Length
}
CheckStatus(Result,Name,Message)
{
static StatusValues := ["Status.GenericError"
,"Status.InvalidParameter"
,"Status.OutOfMemory"
,"Status.ObjectBusy"
,"Status.InsufficientBuffer"
,"Status.NotImplemented"
,"Status.Win32Error"
,"Status.WrongState"
,"Status.Aborted"
,"Status.FileNotFound"
,"Status.ValueOverflow"
,"Status.AccessDenied"
,"Status.UnknownImageFormat"
,"Status.FontFamilyNotFound"
,"Status.FontStyleNotFound"
,"Status.NotTrueTypeFont"
,"Status.UnsupportedGdiplusVersion"
,"Status.GdiplusNotInitialized"
,"Status.PropertyNotFound"
,"Status.PropertyNotSupported"
,"Status.ProfileNotFound"]
If Result != 0 ;Status.Ok
throw Exception("INTERNAL_ERROR",-1,Message . " (GDI+ error " . StatusValues[Result] . " in " . Name . ")")
Return, this
}
CheckPen(Pen)
{
If !Pen.pPen
throw Exception("INVALID_INPUT",-2,"Invalid pen: " . Pen)
}
CheckBrush(Brush)
{
If !Brush.pBrush
throw Exception("INVALID_INPUT",-2,"Invalid brush: " . Brush)
}
CheckFont(Font)
{
If !(Font.hFontFamily && Font.hFont && Font.hFormat)
throw Exception("INVALID_INPUT",-2,"Invalid font: " . Font)
}
CheckLine(X1,Y1,X2,Y2)
{
If X1 Is Not Number
throw Exception("INVALID_INPUT",-2,"Invalid X-axis coordinate 1: " . X1)
If Y1 Is Not Number
throw Exception("INVALID_INPUT",-2,"Invalid Y-axis coordinate 1: " . Y1)
If X2 Is Not Number
throw Exception("INVALID_INPUT",-2,"Invalid X-axis coordinate 2: " . X2)
If Y2 Is Not Number
throw Exception("INVALID_INPUT",-2,"Invalid Y-axis coordinate 2: " . Y2)
}
CheckRectangle(X,Y,W,H)
{
If X Is Not Number
throw Exception("INVALID_INPUT",-2,"Invalid X-axis coordinate: " . X)
If Y Is Not Number
throw Exception("INVALID_INPUT",-2,"Invalid Y-axis coordinate: " . Y)
If W < 0
throw Exception("INVALID_INPUT",-2,"Invalid width: " . W)
If H < 0
throw Exception("INVALID_INPUT",-2,"Invalid height: " . H)
}
CheckSector(X,Y,W,H,Start,Sweep)
{
If X Is Not Number
throw Exception("INVALID_INPUT",-2,"Invalid X-axis coordinate: " . X)
If Y Is Not Number
throw Exception("INVALID_INPUT",-2,"Invalid Y-axis coordinate: " . Y)
If W < 0
throw Exception("INVALID_INPUT",-2,"Invalid width: " . W)
If H < 0
throw Exception("INVALID_INPUT",-2,"Invalid height: " . H)
If Start Is Not Number
throw Exception("INVALID_INPUT",-2,"Invalid start angle: " . Start)
If Sweep Is Not Number
throw Exception("INVALID_INPUT",-2,"Invalid sweep angle: " . Sweep)
}
CheckPoint(X,Y)
{
If X Is Not Number
throw Exception("INVALID_INPUT",-2,"Invalid X-axis coordinate: " . X)
If Y Is Not Number
throw Exception("INVALID_INPUT",-2,"Invalid Y-axis coordinate: " . Y)
}
CheckPoints(Points,ByRef PointArray)
{
Length := Points.MaxIndex()
If !Length
throw Exception("INVALID_INPUT",-2,"Invalid point set: " . Points)
VarSetCapacity(PointArray,Length << 3)
Offset := 0
Loop, %Length%
{
Point := Points[A_Index]
If !IsObject(Point)
throw Exception("INVALID_INPUT",-2,"Invalid point: " . Point)
PointX := Point[1]
PointY := Point[2]
If PointX Is Not Number
throw Exception("INVALID_INPUT",-2,"Invalid X-axis coordinate: " . PointX)
If PointY Is Not Number
throw Exception("INVALID_INPUT",-2,"Invalid Y-axis coordinate: " . PointX)
NumPut(PointX,PointArray,Offset,"Float"), Offset += 4
NumPut(PointY,PointArray,Offset,"Float"), Offset += 4
}
Return, Length
}
}
class Pen
{
__New(Color = 0xFFFFFFFF,Width = 1)
{
If Color Is Not Integer
throw Exception("INVALID_INPUT",-1,"Invalid color: " . Color)
If Width Is Not Number
throw Exception("INVALID_INPUT",-1,"Invalid width: " . Width)
ObjInsert(this,"",Object())
;create the pen
pPen := 0
this.CheckStatus(DllCall("gdiplus\GdipCreatePen1","UInt",Color,"Float",Width,"UInt",2,"UPtr*",pPen) ;Unit.UnitPixel
,"GdipCreatePen1","Could not create pen")
this.pPen := pPen
;set properties
this.Color := Color
this.Width := Width
this.Join := "Miter"
this.Type := "Solid"
this.StartCap := "Flat"
this.EndCap := "Flat"
}
__Delete()
{
;delete the pen
this.CheckStatus(DllCall("gdiplus\GdipDeletePen","UPtr",this.pPen)
,"GdipDeletePen","Could not delete pen")
}
__Get(Key)
{
If (Key != "" && Key != "base")
Return, this[""][Key]
}
__Set(Key,Value)
{
static JoinStyles := Object("Miter",0 ;LineJoin.LineJoinMiter
,"Bevel",1 ;LineJoin.LineJoinBevel
,"Round",2) ;LineJoin.LineJoinRound
static TypeStyles := Object("Solid",0 ;DashStyleSolid
,"Dash",1 ;DashStyleDash
,"Dot",2 ;DashStyleDot
,"DashDot",3) ;DashStyleDashDot
static CapStyles := Object("Flat",0 ;LineCap.LineCapFlat
,"Square",1 ;LineCap.LineCapSquare
,"Round",2 ;LineCap.LineCapRound
,"Triangle",3) ;LineCap.LineCapTriangle
If (Key = "Color") ;set pen color
{
If Value Is Not Integer
throw Exception("INVALID_INPUT",-1,"Invalid color: " . Value)
this.CheckStatus(DllCall("gdiplus\GdipSetPenColor","UPtr",this.pPen,"UInt",Value)
,"GdipSetPenColor","Could not set pen color")
}
Else If (Key = "Width") ;set pen width
{
If Value Is Not Number
throw Exception("INVALID_INPUT",-1,"Invalid width: " . Value)
this.CheckStatus(DllCall("gdiplus\GdipSetPenWidth","UPtr",this.pPen,"Float",Value)
,"GdipSetPenWidth","Could not set pen width")
}
Else If (Key = "Join") ;set pen line join style
{
If !JoinStyles.HasKey(Value)
throw Exception("INVALID_INPUT",-1,"Invalid pen join: " . Value)
this.CheckStatus(DllCall("gdiplus\GdipSetPenLineJoin","UPtr",this.pPen,"UInt",JoinStyles[Value])
,"GdipSetPenLineJoin","Could not set pen join")
}
Else If (Key = "Type") ;set pen type
{
If !TypeStyles.HasKey(Value)
throw Exception("INVALID_INPUT",-1,"Invalid pen type: " . Value)
this.CheckStatus(DllCall("gdiplus\GdipSetPenDashStyle","UPtr",this.pPen,"UInt",TypeStyles[Value])
,"GdipSetPenDashStyle","Could not set pen type")
}
Else If (Key = "StartCap") ;set pen start cap
{
If !CapStyles.HasKey(Value)
throw Exception("INVALID_INPUT",-1,"Invalid pen start cap: " . Value)
this.CheckStatus(DllCall("gdiplus\GdipSetPenStartCap","UPtr",this.pPen,"UInt",CapStyles[Value])
,"GdipSetPenStartCap","Could not set pen start cap")
}
Else If (Key = "EndCap") ;set pen end cap
{
If !CapStyles.HasKey(Value)
throw Exception("INVALID_INPUT",-1,"Invalid pen end cap: " . Value)
this.CheckStatus(DllCall("gdiplus\GdipSetPenEndCap","UPtr",this.pPen,"UInt",CapStyles[Value])
,"GdipSetPenEndCap","Could not set pen end cap")
}
this[""][Key] := Value
Return, Value
}
StubCheckStatus(Result,Name,Message)
{
Return, this
}
CheckStatus(Result,Name,Message)
{
static StatusValues := ["Status.GenericError"
,"Status.InvalidParameter"
,"Status.OutOfMemory"
,"Status.ObjectBusy"
,"Status.InsufficientBuffer"
,"Status.NotImplemented"
,"Status.Win32Error"
,"Status.WrongState"
,"Status.Aborted"
,"Status.FileNotFound"
,"Status.ValueOverflow"
,"Status.AccessDenied"
,"Status.UnknownImageFormat"
,"Status.FontFamilyNotFound"
,"Status.FontStyleNotFound"
,"Status.NotTrueTypeFont"
,"Status.UnsupportedGdiplusVersion"
,"Status.GdiplusNotInitialized"
,"Status.PropertyNotFound"
,"Status.PropertyNotSupported"
,"Status.ProfileNotFound"]
If Result != 0 ;Status.Ok
throw Exception("INTERNAL_ERROR",-1,Message . " (GDI+ error " . StatusValues[Result] . " in " . Name . ")")
Return, this
}
}
class Brush
{
__New(Color = 0xFFFFFFFF)
{
If Color Is Not Integer
throw Exception("INVALID_INPUT",-1,"Invalid color: " . Color)
ObjInsert(this,"",Object())
;create the brush
pBrush := 0
this.CheckStatus(DllCall("gdiplus\GdipCreateSolidFill","UInt",Color,"UPtr*",pBrush)
,"GdipCreateSolidFill","Could not create brush")
this.pBrush := pBrush
this.Color := Color
}
__Delete()
{
;delete the brush
this.CheckStatus(DllCall("gdiplus\GdipDeleteBrush","UPtr",this.pBrush)
,"GdipDeleteBrush","Could not delete brush")
}
__Get(Key)
{
If (Key != "" && Key != "base")
Return, this[""][Key]
}
__Set(Key,Value)
{
If (Key = "Color") ;set brush color
{
If Value Is Not Integer
throw Exception("INVALID_INPUT",-1,"Invalid color: " . Value)
this.CheckStatus(DllCall("gdiplus\GdipSetSolidFillColor","UPtr",this.pBrush,"UInt",Value)
,"GdipSetSolidFillColor","Could not set brush color")
}
this[""][Key] := Value
Return, Value
}
StubCheckStatus(Result,Name,Message)
{
Return, this
}
CheckStatus(Result,Name,Message)
{
static StatusValues := ["Status.GenericError"
,"Status.InvalidParameter"
,"Status.OutOfMemory"
,"Status.ObjectBusy"
,"Status.InsufficientBuffer"
,"Status.NotImplemented"
,"Status.Win32Error"
,"Status.WrongState"
,"Status.Aborted"
,"Status.FileNotFound"
,"Status.ValueOverflow"
,"Status.AccessDenied"
,"Status.UnknownImageFormat"
,"Status.FontFamilyNotFound"
,"Status.FontStyleNotFound"
,"Status.NotTrueTypeFont"
,"Status.UnsupportedGdiplusVersion"
,"Status.GdiplusNotInitialized"
,"Status.PropertyNotFound"
,"Status.PropertyNotSupported"
,"Status.ProfileNotFound"]
If Result != 0 ;Status.Ok
throw Exception("INTERNAL_ERROR",-1,Message . " (GDI+ error " . StatusValues[Result] . " in " . Name . ")")
Return, this
}
}
class Font
{
static _ := Canvas.Font.Initialize()
Initialize()
{
;create device context for graphics object
this.hDC := DllCall("CreateCompatibleDC","UPtr",0,"UPtr")
If !this.hDC
throw Exception("INTERNAL_ERROR",A_ThisFunc,"Could not create device context (error in CreateCompatibleDC)")
;create a graphics object
pGraphics := 0
this.CheckStatus(DllCall("gdiplus\GdipCreateFromHDC","UPtr",this.hDC,"UPtr*",pGraphics)
,"GdipCreateFromHDC","Could not create graphics object")
this.pGraphics := pGraphics
}
__New(Typeface,Size)
{
If Size Is Not Number
throw Exception("INVALID_INPUT",-1,"Invalid size: " . Size)
If Size <= 0
throw Exception("INVALID_INPUT",-1,"Invalid size: " . Size)
ObjInsert(this,"",Object())
;create string format
hFormat := 0
this.CheckStatus(DllCall("gdiplus\GdipCreateStringFormat","Int",0x800,"Int",0,"Ptr*",hFormat) ;StringFormat.StringFormatFlagsMeasureTrailingSpaces, LANG_NEUTRAL
,"GdipCreateStringFormat","Could not create string format")
this.hFormat := hFormat
this[""].Typeface := Typeface
this[""].Size := Size
this[""].Bold := False
this[""].Italic := False
this[""].Underline := False
this[""].Strikeout := False
this.UpdateFontFamily()
this.UpdateFont()
}
UpdateFontFamily()
{
;delete previous font family if present
If this.hFontFamily
this.CheckStatus(DllCall("gdiplus\GdipDeleteFontFamily","UPtr",this.hFontFamily)
,"GdipDeleteFontFamily","Could not delete font family")
;create font family
hFontFamily := 0
this.CheckStatus(DllCall("gdiplus\GdipCreateFontFamilyFromName","WStr",this.Typeface,"UPtr",0,"UPtr*",hFontFamily)
,"GdipCreateFontFamilyFromName","Could not create font family")
this.hFontFamily := hFontFamily
}
UpdateFont()
{
;delete previous font if present
If this.hFont
this.CheckStatus(DllCall("gdiplus\GdipDeleteFont","UPtr",this.hFont)
,"GdipDeleteFont","Could not delete font")
;determine font style
Style := 0 ;FontStyle.FontStyleRegular
If this.Bold
Style |= 1 ;FontStyle.FontStyleBold
If this.Italic
Style |= 2 ;FontStyle.FontStyleItalic
If this.Underline
Style |= 4 ;FontStyle.FontStyleUnderline
If this.Strikeout
Style |= 8 ;FontStyle.FontStyleStrikeout
;create font
hFont := 0, this.CheckStatus(DllCall("gdiplus\GdipCreateFont","UPtr",this.hFontFamily,"Float",this.Size,"Int",Style,"UInt",2,"UPtr*",hFont) ;Unit.UnitPixel
,"GdipCreateFont","Could not create font")
this.hFont := hFont
}
__Delete()
{
;delete font
Result := DllCall("gdiplus\GdipDeleteFont","UPtr",this.hFont)
If Result != 0
{
DllCall("gdiplus\GdipDeleteFontFamily","UPtr",this.hFontFamily) ;delete font family
DllCall("gdiplus\GdipDeleteStringFormat","UPtr",this.hFormat) ;delete string format
this.CheckStatus(Result,"GdipDeleteFont","Could not delete font")
Return
}
;delete font family
Result := DllCall("gdiplus\GdipDeleteFontFamily","UPtr",this.hFontFamily)
If Result != 0 ;Status.Ok
{
DllCall("gdiplus\GdipDeleteStringFormat","UPtr",this.hFormat) ;delete string format
this.CheckStatus(Result,"GdipDeleteFontFamily","Could not delete font family")
Return
}
;delete string format
this.CheckStatus(DllCall("gdiplus\GdipDeleteStringFormat","UPtr",this.hFormat)
,"GdipDeleteStringFormat","Could not delete string format")
}
__Get(Key)
{
If (Key != "" && Key != "base")
Return, this[""][Key]
}
__Set(Key,Value)
{
static AlignStyles := Object("Left", 0 ;StringAlignment.StringAlignmentNear
,"Center",1 ;StringAlignment.StringAlignmentCenter
,"Right", 2) ;StringAlignment.StringAlignmentFar
If (Key = "Size")
{
If Value Is Not Number
throw Exception("INVALID_INPUT",-1,"Invalid size: " . Value)
If Value <= 0
throw Exception("INVALID_INPUT",-1,"Invalid size: " . Value)
this[""].Size := Value
this.UpdateFont()
}
Else If (Key = "Typeface")
{
this[""].Typeface := Value
this.UpdateFontFamily()
this.UpdateFont()
}
Else If (Key = "Bold" || Key = "Italic" || Key = "Underline" || Key = "Strikeout")
{
this[""][Key] := Value
this.UpdateFont()
}
Else If (Key = "Align")
{
If !AlignStyles.HasKey(Value)
throw Exception("INVALID_INPUT",-1,"Invalid alignment: " . Value)
this.CheckStatus(DllCall("gdiplus\GdipSetStringFormatAlign","UPtr",this.hFormat,"UInt",AlignStyles[Value])
,"GdipSetStringFormatAlign","Could not set string format alignment")
this[""].Align := Value
}
Else
this[""][Key] := Value
Return, Value
}
Measure(Value,ByRef Width,ByRef Height)
{
VarSetCapacity(Rectangle,16,0)
VarSetCapacity(Bounds,16)
this.CheckStatus(DllCall("gdiplus\GdipMeasureString"
,"UPtr",this.base.pGraphics
,"WStr",Value ;string value
,"Int",-1 ;null terminated
,"UPtr",this.hFont ;font handle
,"UPtr",&Rectangle ;input bounds
,"UPtr",this.hFormat ;string format
,"UPtr",&Bounds ;output bounds
,"UPtr",0 ;output number of characters that can fit in input bounds
,"UPtr",0) ;output number of lines that can fit in input bounds
,"GdipMeasureString","Could not measure text bounds")
Width := NumGet(Bounds,8,"Float")
Height := NumGet(Bounds,12,"Float")
Return, this
}
StubCheckStatus(Result,Name,Message)
{
Return, this
}
CheckStatus(Result,Name,Message)
{
static StatusValues := ["Status.GenericError"
,"Status.InvalidParameter"
,"Status.OutOfMemory"
,"Status.ObjectBusy"
,"Status.InsufficientBuffer"
,"Status.NotImplemented"
,"Status.Win32Error"
,"Status.WrongState"
,"Status.Aborted"
,"Status.FileNotFound"
,"Status.ValueOverflow"
,"Status.AccessDenied"
,"Status.UnknownImageFormat"
,"Status.FontFamilyNotFound"
,"Status.FontStyleNotFound"
,"Status.NotTrueTypeFont"
,"Status.UnsupportedGdiplusVersion"
,"Status.GdiplusNotInitialized"
,"Status.PropertyNotFound"
,"Status.PropertyNotSupported"
,"Status.ProfileNotFound"]
If Result != 0 ;Status.Ok
throw Exception("INTERNAL_ERROR",-1,Message . " (GDI+ error " . StatusValues[Result] . " in " . Name . ")")
Return, this
}
}
}
;FIN DE classCanvas.ahk------------------------------------------------------------------------------------------------------------