可视化编程专栏

  

可视化编程意义

可视化编程是一个语言能力的提现,这个是AHK实现的可视化编程!本实例为一个公开分享的实例,为方便大家参考,特搬运转移到这里!

实例

实例的使用方法就是将实例替换掉类库的U()函数!欢迎大家!进一步创新分享!

;旋转的点
;~ u(){
	;~ f(r(,20,40)),f=0
	;~ while 17>++f,p:=s(t*3-f/9),a=0
		;~ loop 16
			;~ fc(w/2+s(r:=p+a++*pi/8)*f*h/35,h/2+c(r)*f*h/35,4,h(t/2+(16-f)/16))
;~ }

;旋转的线
;~ u(){
;~ f(),i=0,j=99
;~ loop,%j%
;~ dl(n:=w/2,m:=h/2,n+c(i/j*pi*2)*c(i/j*pi*4+t)*n,m+s(i/j*pi*2)*s(i/j*pi*4+t)*m,h(i++/j))
;~ }

;灯笼
;~ u(){
;~ f(),i=0,j=256
;~ loop,%j%
;~ fc(w/2+sin(i/j*pi)*cos(i/j*pi*32+t)*w/2,h*i/j,3,h(i++/j+t/8))
;~ }
;旋转立方体
;~ u()
;~ {
	;~ f()
	;~ q:=pi*2/3
	;~ loop,3
	;~ dl(j+c(d*q+t-u:=q/2)*j:=w/2,k:=h*2/3,n:=j+c(d*q+t)*j,l:=h/3)dl(j,0,n,l)dl(j,h,m:=j+c(++d*q+t-u)*j,k)dl(n,l,m,k)
;~ }

;诡异图像
;~ u(){
;~ y:=0,x=mod(++t|=0,w)
;~ Loop,%h%{
;~ sp(x,y++,i<30?h(i/30):0),a=b=i=0
;~ while,b*b+a*a<4&&++i<30
;~ a:=(a*a-b*b+x*3/w-2,b=2*a*b+y*2.5/h-5/4)
;~ }}

