[clock03] Repainting

Richard Cohen richard.cohen at virgin.net
Fri Jul 11 13:26:55 CDT 2003


Changelog:
	+ Remove Idle()
	+ Fix repainting artefacts by drawing only through WM_PAINT
	+ Unify hand drawing functions
	+ 0 & 6 ticks are now always vertical
-------------- next part --------------
diff -u programs/clock.2/main.c programs/clock/main.c
--- programs/clock.2/main.c	2003-07-11 17:48:00.000000000 +0100
+++ programs/clock/main.c	2003-07-11 18:07:50.000000000 +0100
@@ -26,12 +26,14 @@
 #include "config.h"
 
 #include <stdio.h>
+
 #include "windows.h"
+#include "commdlg.h"
+
 #include "main.h"
 #include "license.h"
 #include "language.h"
 #include "winclock.h"
-#include "commdlg.h"
 
 #define INITIAL_WINDOW_SIZE 200
 #define TIMER_ID 1
@@ -176,14 +178,10 @@
             HDC context;
             
             context = BeginPaint(hWnd, &ps);
-            if(Globals.bAnalog) {
-                DrawFace(context);
-                Idle(context);
-            }
+	if(Globals.bAnalog)
+	    AnalogClock(context, Globals.MaxX, Globals.MaxY);
             else
-            {
-                /* do nothing */
-            }
+	    DigitalClock(context, Globals.MaxX, Globals.MaxY);
             EndPaint(hWnd, &ps);
             break;
         }
@@ -191,9 +189,6 @@
         case WM_SIZE: {
             Globals.MaxX = LOWORD(lParam);
             Globals.MaxY = HIWORD(lParam);
-            OldHour.DontRedraw   = TRUE;
-            OldMinute.DontRedraw = TRUE;
-            OldSecond.DontRedraw = TRUE;
             break;
         }
 
@@ -203,8 +198,11 @@
         }
             
         case WM_TIMER: {
-            Idle(0);
-            break;
+	/* Could just invalidate the changed hands, 
+	 * but it doesn't really seem worth the effort
+	 */
+	    InvalidateRect(Globals.hMainWnd, NULL, FALSE);
+	    break;
         }
 
         case WM_DESTROY: {
diff -u programs/clock.2/winclock.c programs/clock/winclock.c
--- programs/clock.2/winclock.c	2003-07-11 17:46:58.000000000 +0100
+++ programs/clock/winclock.c	2003-07-11 18:01:58.000000000 +0100
@@ -27,231 +27,124 @@
 #include <math.h>
 #include <stdlib.h>
 #include <string.h>
-#include "winclock.h"
 #include "windows.h"
-#include "main.h"
 #include "winnls.h"
+#include "winclock.h"
+
+#define MIN(a,b) (((a)<(b))?(a):(b))
 
 COLORREF FaceColor = RGB(192,192,192);
 COLORREF HandColor = RGB(0,0,0);
 COLORREF EtchColor = RGB(0,0,0);
 
-float Pi=3.1415926;
-
-int nLastSecond = 60;
-
-HandData OldSecond,OldHour,OldMinute;
-
-int MiddleX(void)
+typedef struct
 {
-    int X, diff;
+    POINT Start;
+    POINT End;
+} HandData;
 
-    X    = (Globals.MaxX/2);
-    diff = (Globals.MaxX-Globals.MaxY);
-    if (diff>0) { X = (X-(diff/2)); }
-    return X;
-}
+HandData HourHand, MinuteHand, SecondHand;
 
