Someone asked me recently, as to the limitations of AHK. I said that as far as I know it does'nt do three dimensional molecular transformations, BUT! we're working on it.
Seriously though,the point at which Chris introduced DllCall, there ceased to be ANY limitations other than the users Imagination/Ability. I currently use a graphics library that I wrote last year. However for political reasons I can't release the Library at this time. However I have extracted some of the more salient functions and written them out as subroutines.
The code attached is intentionally verbose, and with lots of bits to tweak making it easier for newbies to grapple with.
CAVEAT: Any use of SelectObject into a DC must be matched immediately with a DeleteOject as soon as the operation it was used for, is completed. FAILURE TO DO SO WILL RESULT IN POSSIBLY FATAL MEMORY LEAKS.. YOU HAVE BEEN WARNED!.
The code attached shows basically how to set up a buffer/canvas on which to draw (avoids flicker) and then blits the result to the AhkWindow. Just a few simple draw functions such as drawing ellipses,rectangles & lines + a quick look at font handling! Feedback on this will be greatly appreciated,and questions are welcome (if I can answer them even better).
More demos will be downloadable in the near future showing simple Animations and hopefully some spriteing! So,finally as Eintein said,
"make it as simple as possible,but no simpler". Have Fun.
;;################################################### ;;## Compiler Version 1.0.43.00 ## ;;## ## ;;## SUBJECT: GRAPHICS ## ;;## AUTHOR : Dave Perrée March 2006 ## ;;## PROGRAM: DEMO ANALOG CLOCK Ver 1.00 ## ;;## ## ;;################################################### SetTimer,working,500 2pi := 2*3.1415926 Gui,Show, W193 H168, AhkClock_01 ;; Get handle to window we've created hwndA := DllCall("GetActiveWindow") ;;############################################################################# ;; Some trickery! As we've made no provision to handle WM_Paint messages, the ;; resulting display would be rather messy unless of course we never moved ;; another window over it. The first line below is the minimum required and ;; does not affect the appearance of the window. ;; It is this line OR the one below it that fools AHK into being responsible ;; for handling the paint messages. Note also the position of the gui,-caption ;; Try remming out the winset line to see how it would appear :) ;; Not a pretty sight eh! ;;############################################################################# ;Winset,Transparent,255,AhkClock_01 Winset,Transcolor,012345 125,AhkClock_01 Gui, -CAPTION Gosub ONCEONLY Gosub working ; kick straight in Return guiclose: gosub ReleaseGraphics exitapp ONCEONLY: ;; will last for duration of program _xx := 0 ; x cord of canvas area _yy := 0 ; y cord "" _ww := 200 ; width "" _hh := 200 ; height "" gosub CreateStruc gosub CreateBckBuffer RETURN Working: ;; NB: all colors in API are BGR tuples ;; popup if computer is idle > 10 minutes IfGreater, A_TimeIdle, 600000 winactivate,AhkClock ;; Use a rectangle to clear the canvas (invisible colour!) hBrush := DllCall("CreateSolidBrush", UInt,0x452301) DllCall("SelectObject" ,UINT,memDC,uint,hBrush) DllCall("FillRect", UInt, MemDC, Str, Rect, UInt, hBrush) DllCall("DeleteObject", UInt, hBrush) ;----- ;; Draw 2 filled circles ;; 17 million to choose from and we always use white ? :) hBrush := DllCall("CreateSolidBrush", UInt,bgr(255,255,255)) DllCall("SelectObject" ,UINT,memDC,uint,hBrush) hCurrPen := DllCall("CreatePen" ,uint,0,uint,2,uint,bgr(0,0,0)) DllCall("SelectObject" ,UINT,memDC,uint,hCurrPen) DllCall("Ellipse",uint,memdc,uint,3,uint,3,uint,197,uint,197) DllCall("Ellipse",uint,memdc,uint,16,uint,16,uint,184,uint,184) DllCall("DeleteObject", UInt, hBrush) DllCall("DeleteObject", UInt, hCurrPen) ;; Draw some dots for the hour markers dotpos = 0 loop 12 { dotpos+=2pi/12 POSX := _ww/2 + 90*COS(dotpos) POSY := _hh/2 + 90*SIN(dotpos) hCurrPen := DllCall("CreatePen" ,uint,0,uint,8,uint,bgr(0,0,0)) DllCall("SelectObject" ,UINT,memDC,uint,hCurrPen) DllCall("MoveToEx" ,UINT,memDC, UINT,POSX,UINT,POSY,UINT,0) DllCall("LineTo" ,UINT,memDC,UINT,POSX,UINT,POSY) DllCall("DeleteObject", UInt, hCurrPen) } ;; Draw some minute markers dotpos = 0 loop 60 { dotpos+=2pi/60 POSX := _ww/2 + 88*COS(dotpos) POSY := _hh/2 + 88*SIN(dotpos) hCurrPen := DllCall("CreatePen" ,uint,0,uint,3,uint,bgr(0,0,0)) DllCall("SelectObject" ,UINT,memDC,uint,hCurrPen) DllCall("MoveToEx" ,UINT,memDC, UINT,POSX,UINT,POSY,UINT,0) DllCall("LineTo" ,UINT,memDC,UINT,POSX,UINT,POSY) DllCall("DeleteObject", UInt, hCurrPen) } ;; ;; HOUR HAND HANDpos := 2pi*(((A_hour+A_min/60)*5)/60) ; creeps by minutes hlen = 45 wide = 8 hcol := Bgr(255,150,0) GOSUB DRAW_HAND ;; ;; MINUTE HAND HANDpos := 2pi*((A_min/60)+(A_sec/3600)) ; creeps by seconds HLEN = 65 WIDE = 6 HCOL := Bgr(0,255,0) GOSUB DRAW_HAND ;; SECOND HAND HANDpos := 2pi*(A_sec/60) HLEN = 90 WIDE = 2 HCOL := Bgr(0,0,255) GOSUB DRAW_HAND ;; FormatTime, Mdate ,A_now,ddd dd MMM yy DllCall("SetTextColor",UINT,MEMdc,UINT,0X0) DllCall("SetBkMode",UINT,MEMdc,UINT,1) ; transparent ;; minimal font handling, I jest not - You'd better believe it ! hFont := DllCall("CreateFont",uint,14,uint,0,uint,0,uint,0 ,uint,700 ,uint,0 ,uint,0 ,uint,0 ,uint,0 ,uint,0 , uint,0,uint,0 ,uint,0 , verdana) DllCall("SelectObject" ,UINT,memDC,uint,hFont) DllCall("TextOutA",UINT,MEMDC,UINT,70,UINT,130,STR,Mdate,UINT,13) DllCall("TextOutA",UINT,MEMDC,UINT,70,UINT,50,STR,"AutoHotkey",UINT,10) DllCall("DeleteObject", UInt, Hfont) ;; What! no clockface numbers !! Well, go on then, Experiment :) gosub UpdateScreen Return ;;############################################################################# ;; +++++++++++ END OF PROGRAM SECTION ++++++++++++++ ;;############################################################################# Bgr(_blu,_grn,_red) { return (_blu << 16 | _grn << 8 | _red) } DRAW_HAND: POSX := _ww/2 + hlen*COS(HANDpos-2pi/4) POSY := _hh/2 + hlen*SIN(HANDpos-2pi/4) hCurrPen := DllCall("CreatePen" ,uint,0,uint,wide,uint,hcol) DllCall("SelectObject" ,UINT,memDC,uint,hCurrPen) DllCall("MoveToEx" ,UINT,memDC, UINT,_ww/2,UINT,_hh/2,UINT,0) DllCall("LineTo" ,UINT,memDC,UINT,POSX,UINT,POSY) DllCall("DeleteObject", UInt, hCurrPen) RETURN CreateStruc: VarSetCapacity(Rect, 16, 0) InsertInteger(0,rect,0) ; always zero InsertInteger(0,rect,4) ; always zero InsertInteger(_ww,rect,8) InsertInteger(_hh,rect,12) Return CreateBckBuffer: ScreenDC := DllCall("GetDC", uint,hwndA) MemDC := DllCall("CreateCompatibleDC",uint,ScreenDC) MemBM := DllCall("CreateCompatibleBitmap",uint,ScreenDC ,uint,_ww,uint,_hh) DllCall("SelectObject",uint,MemDC,uint,MemBM) Return ReleaseGraphics: DllCall("ReleaseDC", UInt, 0, UInt, ScreenDC) DllCall("DeleteObject", UInt,MemDC) DllCall("DeleteObject", UInt,MemBM) Return UpdateScreen: DllCall("BitBlt" ,Uint,ScreenDC,uint,_xx,uint,_yy,uint,_ww,uint,_hh ,Uint,MemDC,uint,0,uint,0,Uint ,0x00CC0020) ;; Srccopy As Is Return InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4) ; The caller must ensure that pDest has sufficient capacity. ; To preserve any existing contents in pDest, ; only pSize number of bytes starting at pOffset are altered in it. { Loop %pSize% DllCall("RtlFillMemory", UInt, &pDest + pOffset + A_Index-1 , UInt, 1, UChar, pInteger >> 8*(A_Index-1) & 0xFF) }