Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

UNCLE DAVID'S SNIPPETS #1 Graphics - Demo Analog Clock


  • Please log in to reply
11 replies to this topic
Dippy46
  • Members
  • 171 posts
  • Last active: Aug 17 2007 06:53 AM
  • Joined: 06 Jul 2004
Hi,all
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)
}


Simple ideas lie within reach, only of complex minds

corrupt
  • Members
  • 2558 posts
  • Last active: Nov 01 2014 03:23 PM
  • Joined: 29 Dec 2004
Nice. Thanks :)

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
Cool! The seconds hand moves a little irregularly, though. How hard is it to add numbers at the hour positions?

Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004
Thanks for sharing this. I've moved it to the Scripts forum because it might get more attention there.

Grendel
  • Members
  • 25 posts
  • Last active: Mar 17 2007 07:11 PM
  • Joined: 18 Nov 2005
this is a very good example how flexible and genius AHK-Scripts can be !

great stuff...thanks for giving several ideas :D
greets Grendel

not-logged-in-daonlyfreez
  • Guests
  • Last active:
  • Joined: --
Great stuff!

Thru peeking at MSDN on GDI, I quickly was able to add an Arc

hCurrPen := DllCall("CreatePen" ,uint,0,uint,1,uint,bgr(0,0,0)) 
DllCall("SelectObject" ,UINT,memDC,uint,hCurrPen) 
DllCall("Arc",uint,memdc,uint,0,uint,0,uint,50,uint,50,uint,7,uint,12,uint,38,uint,48)
DllCall("DeleteObject", UInt, hCurrPen)

I hope this could be the start of a built-in AHK GUI Canvas Control 8)

Dippy46
  • Members
  • 171 posts
  • Last active: Aug 17 2007 06:53 AM
  • Joined: 06 Jul 2004
Hi all,
Thanx for the responses.
@Laszlo, yes re: irregularity,my fault for choosing a slow timer rate but that was done to show up the lazy graphics. Just reduce it to a more normal 100msecs or less and it should be ok!
As far as Numbers go there are several solutions ranging from the elegant thru to totally gross.
I should have some methods up on the board within the next 24hours or so :roll:
@N-L-I daonlyfreez
I have mixed feelings about adding more complexity to AHK's internal abilities, and I think in some ways it would spoil it for those users who enjoy the simplistic and friendly interface. I think it would probably be more prudent to build an official include file or rather a set of approved
includes for those users who require additional functionality. I may be wrong but there have been many posts on the subject QED.
Simple ideas lie within reach, only of complex minds

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
I like this pure AHK analog clock, but it is too slow or the hands movement is irregular, so I made a little mod. The clock is updated now 4 times a second, but if the value of seconds did not change, we do nothing. This is a factor of 2 speedup, with smoother hands movement.

The original script redrew the whole clock constantly, which was slow. Instead, the outer circle and the markers are now kept unchanged, only the hands are erased and redrawn. This gives more than ten fold speedup. There are a number of simplifications for further speedup and making the script shorter. The end result is less than 1% processor load in my laptop, down from 20%, and the length of the script is reduced more than twofold.

I have my taskbar on the left edge of the screen, and the clock is docked there. Since it is transparent, I still can see or click on everything underneath. Of course the clock can be made to appear in a corner of the screen, always on top, or let it come to the top regularly, and then get back to the bottom.
OnExit GuiClose   ; Close open graphic tools
o2  = 100         ; half width/height of canvas
wh := o2*2
w16:= wh-16

Gui Show, % "X-12 Y867 W" wh "H" wh-44, AhkClock        ; <-- EDIT location
WinGet hwndA, ID, A
Winset Transcolor,012345,AhkClock
Gui -CAPTION

WinGet Tray_ID, ID, ahk_class Shell_TrayWnd             ; Dock to the TASKBAR
WinGet ClockID, ID, ahk_id %hwndA%
DllCall("SetParent", UInt, ClockID, UInt, Tray_ID)

