winclock.c 6.84 KB
Newer Older
1
/*
Alexandre Julliard's avatar
Alexandre Julliard committed
2 3 4 5 6 7 8 9 10 11
 *  Clock (winclock.c)
 *
 *  Copyright 1998 by Marcel Baur <mbaur@g26.ethz.ch>
 *
 *  This file is based on  rolex.c  by Jim Peterson.
 *
 *  I just managed to move the relevant parts into the Clock application
 *  and made it look like the original Windows one. You can find the original
 *  rolex.c in the wine /libtest directory.
 *
12 13 14 15
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
Alexandre Julliard's avatar
Alexandre Julliard committed
16
 *
17 18 19 20 21 22 23
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
24
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Alexandre Julliard's avatar
Alexandre Julliard committed
25
 */
26 27 28
#include "config.h"
#include "wine/port.h"

Alexandre Julliard's avatar
Alexandre Julliard committed
29
#include <math.h>
30
#include <stdlib.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
31 32
#include <string.h>
#include "windows.h"
Richard Cohen's avatar
Richard Cohen committed
33 34
#include "winclock.h"

35 36 37 38 39
#define FaceColor (GetSysColor(COLOR_3DFACE))
#define HandColor (GetSysColor(COLOR_3DHIGHLIGHT))
#define TickColor (GetSysColor(COLOR_3DHIGHLIGHT))
#define ShadowColor (GetSysColor(COLOR_3DDKSHADOW))
#define BackgroundColor (GetSysColor(COLOR_3DFACE))
40 41

static const int SHADOW_DEPTH = 2;
42
 
Richard Cohen's avatar
Richard Cohen committed
43
typedef struct
44
{
Richard Cohen's avatar
Richard Cohen committed
45 46 47
    POINT Start;
    POINT End;
} HandData;
Alexandre Julliard's avatar
Alexandre Julliard committed
48

Richard Cohen's avatar
Richard Cohen committed
49
HandData HourHand, MinuteHand, SecondHand;
Alexandre Julliard's avatar
Alexandre Julliard committed
50

51
static void DrawTicks(HDC dc, const POINT* centre, int radius)
52
{
Richard Cohen's avatar
Richard Cohen committed
53
    int t;
54

55 56 57 58 59 60 61 62 63 64 65
    /* Minute divisions */
    if (radius>64)
        for(t=0; t<60; t++) {
            MoveToEx(dc,
                     centre->x + sin(t*M_PI/30)*0.9*radius,
                     centre->y - cos(t*M_PI/30)*0.9*radius,
                     NULL);
	    LineTo(dc,
		   centre->x + sin(t*M_PI/30)*0.89*radius,
		   centre->y - cos(t*M_PI/30)*0.89*radius);
	}
Richard Cohen's avatar
Richard Cohen committed
66

67
    /* Hour divisions */
Richard Cohen's avatar
Richard Cohen committed
68
    for(t=0; t<12; t++) {
69

Richard Cohen's avatar
Richard Cohen committed
70 71 72 73 74 75 76
        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);
77
    }
78 79
}

80
static void DrawFace(HDC dc, const POINT* centre, int radius, int border)
81 82 83 84 85 86 87 88
{
    /* Ticks */
    SelectObject(dc, CreatePen(PS_SOLID, 2, ShadowColor));
    OffsetWindowOrgEx(dc, -SHADOW_DEPTH, -SHADOW_DEPTH, NULL);
    DrawTicks(dc, centre, radius);
    DeleteObject(SelectObject(dc, CreatePen(PS_SOLID, 2, TickColor)));
    OffsetWindowOrgEx(dc, SHADOW_DEPTH, SHADOW_DEPTH, NULL);
    DrawTicks(dc, centre, radius);
89 90 91 92 93 94
    if (border)
    {
        SelectObject(dc, GetStockObject(NULL_BRUSH));
        DeleteObject(SelectObject(dc, CreatePen(PS_SOLID, 5, ShadowColor)));
        Ellipse(dc, centre->x - radius, centre->y - radius, centre->x + radius, centre->y + radius);
    }
95
    DeleteObject(SelectObject(dc, GetStockObject(NULL_PEN)));
Alexandre Julliard's avatar
Alexandre Julliard committed
96 97
}

Richard Cohen's avatar
Richard Cohen committed
98
static void DrawHand(HDC dc,HandData* hand)
Alexandre Julliard's avatar
Alexandre Julliard committed
99
{
Richard Cohen's avatar
Richard Cohen committed
100 101
    MoveToEx(dc, hand->Start.x, hand->Start.y, NULL);
    LineTo(dc, hand->End.x, hand->End.y);
Alexandre Julliard's avatar
Alexandre Julliard committed
102 103
}

104
static void DrawHands(HDC dc, BOOL bSeconds)
Alexandre Julliard's avatar
Alexandre Julliard committed
105
{
106 107 108 109 110 111 112 113 114 115
    if (bSeconds) {
#if 0
      	SelectObject(dc, CreatePen(PS_SOLID, 1, ShadowColor));
	OffsetWindowOrgEx(dc, -SHADOW_DEPTH, -SHADOW_DEPTH, NULL);
        DrawHand(dc, &SecondHand);
	DeleteObject(SelectObject(dc, CreatePen(PS_SOLID, 1, HandColor)));
	OffsetWindowOrgEx(dc, SHADOW_DEPTH, SHADOW_DEPTH, NULL);
#else
	SelectObject(dc, CreatePen(PS_SOLID, 1, HandColor));
#endif
116
        DrawHand(dc, &SecondHand);
117 118 119 120 121 122 123 124 125 126 127
	DeleteObject(SelectObject(dc, GetStockObject(NULL_PEN)));
    }

    SelectObject(dc, CreatePen(PS_SOLID, 4, ShadowColor));

    OffsetWindowOrgEx(dc, -SHADOW_DEPTH, -SHADOW_DEPTH, NULL);
    DrawHand(dc, &MinuteHand);
    DrawHand(dc, &HourHand);

    DeleteObject(SelectObject(dc, CreatePen(PS_SOLID, 4, HandColor)));
    OffsetWindowOrgEx(dc, SHADOW_DEPTH, SHADOW_DEPTH, NULL);
Richard Cohen's avatar
Richard Cohen committed
128 129
    DrawHand(dc, &MinuteHand);
    DrawHand(dc, &HourHand);
130 131

    DeleteObject(SelectObject(dc, GetStockObject(NULL_PEN)));
Alexandre Julliard's avatar
Alexandre Julliard committed
132 133
}