-int MiddleY(void)
+static void DrawFace(HDC dc, const POINT* centre, int radius)
 {
-    int Y, diff;
-    
-    Y    = (Globals.MaxY/2);
-    diff = (Globals.MaxX-Globals.MaxY);
-    if (diff<0) { Y = Y+(diff/2); }
-    return Y;
-}
-
-void DrawFace(HDC dc)
-{
-    int MidX, MidY, t, DiffX, DiffY;
-
-    MidX = MiddleX();
-    MidY = MiddleY();
-    DiffX = (Globals.MaxX-MidX*2)/2;
-    DiffY = (Globals.MaxY-MidY*2)/2;
+    int t;
 
     SelectObject(dc,CreateSolidBrush(FaceColor));
     SelectObject(dc,CreatePen(PS_SOLID,1,EtchColor));
-    Ellipse(dc,DiffX,DiffY,2*MidX+DiffX,2*MidY+DiffY);
-
-    for(t=0; t<12; t++)
-    {
-        MoveToEx(dc,(MidX+DiffX)+sin(t*Pi/6)*0.9*MidX,(MidY+DiffY)-cos(t*Pi/6)*0.9*MidY,NULL);
-        LineTo(dc,(MidY+DiffX)+sin(t*Pi/6)*0.8*MidX,(MidY+DiffY)-cos(t*Pi/6)*0.8*MidY);
+    Ellipse(dc,
+            centre->x - radius, centre->y - radius,
+            centre->x + radius, centre->y + radius);
+
+    for(t=0; t<12; t++) {
+        MoveToEx(dc,
+                 centre->x + sin(t*M_PI/6)*0.9*radius,
+                 centre->y - cos(t*M_PI/6)*0.9*radius,
+                 NULL);
+        LineTo(dc,
+               centre->x + sin(t*M_PI/6)*0.8*radius,
+               centre->y - cos(t*M_PI/6)*0.8*radius);
     }
-    if(Globals.MaxX>64 && Globals.MaxY>64)
+    if (radius>64)
         for(t=0; t<60; t++)
-            SetPixel(dc,(MidX+DiffX)+sin(t*Pi/30)*0.9*MidX,(MidY+DiffY)-cos(t*Pi/30)*0.9*MidY
-                     ,EtchColor);
+            SetPixel(dc,
+                     centre->x + sin(t*M_PI/30)*0.9*radius,
+                     centre->y - cos(t*M_PI/30)*0.9*radius,
+                     EtchColor);
     DeleteObject(SelectObject(dc,GetStockObject(NULL_BRUSH)));
     DeleteObject(SelectObject(dc,GetStockObject(NULL_PEN)));
-    memset(&OldSecond,0,sizeof(OldSecond));
-    memset(&OldMinute,0,sizeof(OldMinute));
-    memset(&OldHour,0,sizeof(OldHour));
 }
 
-void DrawHourHand(HDC dc)
+static void DrawHand(HDC dc,HandData* hand)
 {
-    if (OldHour.DontRedraw) return;
-    MoveToEx(dc, OldHour.StartX, OldHour.StartY, NULL);
-    LineTo(dc, OldHour.EndX, OldHour.EndY);
+    MoveToEx(dc, hand->Start.x, hand->Start.y, NULL);
+    LineTo(dc, hand->End.x, hand->End.y);
 }
 
-void DrawMinuteHand(HDC dc)
+static void DrawHands(HDC dc)
 {
-    if (OldMinute.DontRedraw) return;
-    MoveToEx(dc, OldMinute.StartX, OldMinute.StartY, NULL);
-    LineTo(dc, OldMinute.EndX, OldMinute.EndY);
+    SelectObject(dc,CreatePen(PS_SOLID,1,HandColor));
+    DrawHand(dc, &SecondHand);
+    DrawHand(dc, &MinuteHand);
+    DrawHand(dc, &HourHand);
+    DeleteObject(SelectObject(dc,GetStockObject(NULL_PEN)));
 }
 
-void DrawSecondHand(HDC dc)
+static void PositionHand(const POINT* centre, double length, double angle, HandData* hand)
 {
-    if (OldSecond.DontRedraw) return;
-    MoveToEx(dc, OldSecond.StartX, OldSecond.StartY, NULL);
-    LineTo(dc, OldSecond.EndX, OldSecond.EndY);
+    hand->Start = *centre;
+    hand->End.x = centre->x + sin(angle)*length;
+    hand->End.y = centre->y - cos(angle)*length;
 }
 
-BOOL UpdateHourHand(HDC dc,int MidX,int MidY,int XExt,int YExt,WORD Pos)
+static void PositionHands(const POINT* centre, int radius)
 {
-    int Sx, Sy, Ex, Ey;
-    BOOL rv;
-    
-    rv = FALSE;
-    Sx = MidX; Sy = MidY;
-    Ex = MidX+sin(Pos*Pi/6000)*XExt;
-    Ey = MidY-cos(Pos*Pi/6000)*YExt;
-    rv = ( Sx!=OldHour.StartX || Ex!=OldHour.EndX ||
-           Sy!=OldHour.StartY || Ey!=OldHour.EndY );
-    if (Globals.bAnalog && rv)DrawHourHand(dc);
-    OldHour.StartX = Sx; OldHour.EndX = Ex;
-    OldHour.StartY = Sy; OldHour.EndY = Ey;
-    OldHour.DontRedraw=FALSE;
-    return rv;
+    SYSTEMTIME st;
+    double hour, minute, second;
+
+    /* 0 <= hour,minute,second < 2pi */
+    /* Adding the millisecond count makes the second hand move more smoothly */
+
+    GetLocalTime(&st);
+    second = st.wSecond + st.wMilliseconds/1000.0;
+    minute = st.wMinute + second/60.0;
+    hour   = st.wHour % 12 + minute/60.0;
+
+    PositionHand(centre, radius * 0.5,  hour/12   * 2*M_PI, &HourHand);
+    PositionHand(centre, radius * 0.65, minute/60 * 2*M_PI, &MinuteHand);
+    PositionHand(centre, radius * 0.79, second/60 * 2*M_PI, &SecondHand);  
 }
 
-BOOL UpdateMinuteHand(HDC dc,int MidX,int MidY,int XExt,int YExt,WORD Pos)
+void AnalogClock(HDC dc, int x, int y)
 {
-    int Sx, Sy, Ex, Ey;
-    BOOL rv;
-    
-    rv = FALSE;
-    Sx = MidX; Sy = MidY;
-    Ex = MidX+sin(Pos*Pi/30000)*XExt;
-    Ey = MidY-cos(Pos*Pi/30000)*YExt;
-    rv = ( Sx!=OldMinute.StartX || Ex!=OldMinute.EndX ||
-           Sy!=OldMinute.StartY || Ey!=OldMinute.EndY );
-    if (Globals.bAnalog && rv)DrawMinuteHand(dc);
-    OldMinute.StartX = Sx; OldMinute.EndX = Ex;
-    OldMinute.StartY = Sy; OldMinute.EndY = Ey;
-    OldMinute.DontRedraw=FALSE;
-    return rv;
-}
-
-BOOL UpdateSecondHand(HDC dc,int MidX,int MidY,int XExt,int YExt,WORD Pos)
-{
-    int Sx, Sy, Ex, Ey;
-    BOOL rv;
-
-    rv = FALSE;
-
-    if (Globals.bSeconds) {
-        Sx = MidX; Sy = MidY;
-        Ex = MidX+sin(Pos*Pi/3000)*XExt;
-        Ey = MidY-cos(Pos*Pi/3000)*YExt;
-        rv = ( Sx!=OldSecond.StartX || Ex!=OldSecond.EndX ||
-               Sy!=OldSecond.StartY || Ey!=OldSecond.EndY );
-        if (Globals.bAnalog && rv) DrawSecondHand(dc);
-        OldSecond.StartX = Sx; OldSecond.EndX = Ex;
-        OldSecond.StartY = Sy; OldSecond.EndY = Ey;
-        OldSecond.DontRedraw=FALSE;
-    }
+    POINT centre;
+    int radius;
+    radius = MIN(x, y)/2;
 
-    return rv;
+    centre.x = x/2;
+    centre.y = y/2;
+
+    DrawFace(dc, &centre, radius);
+    PositionHands(&centre, radius);
+    DrawHands(dc);
 }
 
-void DigitalClock(HDC dc)
+void DigitalClock(HDC dc, int X, int Y)
 {
-    CHAR szTime[MAX_STRING_LEN];
-    LPSTR time = szTime;
+    /* FIXME - this doesn't work very well */
+    CHAR szTime[255];
     static short xChar, yChar;
     TEXTMETRIC tm;
-
     SYSTEMTIME st;
-    LPSYSTEMTIME lpst = &st;
     
     GetLocalTime(&st);
-    GetTimeFormat(LOCALE_USER_DEFAULT, LOCALE_STIMEFORMAT, lpst, NULL, time,
-                  MAX_STRING_LEN);
-
-    SelectObject(dc,CreatePen(PS_SOLID,1,FaceColor));
+    GetTimeFormat(LOCALE_USER_DEFAULT, LOCALE_STIMEFORMAT, &st, NULL,
+                  szTime, sizeof szTime);    
     xChar = tm.tmAveCharWidth;
     yChar = tm.tmHeight;
-    
     xChar = 100;
     yChar = 100;
-    TextOut (dc, xChar, yChar, szTime, strlen (szTime));
-    DeleteObject(SelectObject(dc,GetStockObject(NULL_PEN)));
-}
-
-
-
-void AnalogClock(HDC dc)
-{
-    SYSTEMTIME st;
-    WORD H, M, S, F;
-    int MidX, MidY, DiffX, DiffY;
-    BOOL Redraw;
-
-    GetLocalTime(&st);
-    
-    S = st.wSecond;
-    nLastSecond = S;
-    H = st.wHour;
-    M = st.wMinute;
-    F = st.wMilliseconds / 10;
-    F = F + S*100;
-    M = M*1000+F/6;
-    H = H*1000+M/60;
-    MidX = MiddleX();
-    MidY = MiddleY();
-    DiffX = (Globals.MaxX-MidX*2)/2;
-    DiffY = (Globals.MaxY-MidY*2)/2;
 
     SelectObject(dc,CreatePen(PS_SOLID,1,FaceColor));
-    Redraw = FALSE;
-    if(UpdateHourHand(dc,MidX+DiffX,MidY+DiffY,MidX*0.5,MidY*0.5,H)) Redraw = TRUE;
-    if(UpdateMinuteHand(dc,MidX+DiffX,MidY+DiffY,MidX*0.65,MidY*0.65,M)) Redraw = TRUE;
-    if(UpdateSecondHand(dc,MidX+DiffX,MidY+DiffY,MidX*0.79,MidY*0.79,F)) Redraw = TRUE;
-
-    DeleteObject(SelectObject(dc,CreatePen(PS_SOLID,1,HandColor)));
-    if(Redraw)
-    {
-        DrawSecondHand(dc);
-        DrawMinuteHand(dc);
-        DrawHourHand(dc);
-    }
-    DeleteObject(SelectObject(dc,GetStockObject(NULL_PEN)));
-}
-
-void Idle(HDC idc)
-{
-    HDC context;
-    
-    if(idc)
-        context=idc;
-    else
-        context=GetDC(Globals.hMainWnd);
-
-    if (!context) return;
-    
-    if (Globals.bAnalog)
-    {
-        AnalogClock(context);
-    }
-    else
-    {
-        DigitalClock(context);
-    }
-    if(!idc) ReleaseDC(Globals.hMainWnd, context);
+    TextOut (dc, xChar, yChar, szTime, strlen (szTime));
+    DeleteObject(SelectObject(dc,GetStockObject(NULL_PEN)));   
 }
Only in programs/clock/: winclock.c.orig
diff -u programs/clock.2/winclock.h programs/clock/winclock.h
--- programs/clock.2/winclock.h	2002-06-01 00:40:58.000000000 +0100
+++ programs/clock/winclock.h	2003-07-11 17:58:32.000000000 +0100
@@ -21,24 +21,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
- #include <windows.h>
+void AnalogClock(HDC dc, int X, int Y);
+void DigitalClock(HDC dc, int X, int Y);
 
-typedef struct
-{
-  int StartX,StartY,EndX,EndY;
-  BOOL DontRedraw;
-} HandData;
 
-extern HandData OldMinute, OldHour, OldSecond;
-
-/* function prototypes */
-
-
-void DrawFace(HDC dc);
-void DrawHourHand(HDC dc);
-void DrawMinuteHand(HDC dc);
-void DrawSecondHand(HDC dc);
-BOOL UpdateHourHand(HDC dc,int MidX,int MidY,int XExt,int YExt,WORD Pos);
-BOOL UpdateMinuteHand(HDC dc,int MidX,int MidY,int XExt,int YExt,WORD Pos);
-BOOL UpdateSecondHand(HDC dc,int MidX,int MidY,int XExt,int YExt,WORD Pos);
-void Idle(HDC idc);


More information about the wine-patches mailing list