VarSetCapacity(Rect, 16, 0)
DllCall("ntoskrnl.exe\RtlFillMemoryUlong", UInt,&rect+ 8, UInt,4, UInt,wh)
DllCall("ntoskrnl.exe\RtlFillMemoryUlong", UInt,&rect+12, UInt,4, UInt,wh)

ScreenDC:= DllCall("GetDC", UInt,hwndA)
MemDC   := DllCall("CreateCompatibleDC", UInt,ScreenDC)
MemBM   := DllCall("CreateCompatibleBitmap", UInt,ScreenDC , UInt,wh, UInt,wh)
DllCall("SelectObject", UInt,MemDC, UInt,MemBM)

hBrush  := DllCall("CreateSolidBrush", UInt,0x452301)   ; KEEP IT OPEN for inner circle
DllCall("SelectObject", UInt,memDC, UInt,hBrush)
DllCall("FillRect", UInt,MemDC, Str,Rect, UInt,hBrush)  ; Canvas of invisible color

hCurrPen:= DllCall("CreatePen", UInt,0, UInt,2, UInt,0) ; KEEP IT OPEN for inner circle
DllCall("SelectObject", UInt,memDC, UInt,hCurrPen)
DllCall("Ellipse", UInt,memdc, UInt,1, UInt,1, UInt,wh-1, UInt,wh-1) ; OUTER CIRCLE

loop 12                             ; Hour markers
   DrawHand(o2-3,.523599*A_Index, 5, 0)
loop 60                             ; Minute markers
   DrawHand( o2, .104720*A_Index, 1, 0)

SetTimer Working
RETURN

GuiClose:
   DllCall("DeleteObject", UInt,hBrush)
   DllCall("DeleteObject", UInt,hCurrPen)
   DllCall("ReleaseDC", UInt,0, UInt,ScreenDC)
   DllCall("DeleteObject", UInt,MemDC)
   DllCall("DeleteObject", UInt,MemBM)
ExitApp

Working:
   IfEqual Sec0,%A_Sec%, Return     ; No change - no draw
   Sec0 = %A_Sec%

   DllCall("SelectObject", UInt,memDC, UInt,hCurrPen)
   DllCall("Ellipse", UInt,memdc, UInt,16, UInt,16, UInt,w16, UInt,w16) ; ERASE HANDS

   DrawHand(55,.523599*A_hour+.008727*A_min-1.570796,11,0x000088) ; HOUR HAND
   DrawHand(75,.104720*A_min +.001745*A_sec-1.570796, 7,0x00FFFF) ; MINUTE HAND
   DrawHand(82,.104720*A_sec               -1.570796, 3,0xFFFFFF) ; SECOND HAND
   DrawHand(16,.104720*A_sec               +1.570796, 5,0xFFFFFF) ; "" extension

   DllCall("BitBlt", UInt,ScreenDC, UInt,0, UInt,0, UInt,wh, UInt,wh
           ,UInt,MemDC, UInt,0, UInt,0, UInt,0x00CC0020) ; SrcCopy As Is
Return

DrawHand(r,angle,width,color)
{
   Global memDC, o2
   hCurrPen := DllCall("CreatePen", UInt,0, UInt,width, UInt,color)
   DllCall("SelectObject", UInt,memDC, UInt,hCurrPen)
   DllCall("MoveToEx", UInt,memDC, UInt,o2, UInt,o2, UInt,0)
   DllCall("LineTo", UInt,memDC, UInt,Round(o2+r*cos(angle)), UInt,Round(o2+r*sin(angle)))
   DllCall("DeleteObject", UInt,hCurrPen)
}


Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
I updated my version with
- OnExit, to clean up when the script exits abnormally (like a new version is started)
- Round the coordinates in the DrawHand function (instead of truncating), to improve accuracy
- Colored the hands for demo

