winclock.c 6.86 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

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

33 34 35 36 37
#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))
38 39

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

47
static HandData HourHand, MinuteHand, SecondHand;
Alexandre Julliard's avatar
Alexandre Julliard committed
48

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

53 54 55 56 57 58 59 60 61 62 63
    /* 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
64

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

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

78
static void DrawFace(HDC dc, const POINT* centre, int radius, int border)
79 80 81 82 83 84 85 86
{
    /* 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);
87 88 89 90 91 92
    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);
    }
93
    DeleteObject(SelectObject(dc, GetStockObject(NULL_PEN)));
Alexandre Julliard's avatar
Alexandre Julliard committed
94 95
}

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

102
static void DrawHands(HDC dc, BOOL bSeconds)
Alexandre Julliard's avatar
Alexandre Julliard committed
103
{
104 105 106 107 108 109 110 111 112 113
    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
114
        DrawHand(dc, &SecondHand);
115 116 117 118 119 120 121 122 123 124 125
	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
126 127
    DrawHand(dc, &MinuteHand);
    DrawHand(dc, &HourHand);
128 129

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

Richard Cohen's avatar
Richard Cohen committed
132
static void PositionHand(const POINT* centre, double length, double angle, HandData* hand)
Alexandre Julliard's avatar
Alexandre Julliard committed
133
{
Richard Cohen's avatar
Richard Cohen committed
134 135 136
    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
137 138
}

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

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

    GetLocalTime(&st);
148

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

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

Richard Cohen's avatar
Richard Cohen committed
168 169
    centre.x = x/2;
    centre.y = y/2;
170

171
    DrawFace(dc, &centre, radius, border);
172

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

177

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

187
    chars = GetTimeFormatW(LOCALE_USER_DEFAULT, bSeconds ? 0 : TIME_NOSECONDS, NULL,
188
                           NULL, szTime, ARRAY_SIZE(szTime));
189 190 191 192
    if (!chars)
	return 0;

    --chars;
193

194
    lf = *font;
195 196
    lf.lfHeight = -20;

197 198
    x -= 2 * SHADOW_DEPTH;
    y -= 2 * SHADOW_DEPTH;
199

200 201
    oldFont = SelectObject(dc, CreateFontIndirectW(&lf));
    GetTextExtentPointW(dc, szTime, chars, &extent);
202 203
    DeleteObject(SelectObject(dc, oldFont));

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

209 210 211 212 213 214 215
    return newFont;
}

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

219
    chars = GetTimeFormatW(LOCALE_USER_DEFAULT, bSeconds ? 0 : TIME_NOSECONDS, NULL,
220
                           NULL, szTime, ARRAY_SIZE(szTime));
221 222 223 224 225
    if (!chars)
	return;
    --chars;

    oldFont = SelectObject(dc, font);
226
    GetTextExtentPointW(dc, szTime, chars, &extent);
227 228 229

    SetBkColor(dc, BackgroundColor);
    SetTextColor(dc, ShadowColor);
230
    TextOutW(dc, (x - extent.cx)/2 + SHADOW_DEPTH, (y - extent.cy)/2 + SHADOW_DEPTH, szTime, chars);
231 232
    SetBkMode(dc, TRANSPARENT);

233
    SetTextColor(dc, HandColor);
234
    TextOutW(dc, (x - extent.cx)/2, (y - extent.cy)/2, szTime, chars);
235 236

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