Changed the GDI driver interface to pass an opaque PHYSDEV pointer
[wine] / libtest / rolex.c
1 /*********************************************************************
2  *                                                                   *
3  *  rolex.c: Windows clock application for WINE (by Jim Peterson)    *
4  *                                                                   *
5  *  This is a translation of a Turbo Pascal OWL application I made   *
6  *  once, so it's a little flaky (tons of globals, functions that    *
7  *  could have been in-lined, etc.).  The source code should easily  *
8  *  compile with a standard Win32 C compiler.                        *
9  *                                                                   *
10  *  To try it out, type 'make rolex'.                                *
11  *
12  * Copyright Jim Peterson
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Lesser General Public
16  * License as published by the Free Software Foundation; either
17  * version 2.1 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public
25  * License along with this library; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27  *********************************************************************/
28
29 #include <math.h>
30 #include <string.h>
31 #include "windows.h"
32
33 char AppName[] = "Rolex";
34 char WindowName[] = "Rolex";
35 int WindowWidth = 100;
36 int WindowHeight = 121;
37 COLORREF FaceColor = RGB(192,192,192);
38 COLORREF HandColor = RGB(0,0,0);
39 COLORREF EtchColor = RGB(0,0,0);
40
41 float Pi=3.1415926;
42
43 typedef struct
44 {
45   int StartX,StartY,EndX,EndY;
46 } HandData;
47
48 int MaxX,MaxY;
49 HandData OldSecond,OldHour,OldMinute;
50
51 HWND HWindow;
52
53 void DrawFace(HDC dc)
54 {
55   int MidX, MidY, t;
56
57   MidX=MaxX/2;
58   MidY=MaxY/2;
59   SelectObject(dc,CreateSolidBrush(FaceColor));
60   SelectObject(dc,CreatePen(PS_SOLID,1,EtchColor));
61   Ellipse(dc,0,0,MaxX,MaxY);
62
63   for(t=0; t<12; t++)
64   {
65     MoveToEx(dc,MidX+sin(t*Pi/6)*0.9*MidX,MidY-cos(t*Pi/6)*0.9*MidY,NULL);
66     LineTo(dc,MidX+sin(t*Pi/6)*0.8*MidX,MidY-cos(t*Pi/6)*0.8*MidY);
67   }
68   if(MaxX>64 && MaxY>64)
69     for(t=0; t<60; t++)
70       SetPixel(dc,MidX+sin(t*Pi/30)*0.9*MidX,MidY-cos(t*Pi/30)*0.9*MidY
71                ,EtchColor);
72   DeleteObject(SelectObject(dc,GetStockObject(NULL_BRUSH)));
73   DeleteObject(SelectObject(dc,GetStockObject(NULL_PEN)));
74   memset(&OldSecond,0,sizeof(OldSecond));
75   memset(&OldMinute,0,sizeof(OldMinute));
76   memset(&OldHour,0,sizeof(OldHour));
77 }
78
79 void DrawHourHand(HDC dc)
80 {
81   MoveToEx(dc, OldHour.StartX, OldHour.StartY, NULL);
82   LineTo(dc, OldHour.EndX, OldHour.EndY);
83 }
84
85 void DrawMinuteHand(HDC dc)
86 {
87   MoveToEx(dc, OldMinute.StartX, OldMinute.StartY, NULL);
88   LineTo(dc, OldMinute.EndX, OldMinute.EndY);
89 }
90
91 void DrawSecondHand(HDC dc)
92 {
93   MoveToEx(dc, OldSecond.StartX, OldSecond.StartY, NULL);
94   LineTo(dc, OldSecond.EndX, OldSecond.EndY);
95 }
96
97 BOOL UpdateHourHand(HDC dc,int MidX,int MidY,int XExt,int YExt,WORD Pos)
98 {
99   int Sx, Sy, Ex, Ey;
100   BOOL rv;
101
102   rv = FALSE;
103   Sx = MidX; Sy = MidY;
104   Ex = MidX+sin(Pos*Pi/6000)*XExt;
105   Ey = MidY-cos(Pos*Pi/6000)*YExt;
106   rv = ( Sx!=OldHour.StartX || Ex!=OldHour.EndX || 
107          Sy!=OldHour.StartY || Ey!=OldHour.EndY );
108   if(rv)DrawHourHand(dc);
109   OldHour.StartX = Sx; OldHour.EndX = Ex;
110   OldHour.StartY = Sy; OldHour.EndY = Ey;
111   return rv;
112 }
113
114 BOOL UpdateMinuteHand(HDC dc,int MidX,int MidY,int XExt,int YExt,WORD Pos)
115 {
116   int Sx, Sy, Ex, Ey;
117   BOOL rv;
118
119   rv = FALSE;
120   Sx = MidX; Sy = MidY;
121   Ex = MidX+sin(Pos*Pi/30000)*XExt;
122   Ey = MidY-cos(Pos*Pi/30000)*YExt;
123   rv = ( Sx!=OldMinute.StartX || Ex!=OldMinute.EndX ||
124          Sy!=OldMinute.StartY || Ey!=OldMinute.EndY );
125   if(rv)DrawMinuteHand(dc);
126   OldMinute.StartX = Sx; OldMinute.EndX = Ex;
127   OldMinute.StartY = Sy; OldMinute.EndY = Ey;
128   return rv;
129 }
130
131 BOOL UpdateSecondHand(HDC dc,int MidX,int MidY,int XExt,int YExt,WORD Pos)
132 {
133   int Sx, Sy, Ex, Ey;
134   BOOL rv;
135
136   rv = FALSE;
137   Sx = MidX; Sy = MidY;
138   Ex = MidX+sin(Pos*Pi/3000)*XExt;
139   Ey = MidY-cos(Pos*Pi/3000)*YExt;
140   rv = ( Sx!=OldSecond.StartX || Ex!=OldSecond.EndX ||
141          Sy!=OldSecond.StartY || Ey!=OldSecond.EndY );
142   if(rv)DrawSecondHand(dc);
143   OldSecond.StartX = Sx; OldSecond.EndX = Ex;
144   OldSecond.StartY = Sy; OldSecond.EndY = Ey;
145   return rv;
146 }
147
148 void Idle(HDC idc)
149 {
150   SYSTEMTIME st;
151   WORD H, M, S, F;
152   int MidX, MidY;
153   HDC dc;
154   BOOL Redraw;
155
156   if(idc)
157     dc=idc;
158   else
159     dc=GetDC(HWindow);
160   if(!dc)return;
161
162   GetLocalTime(&st);
163   H = st.wHour;
164   M = st.wMinute;
165   S = st.wSecond;
166   F = st.wMilliseconds / 10;
167   F = F + S*100;
168   M = M*1000+F/6;
169   H = H*1000+M/60;
170   MidX = MaxX/2;
171   MidY = MaxY/2;
172   SelectObject(dc,CreatePen(PS_SOLID,1,FaceColor));
173   Redraw = FALSE;
174   if(UpdateHourHand(dc,MidX,MidY,MidX*0.5,MidY*0.5,H)) Redraw = TRUE;
175   if(UpdateMinuteHand(dc,MidX,MidY,MidX*0.65,MidY*0.65,M)) Redraw = TRUE;
176   if(UpdateSecondHand(dc,MidX,MidY,MidX*0.79,MidY*0.79,F)) Redraw = TRUE;
177   DeleteObject(SelectObject(dc,CreatePen(PS_SOLID,1,HandColor)));
178   if(Redraw)
179   {
180     DrawSecondHand(dc);
181     DrawMinuteHand(dc);
182     DrawHourHand(dc);
183   }
184   DeleteObject(SelectObject(dc,GetStockObject(NULL_PEN)));
185   if(!idc) ReleaseDC(HWindow,dc);
186 }
187
188 LRESULT CALLBACK ProcessAppMsg(HWND wnd,UINT msg,WPARAM w,LPARAM l)
189 {
190   PAINTSTRUCT PaintInfo;
191   HDC dc;
192
193   switch(msg)
194   {
195   case WM_PAINT:
196     if(GetUpdateRect(wnd,NULL,FALSE))
197     {
198       dc=BeginPaint(wnd,&PaintInfo);
199       DrawFace(dc);
200       Idle(dc);
201       EndPaint(wnd,&PaintInfo);
202     }
203     break;
204
205   case WM_SIZE:
206     MaxX = LOWORD(l);
207     MaxY = HIWORD(l);
208     break;
209
210   case WM_DESTROY:
211     PostQuitMessage (0);
212     break;
213
214   default:
215     return DefWindowProc (wnd, msg, w, l);
216   }
217   return 0l;
218 }
219
220 WPARAM MessageLoop()
221 {
222   MSG msg;
223
224   while(1)
225   {
226     Sleep(1); /* sleep 1 millisecond */
227     if(PeekMessage(&msg,0,0,0,PM_REMOVE))
228     {
229       if(msg.message == WM_QUIT) return msg.wParam;
230       TranslateMessage(&msg);
231       DispatchMessage(&msg);
232     }
233     else
234       Idle(NULL);
235   }
236 }
237
238 int PASCAL WinMain (HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
239 {
240   WNDCLASS class;
241   if(!prev)
242   {
243     class.style = CS_HREDRAW | CS_VREDRAW;
244     class.lpfnWndProc = ProcessAppMsg;
245     class.cbClsExtra = 0;
246     class.cbWndExtra = 0;
247     class.hInstance  = inst;
248     class.hIcon      = 0; /* Draw my own icon */
249     class.hCursor    = LoadCursor (0, IDC_ARROW);
250     class.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);
251     class.lpszMenuName = 0;
252     class.lpszClassName = AppName;
253   }
254   if (!RegisterClass (&class)) return -1;
255
256   HWindow=CreateWindowEx(WS_EX_TOPMOST,AppName,WindowName,WS_OVERLAPPEDWINDOW,
257                          CW_USEDEFAULT,CW_USEDEFAULT,WindowWidth,WindowHeight,
258                          0,0,inst,0);
259   memset(&OldSecond,0,sizeof(OldSecond));
260   memset(&OldMinute,0,sizeof(OldMinute));
261   memset(&OldHour,0,sizeof(OldHour));
262   MaxX = WindowWidth;
263   MaxY = WindowHeight;
264
265   ShowWindow (HWindow, show);
266   UpdateWindow (HWindow);
267
268   return MessageLoop();
269 }