Fixed handling of DGA2.0 keyboard events.
[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  *********************************************************************/
13
14 #include <math.h>
15 #include <string.h>
16 #include "windows.h"
17
18 char AppName[] = "Rolex";
19 char WindowName[] = "Rolex";
20 int WindowWidth = 100;
21 int WindowHeight = 121;
22 COLORREF FaceColor = RGB(192,192,192);
23 COLORREF HandColor = RGB(0,0,0);
24 COLORREF EtchColor = RGB(0,0,0);
25
26 float Pi=3.1415926;
27
28 typedef struct
29 {
30   int StartX,StartY,EndX,EndY;
31 } HandData;
32
33 int MaxX,MaxY;
34 HandData OldSecond,OldHour,OldMinute;
35
36 HWND HWindow;
37
38 void DrawFace(HDC dc)
39 {
40   int MidX, MidY, t;
41
42   MidX=MaxX/2;
43   MidY=MaxY/2;
44   SelectObject(dc,CreateSolidBrush(FaceColor));
45   SelectObject(dc,CreatePen(PS_SOLID,1,EtchColor));
46   Ellipse(dc,0,0,MaxX,MaxY);
47
48   for(t=0; t<12; t++)
49   {
50     MoveToEx(dc,MidX+sin(t*Pi/6)*0.9*MidX,MidY-cos(t*Pi/6)*0.9*MidY,NULL);
51     LineTo(dc,MidX+sin(t*Pi/6)*0.8*MidX,MidY-cos(t*Pi/6)*0.8*MidY);
52   }
53   if(MaxX>64 && MaxY>64)
54     for(t=0; t<60; t++)
55       SetPixel(dc,MidX+sin(t*Pi/30)*0.9*MidX,MidY-cos(t*Pi/30)*0.9*MidY
56                ,EtchColor);
57   DeleteObject(SelectObject(dc,GetStockObject(NULL_BRUSH)));
58   DeleteObject(SelectObject(dc,GetStockObject(NULL_PEN)));
59   memset(&OldSecond,0,sizeof(OldSecond));
60   memset(&OldMinute,0,sizeof(OldMinute));
61   memset(&OldHour,0,sizeof(OldHour));
62 }
63
64 void DrawHourHand(HDC dc)
65 {
66   MoveToEx(dc, OldHour.StartX, OldHour.StartY, NULL);
67   LineTo(dc, OldHour.EndX, OldHour.EndY);
68 }
69
70 void DrawMinuteHand(HDC dc)
71 {
72   MoveToEx(dc, OldMinute.StartX, OldMinute.StartY, NULL);
73   LineTo(dc, OldMinute.EndX, OldMinute.EndY);
74 }
75
76 void DrawSecondHand(HDC dc)
77 {
78   MoveToEx(dc, OldSecond.StartX, OldSecond.StartY, NULL);
79   LineTo(dc, OldSecond.EndX, OldSecond.EndY);
80 }
81
82 BOOL UpdateHourHand(HDC dc,int MidX,int MidY,int XExt,int YExt,WORD Pos)
83 {
84   int Sx, Sy, Ex, Ey;
85   BOOL rv;
86
87   rv = FALSE;
88   Sx = MidX; Sy = MidY;
89   Ex = MidX+sin(Pos*Pi/6000)*XExt;
90   Ey = MidY-cos(Pos*Pi/6000)*YExt;
91   rv = ( Sx!=OldHour.StartX || Ex!=OldHour.EndX || 
92          Sy!=OldHour.StartY || Ey!=OldHour.EndY );
93   if(rv)DrawHourHand(dc);
94   OldHour.StartX = Sx; OldHour.EndX = Ex;
95   OldHour.StartY = Sy; OldHour.EndY = Ey;
96   return rv;
97 }
98
99 BOOL UpdateMinuteHand(HDC dc,int MidX,int MidY,int XExt,int YExt,WORD Pos)
100 {
101   int Sx, Sy, Ex, Ey;
102   BOOL rv;
103
104   rv = FALSE;
105   Sx = MidX; Sy = MidY;
106   Ex = MidX+sin(Pos*Pi/30000)*XExt;
107   Ey = MidY-cos(Pos*Pi/30000)*YExt;
108   rv = ( Sx!=OldMinute.StartX || Ex!=OldMinute.EndX ||
109          Sy!=OldMinute.StartY || Ey!=OldMinute.EndY );
110   if(rv)DrawMinuteHand(dc);
111   OldMinute.StartX = Sx; OldMinute.EndX = Ex;
112   OldMinute.StartY = Sy; OldMinute.EndY = Ey;
113   return rv;
114 }
115
116 BOOL UpdateSecondHand(HDC dc,int MidX,int MidY,int XExt,int YExt,WORD Pos)
117 {
118   int Sx, Sy, Ex, Ey;
119   BOOL rv;
120
121   rv = FALSE;
122   Sx = MidX; Sy = MidY;
123   Ex = MidX+sin(Pos*Pi/3000)*XExt;
124   Ey = MidY-cos(Pos*Pi/3000)*YExt;
125   rv = ( Sx!=OldSecond.StartX || Ex!=OldSecond.EndX ||
126          Sy!=OldSecond.StartY || Ey!=OldSecond.EndY );
127   if(rv)DrawSecondHand(dc);
128   OldSecond.StartX = Sx; OldSecond.EndX = Ex;
129   OldSecond.StartY = Sy; OldSecond.EndY = Ey;
130   return rv;
131 }
132
133 void Idle(HDC idc)
134 {
135   SYSTEMTIME st;
136   WORD H, M, S, F;
137   int MidX, MidY;
138   HDC dc;
139   BOOL Redraw;
140
141   if(idc)
142     dc=idc;
143   else
144     dc=GetDC(HWindow);
145   if(!dc)return;
146
147   GetLocalTime(&st);
148   H = st.wHour;
149   M = st.wMinute;
150   S = st.wSecond;
151   F = st.wMilliseconds / 10;
152   F = F + S*100;
153   M = M*1000+F/6;
154   H = H*1000+M/60;
155   MidX = MaxX/2;
156   MidY = MaxY/2;
157   SelectObject(dc,CreatePen(PS_SOLID,1,FaceColor));
158   Redraw = FALSE;
159   if(UpdateHourHand(dc,MidX,MidY,MidX*0.5,MidY*0.5,H)) Redraw = TRUE;
160   if(UpdateMinuteHand(dc,MidX,MidY,MidX*0.65,MidY*0.65,M)) Redraw = TRUE;
161   if(UpdateSecondHand(dc,MidX,MidY,MidX*0.79,MidY*0.79,F)) Redraw = TRUE;
162   DeleteObject(SelectObject(dc,CreatePen(PS_SOLID,1,HandColor)));
163   if(Redraw)
164   {
165     DrawSecondHand(dc);
166     DrawMinuteHand(dc);
167     DrawHourHand(dc);
168   }
169   DeleteObject(SelectObject(dc,GetStockObject(NULL_PEN)));
170   if(!idc) ReleaseDC(HWindow,dc);
171 }
172
173 LRESULT CALLBACK ProcessAppMsg(HWND wnd,UINT msg,WPARAM w,LPARAM l)
174 {
175   PAINTSTRUCT PaintInfo;
176   HDC dc;
177
178   switch(msg)
179   {
180   case WM_PAINT:
181     if(GetUpdateRect(wnd,NULL,FALSE))
182     {
183       dc=BeginPaint(wnd,&PaintInfo);
184       DrawFace(dc);
185       Idle(dc);
186       EndPaint(wnd,&PaintInfo);
187     }
188     break;
189
190   case WM_SIZE:
191     MaxX = LOWORD(l);
192     MaxY = HIWORD(l);
193     break;
194
195   case WM_DESTROY:
196     PostQuitMessage (0);
197     break;
198
199   default:
200     return DefWindowProc (wnd, msg, w, l);
201   }
202   return 0l;
203 }
204
205 WPARAM MessageLoop()
206 {
207   MSG msg;
208
209   while(1)
210   {
211     Sleep(1); /* sleep 1 millisecond */
212     if(PeekMessage(&msg,0,0,0,PM_REMOVE))
213     {
214       if(msg.message == WM_QUIT) return msg.wParam;
215       TranslateMessage(&msg);
216       DispatchMessage(&msg);
217     }
218     else
219       Idle(NULL);
220   }
221 }
222
223 int PASCAL WinMain (HANDLE inst, HANDLE prev, LPSTR cmdline, int show)
224 {
225   WNDCLASS class;
226   if(!prev)
227   {
228     class.style = CS_HREDRAW | CS_VREDRAW;
229     class.lpfnWndProc = ProcessAppMsg;
230     class.cbClsExtra = 0;
231     class.cbWndExtra = 0;
232     class.hInstance  = inst;
233     class.hIcon      = 0; /* Draw my own icon */
234     class.hCursor    = LoadCursor (0, IDC_ARROW);
235     class.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);
236     class.lpszMenuName = 0;
237     class.lpszClassName = AppName;
238   }
239   if (!RegisterClass (&class)) return -1;
240
241   HWindow=CreateWindowEx(WS_EX_TOPMOST,AppName,WindowName,WS_OVERLAPPEDWINDOW,
242                          CW_USEDEFAULT,CW_USEDEFAULT,WindowWidth,WindowHeight,
243                          0,0,inst,0);
244   memset(&OldSecond,0,sizeof(OldSecond));
245   memset(&OldMinute,0,sizeof(OldMinute));
246   memset(&OldHour,0,sizeof(OldHour));
247   MaxX = WindowWidth;
248   MaxY = WindowHeight;
249
250   ShowWindow (HWindow, show);
251   UpdateWindow (HWindow);
252
253   return MessageLoop();
254 }