Richard Cohen's avatar
Richard Cohen committed
134
static void PositionHand(const POINT* centre, double length, double angle, HandData* hand)
Alexandre Julliard's avatar
Alexandre Julliard committed
135
{
Richard Cohen's avatar
Richard Cohen committed
136 137 138
    hand->Start = *centre;
    hand->End.x = centre->x + sin(angle)*length;
    hand->End.y = centre->y - cos(angle)*length;
Alexandre Julliard's avatar
Alexandre Julliard committed
139 140
}

141
static void PositionHands(const POINT* centre, int radius, BOOL bSeconds)
Alexandre Julliard's avatar
Alexandre Julliard committed
142
{
Richard Cohen's avatar
Richard Cohen committed
143 144
    SYSTEMTIME st;
    double hour, minute, second;
Alexandre Julliard's avatar
Alexandre Julliard committed
145

Richard Cohen's avatar
Richard Cohen committed
146 147 148 149
    /* 0 <= hour,minute,second < 2pi */
    /* Adding the millisecond count makes the second hand move more smoothly */

    GetLocalTime(&st);
150

Richard Cohen's avatar
Richard Cohen committed
151 152 153 154 155 156
    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);
157 158
    if (bSeconds)
        PositionHand(centre, radius * 0.79, second/60 * 2*M_PI, &SecondHand);  
Alexandre Julliard's avatar
Alexandre Julliard committed
159 160
}

161
void AnalogClock(HDC dc, int x, int y, BOOL bSeconds, BOOL border)
Alexandre Julliard's avatar
Alexandre Julliard committed
162
{
Richard Cohen's avatar
Richard Cohen committed
163 164
    POINT centre;
    int radius;
165 166 167 168
    
    radius = min(x, y)/2 - SHADOW_DEPTH;
    if (radius < 0)
	return;
169

Richard Cohen's avatar
Richard Cohen committed
170 171
    centre.x = x/2;
    centre.y = y/2;
172

173
    DrawFace(dc, &centre, radius, border);
174

175 176
    PositionHands(&centre, radius, bSeconds);
    DrawHands(dc, bSeconds);
Alexandre Julliard's avatar
Alexandre Julliard committed
177 178
}

179 180

HFONT SizeFont(HDC dc, int x, int y, BOOL bSeconds, const LOGFONT* font)
181
{
182 183 184
    SIZE extent;
    LOGFONT lf;
    double xscale, yscale;
185 186 187
    HFONT oldFont, newFont;
    CHAR szTime[255];
    int chars;
188

189 190 191 192 193 194
    chars = GetTimeFormat(LOCALE_USER_DEFAULT, bSeconds ? 0 : TIME_NOSECONDS, NULL,
			  NULL, szTime, sizeof (szTime));
    if (!chars)
	return 0;

    --chars;
195

196
    lf = *font;
197 198
    lf.lfHeight = -20;

199 200
    x -= 2 * SHADOW_DEPTH;
    y -= 2 * SHADOW_DEPTH;
201 202

    oldFont = SelectObject(dc, CreateFontIndirect(&lf));
203 204 205
    GetTextExtentPoint(dc, szTime, chars, &extent);
    DeleteObject(SelectObject(dc, oldFont));

206 207
    xscale = (double)x/extent.cx;
    yscale = (double)y/extent.cy;
208 209
    lf.lfHeight *= min(xscale, yscale);    
    newFont = CreateFontIndirect(&lf);
210

211 212 213 214 215 216 217 218 219
    return newFont;
}

void DigitalClock(HDC dc, int x, int y, BOOL bSeconds, HFONT font)
{
    SIZE extent;
    HFONT oldFont;
    CHAR szTime[255];
    int chars;
220

221 222 223 224 225 226 227 228 229 230 231 232 233
    chars = GetTimeFormat(LOCALE_USER_DEFAULT, bSeconds ? 0 : TIME_NOSECONDS, NULL,
		  NULL, szTime, sizeof (szTime));
    if (!chars)
	return;
    --chars;

    oldFont = SelectObject(dc, font);
    GetTextExtentPoint(dc, szTime, chars, &extent);

    SetBkColor(dc, BackgroundColor);
    SetTextColor(dc, ShadowColor);
    TextOut(dc, (x - extent.cx)/2 + SHADOW_DEPTH, (y - extent.cy)/2 + SHADOW_DEPTH,
	    szTime, chars);
234 235
    SetBkMode(dc, TRANSPARENT);

236 237 238 239
    SetTextColor(dc, HandColor);
    TextOut(dc, (x - extent.cx)/2, (y - extent.cy)/2, szTime, chars);

    SelectObject(dc, oldFont);
Alexandre Julliard's avatar
Alexandre Julliard committed
240
}