;一串字母
;~ u(){
;~ q=Q_q@FiRIf@_Ez@_P_@_BdH_@_@_UU@@
;~ f()
;~ loop,480
;~ (1<<z:=mod(d|0,5))&*(((t*5+y:=d++//5)&31)*2+&q)?fr(y*a:=w/96,a*z+h/2-a*2.5,a,a,h(t/5))
;~ }

;固定的飞鸟
;~ u(){
;~ l=DJCDHIPLOIPETCYDZE^C[G^F[IZRQZG[AYFXJVBQGRALGN
;~ i:=&l-2,b=2*a:=7/c:=31
;~ while,x:=*(i+=2)&c,y=*(i+=2)&c
;~ dl(a*w,b*h,w*a:=x/c,h*b:=y/c)
;~ }

;十字架
;~ u(){
;~ l=DJCDHIPLOIPETCYDZE^C[G^F[IZRQZG[AYFXJVBQGRALGN
;~ i:=&l-2,b=2*a:=7/c:=31
;~ while,x:=*(i+=2)&c,y=*(i+=2)&c
;~ dl(a*w,b*h,w*a:=x/c,h*b:=y/c)
;~ }


;画圈圈
;~ u(){
	;~ loop 3 {
		;~ i := A_Index
		;~ loop 3 {
			;~ a := 9*t
			;~ d := 4*t
			;~ x := (A_Index-0.5)/3 * w + s(a)*d
			;~ y := (i-0.5)/3 * h + c(a)*d
			;~ sp( x, y, h(t/9) )
		;~ }
	;~ }
;~ }

;喷绘效果
;~ u(i=.3){
	;~ j:=i?t-.2:t
	;~ y=-.5
	;~ while 4>++y,x=-.5
		;~ loop 4
			;~ fc(w/2+ ++x*s(j)*80,h/2+y*c(j)*80,a(s(j))*3+c(j)*3+5,c:=h(x/y*.98+t/99,.7-i))
	;~ i?u(0)
;~ }
;移动的花点
;~ u(i=1,y=-.5){
	;~ (t<1)?f(9999)
	;~ while 4>++y,x=-.5,j=t-.2*i
		;~ loop 4     
			;~ fc(++x*s(j/x)*80+w/2,h/2+y*c(j/y)*80,s(j)+c(j)+7-i,h(x/y,.7-i))
	;~ i?u(0)
;~ }

;下雪了
;~ u(i=0){
	;~ static s:=[]
	;~ if (f()t<1)
		;~ while 999>++i,s[i]:=r
			;~ Random r,0,% w
	;~ while 500>++i,a=i*2
		;~ sp(s[a+1]+s(t+i)*20,Mod(s[a]+t*99,h))
;~ }


;礼花
;~ u(r=1){
	;~ r?u(0)
	;~ p:=Mod(t+.1*r,q:=pi/2),i=0
	;~ loop 98
		;~ fc(w/2+s(a:=++i/24*q)*d:=(s(p)*15)**2,h/3+c(a)*d+(p*3)**3,p*7-r*3,h(t//q/3+i/2,452/d*r))
;~ }

;展开的花
;~ u(d=3,x=0){
	;~ while 256>++x,y=0
		;~ while 3>++y
			;~ fc(s(t*4-x/8+pi*y)*d*x+w/2,c(t*4-x/8+pi*y)*d*x+w/2,11,h(t/4+y/2))
;~ }

;球
;~ u() {
	;~ f()
	;~ Loop 2 {
		;~ i := A_Index
		;~ p := (Mod(t/9+a(t(i)),pi/2))
		;~ fc(s(t/99)*20+a(s(p))*w*(1+i/99),h-a(c(t+i/9))*h*c(p)**2-8,4,h(i/9))
	;~ }
;~ }

;球的轨迹线
;~ u(){
	;~ static x,y,a:=0.5,s
	;~ s+=(d,x+=a)
	;~ y+=s
	;~ if(y+8>h)
		;~ s*=-0.9,a*=0.97,y:=h-8
	;~ if(x<0||x+8>w)
		;~ a*=-1,x:=(x<0?0:h-8)
	;~ fc(x,y,4,h(t))
;~ }

;红心
;~ u(){
;~ i:=2*r:=A_Index/2
;~ fc(0,0,r,i)
;~ fc(w-i,0,r,i)
;~ fc(0,h-i,r,i)
;~ fc(w-i,h-i,r,i)
;~ if i<100
	;~ Sleep 1
;~ if i>5000
	;~ pause
;~ }
;上例子改进版
;~ u(){
;~ i:=2*r:=A_Index/2
;~ fc(0,0,r,h(t))
;~ fc(w-i,0,r,h(t))
;~ fc(0,h-i,r,h(t))
;~ fc(w-i,h-i,r,h(t))
;~ if i<100
	;~ Sleep 1
;~ if i>5000
	;~ pause
;~ }

;齿轮
;~ u(j=0,@=1){
	;~ f()
	;~ while 3>j,i=.5,@*=-1,x=j++*w/2
		;~ while 97>i,ᴀ=ɢ,ʀ=ᴇ,ɢ=x+s(p:=pi/48*i+t*@)*q:=(i&2?.26:.24)*w,ᴇ=h/2+c(p)*q
			;~ i++>1?dl(ɢ,ᴇ,ᴀ,ʀ)
;~ }
;飞线

;~ u(i=0) {
	;~ f()
	;~ while 9>i
		;~ dl(x:=i/9*w,y:=h/5+c(i+t+9)*h/3,x,b:=h/2+y)i++==0&&pi>y&&pi<b?k:=1
	;~ k?fc(6,pi+=GetKeyState("w")?-t/99:.1,9):pi:=t:=0
;~ }

;进出效果
;~ u(s=0){
	;~ while 63>++s
		;~ a:=w*(s-1)/128,fr(a+s(t*-2+s/7)*32,a+s-128+a/3,w-a*2,w-a*2+128,r(255,255,255,(s(t*-2+s/24)+1.1)/2.2))
;~ }

;星星
;~ u() {
	;~ static x=0,y=9,a=1
	;~ q:=x+s(a)*99,e=y+c(a)*99
	;~ q>w||e>h||q<0||e<0?a-=1.5:x:=q+0*y:=e
	;~ fc(q//8*8,e//8*8,2,r(w,,w,s(t*99)))
;~ }
;跳球球
;~ u(r=2,i=99) {
	;~ while i-->0,c=t-r*d/2,p=Mod(c/6+a(t(i)),1.5)
		;~ fc(a(s(p))*w//9*9-r,h-a(c(c+i/9))*h*c(p)**2//9*9-r-9,2+r,h(i/9,1-r*.4))
	;~ r?u(0)
;~ }
;跳跳球加强版
;~ u(r=2,i=80) {
	;~ while i-->0,c=t-r*d/2,p=Mod(c/6+a(t(i)),1.5)
		;~ fc(a(s(p+i))*w//9*9-r,h-a(c(c+i/9))*h*c(p)**2//9*9-r-9,2+r,h(i/9,1-r*.4))
	;~ r?u(0)
;~ }
;神奇的画圈圈,鼠标控制
;~ u(){
;~ static x=0,y=0
;~ fc(x-r:=9+s(t-d)*7,y-r,r,h(t-d,.5))
;~ MouseGetPos a,b
;~ b-=c(t)*9,x=x*.999+a/999,y=y*.998+b/w
;~ fc(x-r:=9+s(t)*7,y-r,r,h(t))
;~ }

;~ ;强迫症治疗
;~ u(){
;~ z:=pi*(3-Sqrt(5)),i:=0,r:=Sqrt(w/2*w/2+h/2*h/2)+5,l:=4,k:=l-1,t:=(r*r)/(l*l)
;~ Loop,%t%
;~ i++,r:=l*sqrt(i),a:=i*z,x:=r*c(a),y:=r*s(a),fc(w/2+x,h/2+y,k,h(a))
;~ }

;乱弹线
;~ u() {
;~ static x=0,y=9,a=1
;~ q:=x+s(a),e=y+c(a)
;~ q>w||e>h||q<0||e<0?a-=Mod(t,2)+1:x:=q+0*y:=e
;~ fc(q//2*2,e//9*9,4,h(t,s(t)*.5+.5))
;~ }

;~ u(){
;~ z:=pi*(3-Sqrt(5)),i:=0,r:=Sqrt(w/2*w/2+h/2*h/2)+5,l:=4,k:=l-1,t:=(r*r)/(l*l)
;~ Loop,%t%
;~ i++,r:=l*sqrt(i),a:=i*z,x:=r*c(a),y:=r*s(a),fc(w/2+x,h/2+y,k,h(a))
;~ }

;~ u(i=0){
;~ Loop,12800
;~ fc(w/2+c(a:=++i*2.3999632297)*r:=4*i**.5,h/2+r*s(a),3,h(a))
;~ }
;潜水艇小游戏
;~ global Vy := 50
;~ global Vx := 50
;~ u() {
	;~ f()
	;~ Vy := GetKeyState("Up") ? Vy-1 : GetKeyState("Down") ? Vy+1 : Vy
	;~ Vx := GetKeyState("Left") ? Vx-1 : GetKeyState("Right") ? Vx+1 : Vx
	;~ fe(Vx,Vy,58,30,h(2/20))
	;~ fc(Vx+25,Vy-10,4,h(6/3))
	;~ loop, 4
		;~ fc(Vx+(10*a_index),Vy+10,4,h(2/3))
	;~ if GetKeyState("space")
;~ loop, 20
 			;~ fc(Vx+25,Vy+30+(a_index*40),4,h(a_index/6))
;~ }

;~ ;打飞机小游戏
;~ u() {
	;~ static p=320,v=0,px=0,py=0,sx=0,sy=0,row,number,numbers,aliens,alien=[[[0,0,1,0,0,0,0,0,1,0,0],[0,0,0,1,0,0,0,1,0,0,0],[0,0,1,1,1,1,1,1,1,0,0],[0,1,1,0,1,1,1,0,1,1,0],[1,1,1,1,1,1,1,1,1,1,1],[1,0,1,1,1,1,1,1,1,0,1],[1,0,1,0,0,0,0,0,1,0,1],[0,0,0,1,1,0,1,1,0,0,0]],[[0,0,0,0,1,0,1,0,0,0,0],[1,0,0,1,0,0,0,1,0,0,1],[1,0,1,1,1,1,1,1,1,0,1],[1,1,1,0,1,1,1,0,1,1,1],[0,1,1,1,1,1,1,1,1,1,0],[0,0,1,1,1,1,1,1,1,0,0],[0,0,1,0,0,0,0,0,1,0,0],[0,0,0,1,1,0,1,1,0,0,0]]]
	;~ static reset=0
	;~ if (reset) {
		;~ reset := 0
		;~ d := 0
	;~ }
	;~ d?:d:=0
	;~ --row?:row:=5
	
	;~ if(!aliens) {
		;~ f()
		;~ t:=0
		;~ number:=55
		;~ numbers:=[11,11,11,11,11]
		;~ y:=0,aliens=[]
		;~ while y++<5,x=0,aliens.push(r:=[])
			;~ while x++<11
				;~ r.push(1)
	;~ }
	;~ d+=d*(55-number)/20
	;~ t+=d 
	;~ offsetX := ((t*9)&63)*3 -30
	;~ offsetY := (t*9)//64
	;~ if (offsetY>19-numbers.length()) {
		;~ MsgBox game over
		;~ reset := 1 ;temp
		;~ return aliens:=0
	;~ }
	;~ offsetY&1?offsetX:=129-offsetX
	;~ offsetY*=30
	
	
	;~ y:=(offsetY+row*30)//3|0
	;~ fr(0,y*3-$:=(row>1?0:30),640,30+$,0)
	;~ dl(px,py,px,py+20,0)
	;~ px:=sx,py:=sy
	
	;~ dl(sx,0,sx,offsetY,0)
	;~ if(!sy) {
		;~ GetKeyState("space")?sy:=580+0*sx:=p+10
	;~ } else {
		;~ a:=(sy-offsetY)//30|0
		;~ b:=(sx-offsetX)//39|0
		;~ if (aliens[a][b]) {
			;~ aliens[a][b]:=0
			;~ number--
			;~ numbers[a]--
			;~ loop 5
				;~ numbers[numbers.Length()]?:numbers.pop()
			;~ if(!numbers.Length()) {
				;~ MsgBox You won!
				;~ return aliens := 0
			;~ }
			;~ sy:=0
		;~ } else {
			;~ dl(sx,sy,sx,sy+20)
			;~ sy:=Max(0,sy-d*400)
		;~ }
	;~ }
	
	;~ c := 0
	;~ r:=row
	;~ while c++<11,y=0
		;~ if(aliens[r][c])
			;~ while y++<8,x=0
				;~ while x++<11
					;~ alien[(t&1)+1][y][x]?fr(offsetX+c*39+x*3, offsetY+r*30+y*3, 2, 2)
	;~ l:=GetKeyState("left"),r=GetKeyState("right"),v=(v>0&&l)||(v<0&&r)||!(l+r)?0:v+9*d*(r-l)
	;~ p:=Max(0,Min(620,p+v)),fr(0,596,640,30,0)fr(p,600,20,5)fc(p+7,596,3)
;~ }

类库

;~ /*
	;~ forum thread: https://autohotkey.com/boards/viewtopic.php?f=6&p=191294
	
	;~ u() is called as fast as possible.
	
	;~ --- global constants ---
	;~ t - time elapsed since script start (seconds)
	;~ d - time elapsed since last frame (seconds, delta time)
	;~ w - canvas width
	;~ h - canvas height
	;~ pi - 3.1415...
	;~ g - GDI object
	
	;~ --- functions ---
	;~ f(Color) - Fill (or clear) canvas (Color is defaulted to 0x000000)
	;~ sp(x, y, Color) - SetPixel
	;~ dl(x1, y1, x2, y2, Color) - DrawLine
	;~ fc(x, y, r, Color) - FillCircle
	;~ fr(x, y, w, h, Color) - FillRectangle
	;~ fe(x, y, w, h, Color) - FillEllipse
	;~ r(r, g, b, brightness) - transform rbg values to hex
	;~ h(hue, brightness) - get hue color from fraction. example: h(0) is red, h(1/3) is green and h(2/3) is blue.
	;~ if not specified, Color is always defaulted to 0xFFFFFF (white)
	;~ if not specified, brightness is always defaulted to 1
			
	;~ --- shorthands ---
	;~ s() - sin()
	;~ c() - cos()
	;~ t() - tan()
	;~ a() - abs()
;~ */


; this is the function you overwrite!
u(){
	f(r(,20,40)),f=0
	while 17>++f,p:=s(t*3-f/9),a=0
		loop 16
			fc(w/2+s(r:=p+a++*pi/8)*f*h/35,h/2+c(r)*f*h/35,4,h(t/2+(16-f)/16))
}





/*
	=== BOILERPLATE BELOW ===
*/

#SingleInstance force
#NoEnv
#Persistent

SetWinDelay -1
SetBatchLines -1

global g, t, d
global pi := 3.14159265359
global w := 640
global h := 640

Gui, -MinimizeBox +Resize
Gui, Color, Black, Black
Gui, Margin, 0, 0
Gui, Add, Progress, % "hwndctrl BackgroundBlack x0 y0 w" w " h" h
Gui, Show

g := new GDI(ctrl, w, h)

SetTimer, FPS, 1000
DllCall("QueryPerformanceFrequency", "Int64P", freq)

Loop {
	t += d := (end - start) / freq
	DllCall("QueryPerformanceCounter", "Int64P", start)
	u()
	g.bitblt()
	DllCall("QueryPerformanceCounter", "Int64P", end)
	frames++
}

return

f(Color := 0x000000) {
	g.FillRectangle(0, 0, g.CliWidth, g.CliHeight, Color)
}

sp(x, y, Color := 0xFFFFFF) {
	g.SetPixel(x, y, Color)
}

dl(x1, y1, x2, y2, Color := 0xFFFFFF) {
	g.DrawLine(x1, y1, x2, y2, Color)
}

fc(x, y, r, Color := 0xFFFFFF) {
	g.FillEllipse(x, y, r*2, r*2, Color)
}

fr(x, y, w, h, Color := 0xFFFFFF) {
	g.FillRectangle(x, y, w, h, Color)
}

fe(x, y, w, h, Color := 0xFFFFFF) {
	g.FillEllipse(x, y, w, h, Color)
}

s(x) {
	return sin(x)
}

c(x) {
	return cos(x)
}

t(x) {
	return tan(x)
}

a(x) {
	return abs(x)
}

r(r := 0, g := 0, b := 0, brightness := 1) {
	return (b * brightness << 16) + (g * brightness << 8) + (r * brightness)
}

h(hue, brightness := 1) {
	if (hue<0,hue:=abs(mod(hue, 1)))
		hue:=1-hue
	Loop 3
		col+=max(min(-8*abs(mod(hue+A_Index/3-0.5,1)-0.5)+2.5,1),0)*255*brightness<<16-(A_Index-1)*8
	return col
}

min(Param*) {
	Out := Param.1
	for Index, Value in param
		if (Value < Out)
			Out := Value
	return Out
}

max(Param*) {
	Out := Param.1
	for Index, Value in Param {
		if (Value > Out)
			Out := Value
	} return Out
}

FPS:
Gui +LastFound
WinSetTitle,,,% "FPS: " frames
frames := 0
return

GuiClose:
GuiEscape:
ExitApp
return

GuiSize(hwnd, type, gw, gh) {
	global time
	w := gw, h:=gh
	GuiControl, Move, % g.hwnd, w%w% h%h%
	g.Resize(w, h)
	Sleep, -1
	u()
	g.bitblt()
}

class GDI
{
	__New(hWnd, CliWidth=0, CliHeight=0)
	{
		if !(CliWidth && CliHeight)
		{
			VarSetCapacity(Rect, 16, 0)
			DllCall("GetClientRect", "Ptr", hWnd, "Ptr", &Rect)
			CliWidth := NumGet(Rect, 8, "Int")
			CliHeight := NumGet(Rect, 12, "Int")
		}
		this.CliWidth := CliWidth
		this.CliHeight := CliHeight
		this.hWnd := hWnd
		this.hDC := DllCall("GetDC", "UPtr", hWnd, "UPtr")
		this.hMemDC := DllCall("CreateCompatibleDC", "UPtr", this.hDC, "UPtr")
		this.hBitmap := DllCall("CreateCompatibleBitmap", "UPtr", this.hDC, "Int", CliWidth, "Int", CliHeight, "UPtr")
		this.hOriginalBitmap := DllCall("SelectObject", "UPtr", this.hMemDC, "UPtr", this.hBitmap)
	}
	
	__Delete()
	{
		DllCall("SelectObject", "UPtr", this.hMemDC, "UPtr", this.hOriginalBitmap)
		DllCall("DeleteObject", "UPtr", this.hBitmap)
		DllCall("DeleteObject", "UPtr", this.hMemDC)
		DllCall("ReleaseDC", "UPtr", this.hWnd, "UPtr", this.hDC)
	}
	
	Resize(w, h)
	{
		this.CliWidth := w
		this.CliHeight := h
		
		this.hBitmap := DllCall("CreateCompatibleBitmap", "UPtr", this.hDC, "Int", w, "Int", h, "UPtr")
		hPrevBitmap := DllCall("SelectObject", "UPtr", this.hMemDC, "UPtr", this.hBitmap)
		DllCall("DeleteObject", "UPtr", hPrevBitmap)
	}
	
	BitBlt(x=0, y=0, w=0, h=0)
	{
		w := w ? w : this.CliWidth
		h := h ? h : this.CliHeight
		
		DllCall("BitBlt", "UPtr", this.hDC, "Int", x, "Int", y
		, "Int", w, "Int", h, "UPtr", this.hMemDC, "Int", 0, "Int", 0, "UInt", 0xCC0020) ;SRCCOPY
	}
	
	; DrawLine
	DrawLine(x, y, x2, y2, Color)
	{
		Pen := new GDI.Pen(Color)
		DllCall("MoveToEx", "UPtr", this.hMemDC, "Int", this.TranslateX(x), "Int", this.TranslateY(y), "UPtr", 0)
		hOriginalPen := DllCall("SelectObject", "UPtr", this.hMemDC, "UPtr", Pen.Handle, "UPtr")
		DllCall("LineTo", "UPtr", this.hMemDC, "Int", this.TranslateX(x2), "Int", this.TranslateY(y2))
		DllCall("SelectObject", "UPtr", this.hMemDC, "UPtr", hOriginalPen, "UPtr")
	}
	
	; SetPixel
	SetPixel(x, y, Color)
	{
		x := this.TranslateX(x)
		y := this.TranslateY(y, this.Invert) ; Move up 1 px if inverted (drawing "up" instead of down)
		DllCall("SetPixelV", "UPtr", this.hMemDC, "Int", x, "Int", y, "UInt", Color)
	}
	
	FillRectangle(x, y, w, h, Color, BorderColor=-1)
	{
		if (w == 1 && h == 1)
			return this.SetPixel(x, y, Color)
		
		Pen := new this.Pen(BorderColor < 0 ? Color : BorderColor)
		Brush := new this.Brush(Color)
		
		; Replace the original pen and brush with our own
		hOriginalPen := DllCall("SelectObject", "UPtr", this.hMemDC, "UPtr", Pen.Handle, "UPtr")
		hOriginalBrush := DllCall("SelectObject", "UPtr", this.hMemDC, "UPtr", Brush.Handle, "UPtr")
		
		x1 := this.TranslateX(x)
		x2 := this.TranslateX(x+w)
		y1 := this.TranslateY(y)
		y2 := this.TranslateY(y+h)
		
		DllCall("Rectangle", "UPtr", this.hMemDC
		, "Int", x1, "Int", y1
		, "Int", x2, "Int", y2)
		
		; Reselect the original pen and brush
		DllCall("SelectObject", "UPtr", this.hMemDC, "UPtr", hOriginalPen, "UPtr")
		DllCall("SelectObject", "UPtr", this.hMemDC, "UPtr", hOriginalBrush, "UPtr")
	}
	
	FillEllipse(x, y, w, h, Color, BorderColor=-1)
	{
		Pen := new this.Pen(BorderColor < 0 ? Color : BorderColor)
		Brush := new this.Brush(Color)
		
		; Replace the original pen and brush with our own
		hOriginalPen := DllCall("SelectObject", "UPtr", this.hMemDC, "UPtr", Pen.Handle, "UPtr")
		hOriginalBrush := DllCall("SelectObject", "UPtr", this.hMemDC, "UPtr", Brush.Handle, "UPtr")
		
		x1 := this.TranslateX(x)
		x2 := this.TranslateX(x+w)
		y1 := this.TranslateY(y)
		y2 := this.TranslateY(y+h)
		
		DllCall("Ellipse", "UPtr", this.hMemDC
		, "Int", x1, "Int", y1
		, "Int", x2, "Int", y2)
		
		; Reselect the original pen and brush
		DllCall("SelectObject", "UPtr", this.hMemDC, "UPtr", hOriginalPen, "UPtr")
		DllCall("SelectObject", "UPtr", this.hMemDC, "UPtr", hOriginalBrush, "UPtr")
	}
	
	TranslateX(X)
	{
		return Floor(X)
	}
	
	TranslateY(Y, Offset=0)
	{
		if this.Invert
			return this.CliHeight - Floor(Y) - Offset
		return Floor(Y)
	}
	
	class Pen
	{
		__New(Color, Width=1, Style=0)
		{
			this.Handle := DllCall("CreatePen", "Int", Style, "Int", Width, "UInt", Color, "UPtr")
		}
		
		__Delete()
		{
			DllCall("DeleteObject", "UPtr", this.Handle)
		}
	}
	
	class Brush
	{
		__New(Color)
		{
			this.Handle := DllCall("CreateSolidBrush", "UInt", Color, "UPtr")
		}
		
		__Delete()
		{
			DllCall("DeleteObject", "UPtr", this.Handle)
		}
	}
}