Don't forget to edit the location. On lower screen resolutions the clock could be outside.

Dippy46
  • Members
  • 171 posts
  • Last active: Aug 17 2007 06:53 AM
  • Joined: 06 Jul 2004
@Laszlo, Nice one!
The main reason I popped this code up was to generate a little bit of interest. Thanx for taking up the challenge. I wonder if you've sussed the best way to produce the clockface numbers :roll:

Back Soon
Regards
Dave.
Simple ideas lie within reach, only of complex minds

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
As you see, no numbers in my version, either. I've been too lazy, and waited for you to do the numbers.

Another question: the lines, circles would look much nicer, with some dithering or anti-aliasing, or how is it called, when the edges of straight lines made blurry, to avoid sharp steps at pixel boundaries. Does anyone know a simple way to do it?

Jaytech
  • Members
  • 243 posts
  • Last active: Dec 24 2008 09:22 PM
  • Joined: 11 Dec 2006
Ok, this string has ben dead for quite some time, but I was in need of an analog clock. Finding this was a good send considering that I know almost nothing about how it works. That being said, I did make a couple small changes. I increased the size and added numbers. Woot!

So for anyone who wants it, here my additions:

;;###################################################
;;##         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, W493 H468, 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
Gui, -CAPTION
Winset,Transcolor,012345 125,AhkClock_01

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 := 500   ; width    ""
_hh := 500   ; 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,497,uint,497)
DllCall("Ellipse",uint,memdc,uint,16,uint,16,uint,484,uint,484)
DllCall("DeleteObject", UInt, hBrush) 
DllCall("DeleteObject", UInt, hCurrPen)


;; Draw some numbers								;New
loop 12										;New
{										;New
dotpos+=2pi/12									;New
POSX := _ww/2 + 220*COS(dotpos)-5						;New
POSY := _hh/2 + 220*SIN(dotpos)-12						;New
IfEqual, A_Index, 1								;New
	Index=3									;New
Index+=1									;New
IfGreater, Index, 12								;New
Index-=12									;New
Len:=StrLen(Index)								;New
ifEqual, Len, 2									;New
	POSX-=5									;New
DllCall("SetTextColor",UINT,MEMdc,UINT,0X0)					;New
DllCall("SetBkMode",UINT,MEMdc,UINT,1) ; transparent				;New
hFont := DllCall("CreateFont",uint,24,uint,0,uint,0,uint,0 ,uint,700 ,uint,0	;New
         ,uint,0 ,uint,0 ,uint,0 ,uint,0 , uint,0,uint,0 ,uint,0		;New
         , verdana)								;New
DllCall("SelectObject" ,UINT,memDC,uint,hFont)					;New
DllCall("TextOutA",UINT,MEMDC,UINT,POSX,UINT,POSY,STR,Index,UINT,Len)		;New
}




;; Draw some minute markers
dotpos = 0
loop 60
{
dotpos+=2pi/60
Dot_Test:=Mod(A_Index,5)							;New
IfEqual, Dot_Test, 0								;New
	CONTINUE								;New
POSX := _ww/2 + 218*COS(dotpos)    
POSY := _hh/2 + 218*SIN(dotpos)
hCurrPen := DllCall("CreatePen" ,uint,0,uint,4,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 = 175
wide = 8
hcol := Bgr(255,150,0)
GOSUB DRAW_HAND
;;
;; MINUTE HAND
HANDpos := 2pi*((A_min/60)+(A_sec/3600)) ; creeps by seconds
HLEN = 195
WIDE = 6
HCOL := Bgr(0,255,0)
GOSUB DRAW_HAND
;; SECOND HAND
HANDpos := 2pi*(A_sec/60)
HLEN = 220
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,24,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,190,UINT,340,STR,Mdate,UINT,13)
DllCall("TextOutA",UINT,MEMDC,UINT,215,UINT,140,STR,"Jaytech",UINT,7)		;Vanity Plate :)
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)
}