source: trunk/src/comctl32/monthcal.cpp@ 2875

Last change on this file since 2875 was 2875, checked in by cbratschi, 26 years ago

C -> C++, WINE animate, treeview WM_VSCROLL fixed

File size: 48.8 KB
Line 
1/* $Id: */
2/* Month calendar control
3 *
4 * Copyright 1998, 1999 Eric Kohl (ekohl@abo.rhein-zeitung.de)
5 * Copyright 1999 Alex Priem (alexp@sci.kun.nl)
6 * Copyright 1999 Chris Morgan <cmorgan@wpi.edu> and
7 * James Abbatiello <abbeyj@wpi.edu>
8 * Copyright 2000 Christoph Bratschi
9 *
10 * TODO:
11 * - Notifications.
12 *
13 *
14 * FIXME: refresh should ask for rect of required length. (?)
15 * FIXME: handle resources better (doesn't work now); also take care
16 of internationalization.
17 * FIXME: keyboard handling.
18 */
19
20/* WINE 20000130 level */
21
22#include "winbase.h"
23#include "win.h"
24#include "commctrl.h"
25#include "comctl32.h"
26#include "monthcal.h"
27#include "winnls.h"
28#include <stdio.h>
29#include <string.h>
30#include <stdlib.h>
31
32//DEFAULT_DEBUG_CHANNEL(monthcal)
33
34/* take #days/month from ole/parsedt.c;
35 * we want full month-names, and abbreviated weekdays, so these are
36 * defined here */
37
38static const int mdays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0};
39
40const char * const monthtxt[] = {"January", "February", "March", "April", "May",
41 "June", "July", "August", "September", "October",
42 "November", "December"};
43const char * const daytxt[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
44static const int DayOfWeekTable[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
45
46
47#define MONTHCAL_GetInfoPtr(hwnd) ((MONTHCAL_INFO *)GetWindowLongA(hwnd, 0))
48
49/* helper functions */
50
51/* returns the number of days in any given month */
52/* january is 1, december is 12 */
53static int MONTHCAL_MonthLength(int month, int year)
54{
55 /* if we have a leap year add 1 day to February */
56 /* a leap year is a year either divisible by 400 */
57 /* or divisible by 4 and not by 100 */
58 if(month == 2) { /* February */
59 return mdays[month - 1] + ((year%400 == 0) ? 1 : ((year%100 != 0) &&
60 (year%4 == 0)) ? 1 : 0);
61 }
62 else {
63 return mdays[month - 1];
64 }
65}
66
67
68/* make sure that time is valid */
69static int MONTHCAL_ValidateTime(SYSTEMTIME time)
70{
71 if(time.wMonth > 12) return FALSE;
72 if(time.wDayOfWeek > 6) return FALSE;
73 if(time.wDay > MONTHCAL_MonthLength(time.wMonth, time.wYear))
74 return FALSE;
75 if(time.wHour > 23) return FALSE;
76 if(time.wMinute > 59) return FALSE;
77 if(time.wSecond > 59) return FALSE;
78 if(time.wMilliseconds > 999) return FALSE;
79
80 return TRUE;
81}
82
83
84void MONTHCAL_CopyTime(const SYSTEMTIME *from, SYSTEMTIME *to)
85{
86 to->wYear = from->wYear;
87 to->wMonth = from->wMonth;
88 to->wDayOfWeek = from->wDayOfWeek;
89 to->wDay = from->wDay;
90 to->wHour = from->wHour;
91 to->wMinute = from->wMinute;
92 to->wSecond = from->wSecond;
93 to->wMilliseconds = from->wMilliseconds;
94}
95
96
97/* Note:Depending on DST, this may be offset by a day.
98 Need to find out if we're on a DST place & adjust the clock accordingly.
99 Above function assumes we have a valid data.
100 Valid for year>1752; 1 <= d <= 31, 1 <= m <= 12.
101 0 = Monday.
102*/
103
104/* returns the day in the week(0 == sunday, 6 == saturday) */
105/* day(1 == 1st, 2 == 2nd... etc), year is the year value */
106int MONTHCAL_CalculateDayOfWeek(DWORD day, DWORD month, DWORD year)
107{
108 year-=(month < 3);
109
110 return((year + year/4 - year/100 + year/400 +
111 DayOfWeekTable[month-1] + day - 1 ) % 7);
112}
113
114
115static int MONTHCAL_CalcDayFromPos(MONTHCAL_INFO *infoPtr, int x, int y)
116{
117 int daypos, weekpos, retval, firstDay;
118
119 /* if the point is outside the x bounds of the window put
120 it at the boundry */
121 if(x > (infoPtr->width_increment * 7.0)) {
122 x = infoPtr->rcClient.right - infoPtr->rcClient.left - infoPtr->left_offset;
123 }
124
125 daypos = (x -(infoPtr->prevmonth.left + infoPtr->left_offset)) / infoPtr->width_increment;
126 weekpos = (y - infoPtr->days.bottom - infoPtr->rcClient.top) / infoPtr->height_increment;
127
128 firstDay = MONTHCAL_CalculateDayOfWeek(1, infoPtr->currentMonth, infoPtr->currentYear);
129 retval = daypos + (7 * weekpos) - firstDay;
130 //TRACE("%d %d %d\n", daypos, weekpos, retval);
131 return retval;
132}
133
134/* day is the day of the month, 1 == 1st day of the month */
135/* sets x and y to be the position of the day */
136/* x == day, y == week where(0,0) == sunday, 1st week */
137static void MONTHCAL_CalcDayXY(MONTHCAL_INFO *infoPtr, int day, int month,
138 int *x, int *y)
139{
140 int firstDay, prevMonth;
141
142 firstDay = MONTHCAL_CalculateDayOfWeek(1, infoPtr->currentMonth, infoPtr->currentYear);
143
144 if(month==infoPtr->currentMonth) {
145 *x = (day + firstDay) % 7;
146 *y = (day + firstDay - *x) / 7;
147 return;
148 }
149 if(month < infoPtr->currentMonth) {
150 prevMonth = month - 1;
151 if(prevMonth==0)
152 prevMonth = 12;
153
154 *x = (MONTHCAL_MonthLength(prevMonth, infoPtr->currentYear) - firstDay) % 7;
155 *y = 0;
156 return;
157 }
158
159 *y = MONTHCAL_MonthLength(month, infoPtr->currentYear - 1) / 7;
160 *x = (day + firstDay + MONTHCAL_MonthLength(month,
161 infoPtr->currentYear)) % 7;
162}
163
164
165/* x: column(day), y: row(week) */
166static void MONTHCAL_CalcDayRect(MONTHCAL_INFO *infoPtr, RECT *r, int x, int y)
167{
168 r->left = infoPtr->prevmonth.left + x * infoPtr->width_increment + infoPtr->left_offset;
169 r->right = r->left + infoPtr->width_increment;
170 r->top = infoPtr->height_increment * y + infoPtr->days.bottom + infoPtr->top_offset;
171 r->bottom = r->top + infoPtr->textHeight;
172}
173
174
175/* sets the RECT struct r to the rectangle around the day and month */
176/* day is the day value of the month(1 == 1st), month is the month */
177/* value(january == 1, december == 12) */
178static void MONTHCAL_CalcPosFromDay(MONTHCAL_INFO *infoPtr,
179 int day, int month, RECT *r)
180{
181 int x, y;
182
183 MONTHCAL_CalcDayXY(infoPtr, day, month, &x, &y);
184 MONTHCAL_CalcDayRect(infoPtr, r, x, y);
185}
186
187
188/* day is the day in the month(1 == 1st of the month) */
189/* month is the month value(1 == january, 12 == december) */
190static void MONTHCAL_CircleDay(HDC hdc, MONTHCAL_INFO *infoPtr, int day,
191int month)
192{
193 HPEN hRedPen = CreatePen(PS_SOLID, 2, RGB(255, 0, 0));
194 HPEN hOldPen2 = SelectObject(hdc, hRedPen);
195 POINT points[13];
196 int x, y;
197 RECT day_rect;
198
199 /* use prevmonth to calculate position because it contains the extra width
200 * from MCS_WEEKNUMBERS
201 */
202
203 MONTHCAL_CalcPosFromDay(infoPtr, day, month, &day_rect);
204
205 x = day_rect.left;
206 y = day_rect.top;
207
208 points[0].x = x;
209 points[0].y = y - 1;
210 points[1].x = x + 0.8 * infoPtr->width_increment;
211 points[1].y = y - 1;
212 points[2].x = x + 0.9 * infoPtr->width_increment;
213 points[2].y = y;
214 points[3].x = x + infoPtr->width_increment;
215 points[3].y = y + 0.5 * infoPtr->textHeight;
216
217 points[4].x = x + infoPtr->width_increment;
218 points[4].y = y + 0.9 * infoPtr->textHeight;
219 points[5].x = x + 0.6 * infoPtr->width_increment;
220 points[5].y = y + 0.9 * infoPtr->textHeight;
221 points[6].x = x + 0.5 * infoPtr->width_increment;
222 points[6].y = y + 0.9 * infoPtr->textHeight; /* bring the bottom up just
223 a hair to fit inside the day rectangle */
224
225 points[7].x = x + 0.2 * infoPtr->width_increment;
226 points[7].y = y + 0.8 * infoPtr->textHeight;
227 points[8].x = x + 0.1 * infoPtr->width_increment;
228 points[8].y = y + 0.8 * infoPtr->textHeight;
229 points[9].x = x;
230 points[9].y = y + 0.5 * infoPtr->textHeight;
231
232 points[10].x = x + 0.1 * infoPtr->width_increment;
233 points[10].y = y + 0.2 * infoPtr->textHeight;
234 points[11].x = x + 0.2 * infoPtr->width_increment;
235 points[11].y = y + 0.3 * infoPtr->textHeight;
236 points[12].x = x + 0.5 * infoPtr->width_increment;
237 points[12].y = y + 0.3 * infoPtr->textHeight;
238
239 PolyBezier(hdc, points, 13);
240 DeleteObject(hRedPen);
241 SelectObject(hdc, hOldPen2);
242}
243
244
245static void MONTHCAL_DrawDay(HDC hdc, MONTHCAL_INFO *infoPtr,
246 int day, int month, int x, int y, int bold)
247{
248 char buf[10];
249 RECT r;
250 static int haveBoldFont, haveSelectedDay = FALSE;
251 HBRUSH hbr;
252 HPEN hNewPen, hOldPen = 0;
253 COLORREF oldCol = 0;
254 COLORREF oldBk = 0;
255
256 sprintf(buf, "%d", day);
257
258/* No need to check styles: when selection is not valid, it is set to zero.
259 * 1<day<31, so evertyhing's OK.
260 */
261
262 MONTHCAL_CalcDayRect(infoPtr, &r, x, y);
263
264 if((day>=infoPtr->minSel.wDay) && (day<=infoPtr->maxSel.wDay)
265 && (month==infoPtr->currentMonth)) {
266 HRGN hrgn;
267 RECT r2;
268
269 //TRACE("%d %d %d\n",day, infoPtr->minSel.wDay, infoPtr->maxSel.wDay);
270 //TRACE("%d %d %d %d\n", r.left, r.top, r.right, r.bottom);
271 oldCol = SetTextColor(hdc, infoPtr->monthbk);
272 oldBk = SetBkColor(hdc, infoPtr->trailingtxt);
273 hbr = GetSysColorBrush(COLOR_GRAYTEXT);
274 hrgn = CreateEllipticRgn(r.left, r.top, r.right, r.bottom);
275 FillRgn(hdc, hrgn, hbr);
276
277 /* FIXME: this may need to be changed now b/c of the other
278 drawing changes 11/3/99 CMM */
279 r2.left = r.left - 0.25 * infoPtr->textWidth;
280 r2.top = r.top;
281 r2.right = r.left + 0.5 * infoPtr->textWidth;
282 r2.bottom = r.bottom;
283 if(haveSelectedDay) FillRect(hdc, &r2, hbr);
284 haveSelectedDay = TRUE;
285 } else {
286 haveSelectedDay = FALSE;
287 }
288
289 /* need to add some code for multiple selections */
290
291 if((bold) &&(!haveBoldFont)) {
292 SelectObject(hdc, infoPtr->hBoldFont);
293 haveBoldFont = TRUE;
294 }
295 if((!bold) &&(haveBoldFont)) {
296 SelectObject(hdc, infoPtr->hFont);
297 haveBoldFont = FALSE;
298 }
299
300 if(haveSelectedDay) {
301 SetTextColor(hdc, oldCol);
302 SetBkColor(hdc, oldBk);
303 }
304
305 DrawTextA(hdc, buf, lstrlenA(buf), &r,
306 DT_CENTER | DT_VCENTER | DT_SINGLELINE );
307
308 /* draw a rectangle around the currently selected days text */
309 if((day==infoPtr->curSelDay) && (month==infoPtr->currentMonth)) {
310 hNewPen = CreatePen(PS_DOT, 0, GetSysColor(COLOR_WINDOWTEXT) );
311 hbr = GetSysColorBrush(COLOR_WINDOWTEXT);
312 FrameRect(hdc, &r, hbr);
313 SelectObject(hdc, hOldPen);
314 }
315}
316
317
318/* CHECKME: For `todays date', do we need to check the locale?*/
319static void MONTHCAL_Refresh(HWND hwnd, HDC hdc)
320{
321 MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd);
322 RECT *rcClient=&infoPtr->rcClient;
323 RECT *rcDraw=&infoPtr->rcDraw;
324 RECT *title=&infoPtr->title;
325 RECT *prev=&infoPtr->titlebtnprev;
326 RECT *next=&infoPtr->titlebtnnext;
327 RECT *titlemonth=&infoPtr->titlemonth;
328 RECT *titleyear=&infoPtr->titleyear;
329 RECT *prevmonth=&infoPtr->prevmonth;
330 RECT *nextmonth=&infoPtr->nextmonth;
331 RECT dayrect;
332 RECT *days=&dayrect;
333 RECT *weeknums=&infoPtr->weeknums;
334 RECT *rtoday=&infoPtr->today;
335 int i, j, m, mask, day, firstDay, weeknum, prevMonth;
336 int textHeight = infoPtr->textHeight, textWidth = infoPtr->textWidth;
337 SIZE size;
338 HBRUSH hbr;
339 HFONT currentFont;
340 /* LOGFONTA logFont; */
341 char buf[20];
342 const char *thisMonthtxt;
343 COLORREF oldTextColor, oldBkColor;
344 DWORD dwStyle = GetWindowLongA(hwnd, GWL_STYLE);
345 BOOL prssed;
346
347 oldTextColor = SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
348
349 /* draw control edge */
350 hbr = CreateSolidBrush(RGB(255, 255, 255));
351 FillRect(hdc, rcClient, hbr);
352 DrawEdge(hdc, rcClient, EDGE_SUNKEN, BF_RECT);
353 DeleteObject(hbr);
354 prssed = FALSE;
355
356 /* draw header */
357 hbr = CreateSolidBrush(infoPtr->titlebk);
358 FillRect(hdc, title, hbr);
359
360 /* if the previous button is pressed draw it depressed */
361 if((infoPtr->status & MC_PREVPRESSED))
362 DrawFrameControl(hdc, prev, DFC_SCROLL,
363 DFCS_SCROLLLEFT | DFCS_PUSHED |
364 (dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0));
365 else /* if the previous button is pressed draw it depressed */
366 DrawFrameControl(hdc, prev, DFC_SCROLL,
367 DFCS_SCROLLLEFT |(dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0));
368
369 /* if next button is depressed draw it depressed */
370 if((infoPtr->status & MC_NEXTPRESSED))
371 DrawFrameControl(hdc, next, DFC_SCROLL,
372 DFCS_SCROLLRIGHT | DFCS_PUSHED |
373 (dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0));
374 else /* if the next button is pressed draw it depressed */
375 DrawFrameControl(hdc, next, DFC_SCROLL,
376 DFCS_SCROLLRIGHT |(dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0));
377
378 oldBkColor = SetBkColor(hdc, infoPtr->titlebk);
379 SetTextColor(hdc, infoPtr->titletxt);
380 currentFont = SelectObject(hdc, infoPtr->hBoldFont);
381
382 /* titlemonth->left and right are set in MONTHCAL_UpdateSize */
383 titlemonth->left = title->left;
384 titlemonth->right = title->right;
385
386 thisMonthtxt = monthtxt[infoPtr->currentMonth - 1];
387 sprintf(buf, "%s %ld", thisMonthtxt, infoPtr->currentYear);
388 DrawTextA(hdc, buf, strlen(buf), titlemonth,
389 DT_CENTER | DT_VCENTER | DT_SINGLELINE);
390 SelectObject(hdc, infoPtr->hFont);
391
392/* titlemonth left/right contained rect for whole titletxt('June 1999')
393 * MCM_HitTestInfo wants month & year rects, so prepare these now.
394 *(no, we can't draw them separately; the whole text is centered)
395 */
396 GetTextExtentPoint32A(hdc, buf, lstrlenA(buf), &size);
397 titlemonth->left = title->right / 2 - size.cx / 2;
398 titleyear->right = title->right / 2 + size.cx / 2;
399 GetTextExtentPoint32A(hdc, thisMonthtxt, lstrlenA(thisMonthtxt), &size);
400 titlemonth->right = titlemonth->left + size.cx;
401 titleyear->right = titlemonth->right;
402
403
404/* draw line under day abbreviatons */
405
406 if(dwStyle & MCS_WEEKNUMBERS)
407 MoveToEx(hdc, rcDraw->left + textWidth + 3, title->bottom + textHeight + 2, NULL);
408 else
409 MoveToEx(hdc, rcDraw->left + 3, title->bottom + textHeight + 2, NULL);
410
411 LineTo(hdc, rcDraw->right - 3, title->bottom + textHeight + 2);
412
413/* draw day abbreviations */
414
415 SetBkColor(hdc, infoPtr->monthbk);
416 SetTextColor(hdc, infoPtr->trailingtxt);
417
418 /* copy this rect so we can change the values without changing */
419 /* the original version */
420 days->left = infoPtr->days.left;
421 days->right = infoPtr->days.right;
422 days->top = infoPtr->days.top;
423 days->bottom = infoPtr->days.bottom;
424
425 i = infoPtr->firstDay;
426
427 for(j=0; j<7; j++) {
428 DrawTextA(hdc, daytxt[i], strlen(daytxt[i]), days,
429 DT_CENTER | DT_VCENTER | DT_SINGLELINE );
430 i = (i + 1) % 7;
431 days->left+=infoPtr->width_increment;
432 days->right+=infoPtr->width_increment;
433 }
434
435 days->left = rcDraw->left + j;
436 if(dwStyle & MCS_WEEKNUMBERS) days->left+=textWidth;
437 /* FIXME: this may need to be changed now 11/10/99 CMM */
438 days->right = rcDraw->left + (j+1) * textWidth - 2;
439
440/* draw day numbers; first, the previous month */
441
442 firstDay = MONTHCAL_CalculateDayOfWeek(1, infoPtr->currentMonth, infoPtr->currentYear);
443
444 prevMonth = infoPtr->currentMonth - 1;
445 if(prevMonth == 0) /* if currentMonth is january(1) prevMonth is */
446 prevMonth = 12; /* december(12) of the previous year */
447
448 day = MONTHCAL_MonthLength(prevMonth, infoPtr->currentYear) - firstDay;
449 mask = 1<<(day-1);
450
451 i = 0;
452 m = 0;
453 while(day <= MONTHCAL_MonthLength(prevMonth, infoPtr->currentYear)) {
454 MONTHCAL_DrawDay(hdc, infoPtr, day, prevMonth, i, 0,
455 infoPtr->monthdayState[m] & mask);
456 mask<<=1;
457 day++;
458 i++;
459 }
460
461 prevmonth->left = 0;
462 if(dwStyle & MCS_WEEKNUMBERS) prevmonth->left = textWidth;
463 prevmonth->right = prevmonth->left + i * textWidth;
464 prevmonth->top = days->bottom;
465 prevmonth->bottom = prevmonth->top + textHeight;
466
467/* draw `current' month */
468
469 day = 1; /* start at the beginning of the current month */
470
471 infoPtr->firstDayplace = i;
472 SetTextColor(hdc, infoPtr->txt);
473 m++;
474 mask = 1;
475
476 /* draw the first week of the current month */
477 while(i<7) {
478 MONTHCAL_DrawDay(hdc, infoPtr, day, infoPtr->currentMonth, i, 0,
479 infoPtr->monthdayState[m] & mask);
480
481 if((infoPtr->currentMonth==infoPtr->todaysDate.wMonth) &&
482 (day==infoPtr->todaysDate.wDay) &&
483 (infoPtr->currentYear == infoPtr->todaysDate.wYear)) {
484 MONTHCAL_CircleDay(hdc, infoPtr, day, infoPtr->currentMonth);
485 }
486
487 mask<<=1;
488 day++;
489 i++;
490 }
491
492 j = 1; /* move to the 2nd week of the current month */
493 i = 0; /* move back to sunday */
494 while(day <= MONTHCAL_MonthLength(infoPtr->currentMonth, infoPtr->currentYear)) {
495 MONTHCAL_DrawDay(hdc, infoPtr, day, infoPtr->currentMonth, i, j,
496 infoPtr->monthdayState[m] & mask);
497
498 if((infoPtr->currentMonth==infoPtr->todaysDate.wMonth) &&
499 (day==infoPtr->todaysDate.wDay) &&
500 (infoPtr->currentYear == infoPtr->todaysDate.wYear))
501 MONTHCAL_CircleDay(hdc, infoPtr, day, infoPtr->currentMonth);
502
503 mask<<=1;
504 day++;
505 i++;
506 if(i>6) { /* past saturday, goto the next weeks sunday */
507 i = 0;
508 j++;
509 }
510 }
511
512/* draw `next' month */
513
514/* note: the nextmonth rect only hints for the `half-week' that needs to be
515 * drawn to complete the current week. An eventual next week that needs to
516 * be drawn to complete the month calendar is not taken into account in
517 * this rect -- HitTest knows about this.*/
518
519 nextmonth->left = prevmonth->left + i * textWidth;
520 nextmonth->right = rcDraw->right;
521 nextmonth->top = days->bottom + (j+1) * textHeight;
522 nextmonth->bottom = nextmonth->top + textHeight;
523
524 day = 1; /* start at the first day of the next month */
525 m++;
526 mask = 1;
527
528 SetTextColor(hdc, infoPtr->trailingtxt);
529 while((i<7) &&(j<6)) {
530 MONTHCAL_DrawDay(hdc, infoPtr, day, infoPtr->currentMonth + 1, i, j,
531 infoPtr->monthdayState[m] & mask);
532
533 mask<<=1;
534 day++;
535 i++;
536 if(i==7) { /* past saturday, go to next week's sunday */
537 i = 0;
538 j++;
539 }
540 }
541 SetTextColor(hdc, infoPtr->txt);
542
543
544/* draw `today' date if style allows it, and draw a circle before today's
545 * date if necessary */
546
547 if(!(dwStyle & MCS_NOTODAY)) {
548 int offset = 0;
549 if(!(dwStyle & MCS_NOTODAYCIRCLE)) {
550 MONTHCAL_CircleDay(hdc, infoPtr, day, infoPtr->currentMonth + 1);
551 offset+=textWidth;
552 }
553 MONTHCAL_CalcDayRect(infoPtr, rtoday, offset==textWidth, 6);
554 sprintf(buf, "Today: %d/%d/%d", infoPtr->todaysDate.wMonth,
555 infoPtr->todaysDate.wDay, infoPtr->todaysDate.wYear % 100);
556 rtoday->right = rcDraw->right;
557 SelectObject(hdc, infoPtr->hBoldFont);
558 DrawTextA(hdc, buf, lstrlenA(buf), rtoday,
559 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
560 SelectObject(hdc, infoPtr->hFont);
561 }
562
563 if(dwStyle & MCS_WEEKNUMBERS) {
564 /* display weeknumbers*/
565 weeknums->left = 0;
566 weeknums->right = textWidth;
567 weeknums->top = days->bottom + 2;
568 weeknums->bottom = days->bottom + 2 + textHeight;
569
570 weeknum = 0;
571 for(i=0; i<infoPtr->currentMonth-1; i++)
572 weeknum+=MONTHCAL_MonthLength(i, infoPtr->currentYear);
573
574 weeknum/=7;
575 for(i=0; i<6; i++) {
576 sprintf(buf, "%d", weeknum + i);
577 DrawTextA(hdc, buf, lstrlenA(buf), weeknums,
578 DT_CENTER | DT_BOTTOM | DT_SINGLELINE );
579 weeknums->top+=textHeight * 1.25;
580 weeknums->bottom+=textHeight * 1.25;
581 }
582
583 MoveToEx(hdc, weeknums->right, days->bottom + 5 , NULL);
584 LineTo(hdc, weeknums->right, weeknums->bottom - 1.25 * textHeight - 5);
585
586 }
587
588 /* currentFont was font at entering Refresh */
589
590 SetBkColor(hdc, oldBkColor);
591 SelectObject(hdc, currentFont);
592 SetTextColor(hdc, oldTextColor);
593}
594
595
596static LRESULT
597MONTHCAL_GetMinReqRect(HWND hwnd, WPARAM wParam, LPARAM lParam)
598{
599 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
600 LPRECT lpRect = (LPRECT) lParam;
601 //TRACE("%x %lx\n", wParam, lParam);
602
603 /* validate parameters */
604
605 if((infoPtr==NULL) ||(lpRect == NULL) ) return FALSE;
606
607 lpRect->left = infoPtr->rcClient.left;
608 lpRect->right = infoPtr->rcClient.right;
609 lpRect->top = infoPtr->rcClient.top;
610 lpRect->bottom = infoPtr->rcClient.bottom;
611 return TRUE;
612}
613
614static LRESULT
615MONTHCAL_GetColor(HWND hwnd, WPARAM wParam, LPARAM lParam)
616{
617 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
618
619 //TRACE("%x %lx\n", wParam, lParam);
620
621 switch((int)wParam) {
622 case MCSC_BACKGROUND:
623 return infoPtr->bk;
624 case MCSC_TEXT:
625 return infoPtr->txt;
626 case MCSC_TITLEBK:
627 return infoPtr->titlebk;
628 case MCSC_TITLETEXT:
629 return infoPtr->titletxt;
630 case MCSC_MONTHBK:
631 return infoPtr->monthbk;
632 case MCSC_TRAILINGTEXT:
633 return infoPtr->trailingtxt;
634 }
635
636 return -1;
637}
638
639static LRESULT
640MONTHCAL_SetColor(HWND hwnd, WPARAM wParam, LPARAM lParam)
641{
642 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
643 int prev = -1;
644
645 //TRACE("%x %lx\n", wParam, lParam);
646
647 switch((int)wParam) {
648 case MCSC_BACKGROUND:
649 prev = infoPtr->bk;
650 infoPtr->bk = (COLORREF)lParam;
651 break;
652 case MCSC_TEXT:
653 prev = infoPtr->txt;
654 infoPtr->txt = (COLORREF)lParam;
655 break;
656 case MCSC_TITLEBK:
657 prev = infoPtr->titlebk;
658 infoPtr->titlebk = (COLORREF)lParam;
659 break;
660 case MCSC_TITLETEXT:
661 prev=infoPtr->titletxt;
662 infoPtr->titletxt = (COLORREF)lParam;
663 break;
664 case MCSC_MONTHBK:
665 prev = infoPtr->monthbk;
666 infoPtr->monthbk = (COLORREF)lParam;
667 break;
668 case MCSC_TRAILINGTEXT:
669 prev = infoPtr->trailingtxt;
670 infoPtr->trailingtxt = (COLORREF)lParam;
671 break;
672 }
673
674 return prev;
675}
676
677static LRESULT
678MONTHCAL_GetMonthDelta(HWND hwnd, WPARAM wParam, LPARAM lParam)
679{
680 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
681
682 //TRACE("%x %lx\n", wParam, lParam);
683
684 if(infoPtr->delta)
685 return infoPtr->delta;
686 else
687 return infoPtr->visible;
688}
689
690static LRESULT
691MONTHCAL_SetMonthDelta(HWND hwnd, WPARAM wParam, LPARAM lParam)
692{
693 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
694 int prev = infoPtr->delta;
695
696 //TRACE("%x %lx\n", wParam, lParam);
697
698 infoPtr->delta = (int)wParam;
699 return prev;
700}
701
702
703static LRESULT
704MONTHCAL_GetFirstDayOfWeek(HWND hwnd, WPARAM wParam, LPARAM lParam)
705{
706 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
707
708 return infoPtr->firstDay;
709}
710
711
712/* sets the first day of the week that will appear in the control */
713/* 0 == Monday, 6 == Sunday */
714/* FIXME: this needs to be implemented properly in MONTHCAL_Refresh() */
715/* FIXME: we need more error checking here */
716static LRESULT
717MONTHCAL_SetFirstDayOfWeek(HWND hwnd, WPARAM wParam, LPARAM lParam)
718{
719 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
720 int prev = infoPtr->firstDay;
721 char buf[40];
722 int day;
723
724 //TRACE("%x %lx\n", wParam, lParam);
725
726 if((lParam >= 0) && (lParam < 7)) {
727 infoPtr->firstDay = (int)lParam;
728 GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_IFIRSTDAYOFWEEK,
729 buf, sizeof(buf));
730 //TRACE("%s %d\n", buf, strlen(buf));
731 if((sscanf(buf, "%d", &day) == 1) &&(infoPtr->firstDay != day))
732 infoPtr->firstDay = day;
733 }
734 return prev;
735}
736
737
738/* FIXME: fill this in */
739static LRESULT
740MONTHCAL_GetMonthRange(HWND hwnd, WPARAM wParam, LPARAM lParam)
741{
742 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
743
744 //TRACE("%x %lx\n", wParam, lParam);
745 //FIXME("stub\n");
746
747 return infoPtr->monthRange;
748}
749
750
751static LRESULT
752MONTHCAL_GetMaxTodayWidth(HWND hwnd)
753{
754 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
755
756 return(infoPtr->today.right - infoPtr->today.left);
757}
758
759
760/* FIXME: are validated times taken from current date/time or simply
761 * copied?
762 * FIXME: check whether MCM_GETMONTHRANGE shows correct result after
763 * adjusting range with MCM_SETRANGE
764 */
765
766static LRESULT
767MONTHCAL_SetRange(HWND hwnd, WPARAM wParam, LPARAM lParam)
768{
769 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
770 SYSTEMTIME lprgSysTimeArray[1];
771 int prev;
772
773 //TRACE("%x %lx\n", wParam, lParam);
774
775 if(wParam & GDTR_MAX) {
776 if(MONTHCAL_ValidateTime(lprgSysTimeArray[1])){
777 MONTHCAL_CopyTime(&lprgSysTimeArray[1], &infoPtr->maxDate);
778 infoPtr->rangeValid|=GDTR_MAX;
779 } else {
780 GetSystemTime(&infoPtr->todaysDate);
781 MONTHCAL_CopyTime(&infoPtr->todaysDate, &infoPtr->maxDate);
782 }
783 }
784 if(wParam & GDTR_MIN) {
785 if(MONTHCAL_ValidateTime(lprgSysTimeArray[0])) {
786 MONTHCAL_CopyTime(&lprgSysTimeArray[0], &infoPtr->maxDate);
787 infoPtr->rangeValid|=GDTR_MIN;
788 } else {
789 GetSystemTime(&infoPtr->todaysDate);
790 MONTHCAL_CopyTime(&infoPtr->todaysDate, &infoPtr->maxDate);
791 }
792 }
793
794 prev = infoPtr->monthRange;
795 infoPtr->monthRange = infoPtr->maxDate.wMonth - infoPtr->minDate.wMonth;
796
797 if(infoPtr->monthRange!=prev) {
798 COMCTL32_ReAlloc(infoPtr->monthdayState,
799 infoPtr->monthRange * sizeof(MONTHDAYSTATE));
800 }
801
802 return 1;
803}
804
805
806/* CHECKME: At the moment, we copy ranges anyway,regardless of
807 * infoPtr->rangeValid; a invalid range is simply filled with zeros in
808 * SetRange. Is this the right behavior?
809*/
810
811static LRESULT
812MONTHCAL_GetRange(HWND hwnd, WPARAM wParam, LPARAM lParam)
813{
814 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
815 SYSTEMTIME *lprgSysTimeArray = (SYSTEMTIME *)lParam;
816
817 /* validate parameters */
818
819 if((infoPtr==NULL) || (lprgSysTimeArray==NULL)) return FALSE;
820
821 MONTHCAL_CopyTime(&infoPtr->maxDate, &lprgSysTimeArray[1]);
822 MONTHCAL_CopyTime(&infoPtr->minDate, &lprgSysTimeArray[0]);
823
824 return infoPtr->rangeValid;
825}
826
827
828static LRESULT
829MONTHCAL_SetDayState(HWND hwnd, WPARAM wParam, LPARAM lParam)
830
831{
832 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
833 int i, iMonths = (int)wParam;
834 MONTHDAYSTATE *dayStates = (LPMONTHDAYSTATE)lParam;
835
836 //TRACE("%x %lx\n", wParam, lParam);
837 if(iMonths!=infoPtr->monthRange) return 0;
838
839 for(i=0; i<iMonths; i++)
840 infoPtr->monthdayState[i] = dayStates[i];
841 return 1;
842}
843
844
845static LRESULT
846MONTHCAL_GetCurSel(HWND hwnd, WPARAM wParam, LPARAM lParam)
847{
848 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
849 SYSTEMTIME *lpSel = (SYSTEMTIME *) lParam;
850
851 //TRACE("%x %lx\n", wParam, lParam);
852 if((infoPtr==NULL) ||(lpSel==NULL)) return FALSE;
853 if(GetWindowLongA(hwnd, GWL_STYLE) & MCS_MULTISELECT) return FALSE;
854
855 MONTHCAL_CopyTime(&infoPtr->minSel, lpSel);
856 return TRUE;
857}
858
859
860/* FIXME: if the specified date is not visible, make it visible */
861/* FIXME: redraw? */
862static LRESULT
863MONTHCAL_SetCurSel(HWND hwnd, WPARAM wParam, LPARAM lParam)
864{
865 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
866 SYSTEMTIME *lpSel = (SYSTEMTIME *)lParam;
867
868 //TRACE("%x %lx\n", wParam, lParam);
869 if((infoPtr==NULL) ||(lpSel==NULL)) return FALSE;
870 if(GetWindowLongA(hwnd, GWL_STYLE) & MCS_MULTISELECT) return FALSE;
871
872 //TRACE("%d %d\n", lpSel->wMonth, lpSel->wDay);
873
874 MONTHCAL_CopyTime(lpSel, &infoPtr->minSel);
875 MONTHCAL_CopyTime(lpSel, &infoPtr->maxSel);
876
877 return TRUE;
878}
879
880
881static LRESULT
882MONTHCAL_GetMaxSelCount(HWND hwnd, WPARAM wParam, LPARAM lParam)
883{
884 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
885
886 //TRACE("%x %lx\n", wParam, lParam);
887 return infoPtr->maxSelCount;
888}
889
890
891static LRESULT
892MONTHCAL_SetMaxSelCount(HWND hwnd, WPARAM wParam, LPARAM lParam)
893{
894 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
895
896 //TRACE("%x %lx\n", wParam, lParam);
897 if(GetWindowLongA(hwnd, GWL_STYLE) & MCS_MULTISELECT) {
898 infoPtr->maxSelCount = wParam;
899 }
900
901 return TRUE;
902}
903
904
905static LRESULT
906MONTHCAL_GetSelRange(HWND hwnd, WPARAM wParam, LPARAM lParam)
907{
908 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
909 SYSTEMTIME *lprgSysTimeArray = (SYSTEMTIME *) lParam;
910
911 //TRACE("%x %lx\n", wParam, lParam);
912
913 /* validate parameters */
914
915 if((infoPtr==NULL) ||(lprgSysTimeArray==NULL)) return FALSE;
916
917 if(GetWindowLongA(hwnd, GWL_STYLE) & MCS_MULTISELECT)
918 {
919 MONTHCAL_CopyTime(&infoPtr->maxSel, &lprgSysTimeArray[1]);
920 MONTHCAL_CopyTime(&infoPtr->minSel, &lprgSysTimeArray[0]);
921 //TRACE("[min,max]=[%d %d]\n", infoPtr->minSel.wDay, infoPtr->maxSel.wDay);
922 return TRUE;
923 }
924
925 return FALSE;
926}
927
928
929static LRESULT
930MONTHCAL_SetSelRange(HWND hwnd, WPARAM wParam, LPARAM lParam)
931{
932 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
933 SYSTEMTIME *lprgSysTimeArray = (SYSTEMTIME *) lParam;
934
935 //TRACE("%x %lx\n", wParam, lParam);
936
937 /* validate parameters */
938
939 if((infoPtr==NULL) ||(lprgSysTimeArray==NULL)) return FALSE;
940
941 if(GetWindowLongA( hwnd, GWL_STYLE) & MCS_MULTISELECT)
942 {
943 MONTHCAL_CopyTime(&lprgSysTimeArray[1], &infoPtr->maxSel);
944 MONTHCAL_CopyTime(&lprgSysTimeArray[0], &infoPtr->minSel);
945 //TRACE("[min,max]=[%d %d]\n", infoPtr->minSel.wDay, infoPtr->maxSel.wDay);
946 return TRUE;
947 }
948
949 return FALSE;
950}
951
952
953static LRESULT
954MONTHCAL_GetToday(HWND hwnd, WPARAM wParam, LPARAM lParam)
955{
956 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
957 SYSTEMTIME *lpToday = (SYSTEMTIME *) lParam;
958
959 //TRACE("%x %lx\n", wParam, lParam);
960
961 /* validate parameters */
962
963 if((infoPtr==NULL) || (lpToday==NULL)) return FALSE;
964 MONTHCAL_CopyTime(&infoPtr->todaysDate, lpToday);
965 return TRUE;
966}
967
968
969static LRESULT
970MONTHCAL_SetToday(HWND hwnd, WPARAM wParam, LPARAM lParam)
971{
972 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
973 SYSTEMTIME *lpToday = (SYSTEMTIME *) lParam;
974
975 //TRACE("%x %lx\n", wParam, lParam);
976
977 /* validate parameters */
978
979 if((infoPtr==NULL) ||(lpToday==NULL)) return FALSE;
980 MONTHCAL_CopyTime(lpToday, &infoPtr->todaysDate);
981 return TRUE;
982}
983
984
985static LRESULT
986MONTHCAL_HitTest(HWND hwnd, LPARAM lParam)
987{
988 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
989 PMCHITTESTINFO lpht = (PMCHITTESTINFO)lParam;
990 UINT x,y;
991 DWORD retval;
992
993 x = lpht->pt.x;
994 y = lpht->pt.y;
995 retval = MCHT_NOWHERE;
996
997
998 /* are we in the header? */
999
1000 if(PtInRect(&infoPtr->title, lpht->pt)) {
1001 if(PtInRect(&infoPtr->titlebtnprev, lpht->pt)) {
1002 retval = MCHT_TITLEBTNPREV;
1003 goto done;
1004 }
1005 if(PtInRect(&infoPtr->titlebtnnext, lpht->pt)) {
1006 retval = MCHT_TITLEBTNNEXT;
1007 goto done;
1008 }
1009 if(PtInRect(&infoPtr->titlemonth, lpht->pt)) {
1010 retval = MCHT_TITLEMONTH;
1011 goto done;
1012 }
1013 if(PtInRect(&infoPtr->titleyear, lpht->pt)) {
1014 retval = MCHT_TITLEYEAR;
1015 goto done;
1016 }
1017
1018 retval = MCHT_TITLE;
1019 goto done;
1020 }
1021
1022 if(PtInRect(&infoPtr->days, lpht->pt)) {
1023 retval = MCHT_CALENDARDAY; /* FIXME: find out which day we're on */
1024 goto done;
1025 }
1026 if(PtInRect(&infoPtr->weeknums, lpht->pt)) {
1027 retval = MCHT_CALENDARWEEKNUM; /* FIXME: find out which day we're on */
1028 goto done;
1029 }
1030 if(PtInRect(&infoPtr->prevmonth, lpht->pt)) {
1031 retval = MCHT_CALENDARDATEPREV;
1032 goto done;
1033 }
1034
1035 if(PtInRect(&infoPtr->nextmonth, lpht->pt) ||
1036 ((x>infoPtr->nextmonth.left) &&(x<infoPtr->nextmonth.right) &&
1037 (y>infoPtr->nextmonth.bottom) &&(y<infoPtr->today.top ))) {
1038 retval = MCHT_CALENDARDATENEXT;
1039 goto done;
1040 }
1041
1042 if(PtInRect(&infoPtr->today, lpht->pt)) {
1043 retval = MCHT_TODAYLINK;
1044 goto done;
1045 }
1046
1047/* MCHT_CALENDARDATE determination: since the next & previous month have
1048 * been handled already(MCHT_CALENDARDATEPREV/NEXT), we only have to check
1049 * whether we're in the calendar area. infoPtr->prevMonth.left handles the
1050 * MCS_WEEKNUMBERS style nicely.
1051 */
1052
1053
1054 //TRACE("%d %d [%d %d %d %d] [%d %d %d %d]\n", x, y,
1055 // infoPtr->prevmonth.left, infoPtr->prevmonth.right,
1056 // infoPtr->prevmonth.top, infoPtr->prevmonth.bottom,
1057 // infoPtr->nextmonth.left, infoPtr->nextmonth.right,
1058 // infoPtr->nextmonth.top, infoPtr->nextmonth.bottom);
1059 if((x>infoPtr->prevmonth.left) &&(x<infoPtr->nextmonth.right) &&
1060 (y>infoPtr->prevmonth.top) &&(y<infoPtr->nextmonth.bottom)) {
1061 lpht->st.wYear = infoPtr->currentYear;
1062 lpht->st.wMonth = infoPtr->currentMonth;
1063
1064 lpht->st.wDay = MONTHCAL_CalcDayFromPos(infoPtr, x, y);
1065
1066 //TRACE("day hit: %d\n", lpht->st.wDay);
1067 retval = MCHT_CALENDARDATE;
1068 goto done;
1069
1070 }
1071
1072 /* Hit nothing special? What's left must be background :-) */
1073
1074 retval = MCHT_CALENDARBK;
1075 done:
1076 lpht->uHit = retval;
1077 return retval;
1078}
1079
1080
1081static void MONTHCAL_GoToNextMonth(HWND hwnd, MONTHCAL_INFO *infoPtr)
1082{
1083 DWORD dwStyle = GetWindowLongA(hwnd, GWL_STYLE);
1084
1085 //TRACE("MONTHCAL_GoToNextMonth\n");
1086
1087 infoPtr->currentMonth++;
1088 if(infoPtr->currentMonth > 12) {
1089 infoPtr->currentYear++;
1090 infoPtr->currentMonth = 1;
1091 }
1092
1093 if(dwStyle & MCS_DAYSTATE) {
1094 NMDAYSTATE nmds;
1095 int i;
1096
1097 nmds.nmhdr.hwndFrom = hwnd;
1098 nmds.nmhdr.idFrom = GetWindowLongA(hwnd, GWL_ID);
1099 nmds.nmhdr.code = MCN_GETDAYSTATE;
1100 nmds.cDayState = infoPtr->monthRange;
1101 nmds.prgDayState = (DWORD*)COMCTL32_Alloc(infoPtr->monthRange * sizeof(MONTHDAYSTATE));
1102
1103 SendMessageA(GetParent(hwnd), WM_NOTIFY,
1104 (WPARAM)nmds.nmhdr.idFrom, (LPARAM)&nmds);
1105 for(i=0; i<infoPtr->monthRange; i++)
1106 infoPtr->monthdayState[i] = nmds.prgDayState[i];
1107 }
1108}
1109
1110
1111static void MONTHCAL_GoToPrevMonth(HWND hwnd, MONTHCAL_INFO *infoPtr)
1112{
1113 DWORD dwStyle = GetWindowLongA(hwnd, GWL_STYLE);
1114
1115 //TRACE("MONTHCAL_GoToPrevMonth\n");
1116
1117 infoPtr->currentMonth--;
1118 if(infoPtr->currentMonth < 1) {
1119 infoPtr->currentYear--;
1120 infoPtr->currentMonth = 12;
1121 }
1122
1123 if(dwStyle & MCS_DAYSTATE) {
1124 NMDAYSTATE nmds;
1125 int i;
1126
1127 nmds.nmhdr.hwndFrom = hwnd;
1128 nmds.nmhdr.idFrom = GetWindowLongA(hwnd, GWL_ID);
1129 nmds.nmhdr.code = MCN_GETDAYSTATE;
1130 nmds.cDayState = infoPtr->monthRange;
1131 nmds.prgDayState = (DWORD*)COMCTL32_Alloc
1132 (infoPtr->monthRange * sizeof(MONTHDAYSTATE));
1133
1134 SendMessageA(GetParent(hwnd), WM_NOTIFY,
1135 (WPARAM)nmds.nmhdr.idFrom, (LPARAM)&nmds);
1136 for(i=0; i<infoPtr->monthRange; i++)
1137 infoPtr->monthdayState[i] = nmds.prgDayState[i];
1138 }
1139}
1140
1141
1142static LRESULT
1143MONTHCAL_LButtonDown(HWND hwnd, WPARAM wParam, LPARAM lParam)
1144{
1145 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
1146 MCHITTESTINFO ht;
1147 HDC hdc;
1148 DWORD hit;
1149 HMENU hMenu;
1150 HWND retval;
1151 BOOL redraw = FALSE;
1152
1153
1154 //TRACE("%x %lx\n", wParam, lParam);
1155
1156 ht.pt.x = (INT)LOWORD(lParam);
1157 ht.pt.y = (INT)HIWORD(lParam);
1158 hit = MONTHCAL_HitTest(hwnd, (LPARAM)&ht);
1159
1160 /* FIXME: these flags should be checked by */
1161 /*((hit & MCHT_XXX) == MCHT_XXX) b/c some of the flags are */
1162 /* multi-bit */
1163 if(hit & MCHT_NEXT) {
1164 redraw = TRUE;
1165 MONTHCAL_GoToNextMonth(hwnd, infoPtr);
1166 infoPtr->status = MC_NEXTPRESSED;
1167 SetTimer(hwnd, MC_NEXTMONTHTIMER, MC_NEXTMONTHDELAY, 0);
1168 }
1169 if(hit & MCHT_PREV) {
1170 redraw = TRUE;
1171 MONTHCAL_GoToPrevMonth(hwnd, infoPtr);
1172 infoPtr->status = MC_PREVPRESSED;
1173 SetTimer(hwnd, MC_PREVMONTHTIMER, MC_NEXTMONTHDELAY, 0);
1174 }
1175
1176 if(hit == MCHT_TITLEMONTH) {
1177/*
1178 HRSRC hrsrc = FindResourceA( COMCTL32_hModule, MAKEINTRESOURCEA(IDD_MCMONTHMENU), RT_MENUA );
1179 if(!hrsrc) {
1180 TRACE("returning zero\n");
1181 return 0;
1182 }
1183 TRACE("resource is:%x\n",hrsrc);
1184 hMenu = LoadMenuIndirectA((LPCVOID)LoadResource( COMCTL32_hModule, hrsrc ));
1185
1186 TRACE("menu is:%x\n",hMenu);
1187*/
1188
1189 hMenu = CreateMenu();
1190 AppendMenuA(hMenu, MF_STRING,IDM_JAN, "January");
1191 AppendMenuA(hMenu, MF_STRING,IDM_FEB, "February");
1192 AppendMenuA(hMenu, MF_STRING,IDM_MAR, "March");
1193
1194 retval = CreateWindowA(POPUPMENU_CLASS_ATOM, NULL,
1195 WS_CHILD | WS_VISIBLE, 0, 0 ,100 , 220,
1196 hwnd, hMenu, GetWindowLongA(hwnd, GWL_HINSTANCE), NULL);
1197 //TRACE("hwnd returned:%x\n", retval);
1198
1199 }
1200 if(hit == MCHT_TITLEYEAR) {
1201 //FIXME("create updown for yearselection\n");
1202 }
1203 if(hit == MCHT_TODAYLINK) {
1204 //FIXME("set currentday\n");
1205 }
1206 if(hit == MCHT_CALENDARDATE) {
1207 SYSTEMTIME selArray[2];
1208 NMSELCHANGE nmsc;
1209
1210 //TRACE("\n");
1211 nmsc.nmhdr.hwndFrom = hwnd;
1212 nmsc.nmhdr.idFrom = GetWindowLongA(hwnd, GWL_ID);
1213 nmsc.nmhdr.code = MCN_SELCHANGE;
1214 MONTHCAL_CopyTime(&nmsc.stSelStart, &infoPtr->minSel);
1215 MONTHCAL_CopyTime(&nmsc.stSelEnd, &infoPtr->maxSel);
1216
1217 SendMessageA(GetParent(hwnd), WM_NOTIFY,
1218 (WPARAM)nmsc.nmhdr.idFrom,(LPARAM)&nmsc);
1219
1220 MONTHCAL_CopyTime(&ht.st, &selArray[0]);
1221 MONTHCAL_CopyTime(&ht.st, &selArray[1]);
1222 MONTHCAL_SetSelRange(hwnd,0,(LPARAM) &selArray);
1223
1224 /* redraw if the selected day changed */
1225 if(infoPtr->curSelDay != ht.st.wDay) {
1226 redraw = TRUE;
1227 }
1228
1229 infoPtr->firstSelDay = ht.st.wDay;
1230 infoPtr->curSelDay = ht.st.wDay;
1231 infoPtr->status = MC_SEL_LBUTDOWN;
1232 }
1233
1234 /* redraw only if the control changed */
1235 if(redraw) {
1236 hdc = GetDC(hwnd);
1237 MONTHCAL_Refresh(hwnd, hdc);
1238 ReleaseDC(hwnd, hdc);
1239 }
1240
1241 return 0;
1242}
1243
1244
1245static LRESULT
1246MONTHCAL_LButtonUp(HWND hwnd, WPARAM wParam, LPARAM lParam)
1247{
1248 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
1249 NMSELCHANGE nmsc;
1250 NMHDR nmhdr;
1251 HDC hdc;
1252 BOOL redraw = FALSE;
1253
1254 //TRACE("\n");
1255
1256 if(infoPtr->status & MC_NEXTPRESSED) {
1257 KillTimer(hwnd, MC_NEXTMONTHTIMER);
1258 redraw = TRUE;
1259 }
1260 if(infoPtr->status & MC_PREVPRESSED) {
1261 KillTimer(hwnd, MC_PREVMONTHTIMER);
1262 redraw = TRUE;
1263 }
1264
1265 infoPtr->status = MC_SEL_LBUTUP;
1266
1267 nmhdr.hwndFrom = hwnd;
1268 nmhdr.idFrom = GetWindowLongA( hwnd, GWL_ID);
1269 nmhdr.code = NM_RELEASEDCAPTURE;
1270 //TRACE("Sent notification from %x to %x\n", hwnd, GetParent(hwnd));
1271
1272 SendMessageA(GetParent(hwnd), WM_NOTIFY,
1273 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1274
1275 nmsc.nmhdr.hwndFrom = hwnd;
1276 nmsc.nmhdr.idFrom = GetWindowLongA(hwnd, GWL_ID);
1277 nmsc.nmhdr.code = MCN_SELECT;
1278 MONTHCAL_CopyTime(&nmsc.stSelStart, &infoPtr->minSel);
1279 MONTHCAL_CopyTime(&nmsc.stSelEnd, &infoPtr->maxSel);
1280
1281 SendMessageA(GetParent(hwnd), WM_NOTIFY,
1282 (WPARAM)nmsc.nmhdr.idFrom, (LPARAM)&nmsc);
1283
1284 /* redraw if necessary */
1285 if(redraw) {
1286 hdc = GetDC(hwnd);
1287 MONTHCAL_Refresh(hwnd, hdc);
1288 ReleaseDC(hwnd, hdc);
1289 }
1290
1291 return 0;
1292}
1293
1294
1295static LRESULT
1296MONTHCAL_Timer(HWND hwnd, WPARAM wParam, LPARAM lParam)
1297{
1298 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
1299 HDC hdc;
1300 BOOL redraw = FALSE;
1301
1302 //TRACE(" %d\n", wParam);
1303 if(!infoPtr) return 0;
1304
1305 switch(wParam) {
1306 case MC_NEXTMONTHTIMER:
1307 redraw = TRUE;
1308 MONTHCAL_GoToNextMonth(hwnd, infoPtr);
1309 break;
1310 case MC_PREVMONTHTIMER:
1311 redraw = TRUE;
1312 MONTHCAL_GoToPrevMonth(hwnd, infoPtr);
1313 break;
1314 //default:
1315 // ERR("got unknown timer\n");
1316 }
1317
1318 /* redraw only if necessary */
1319 if(redraw) {
1320 hdc = GetDC(hwnd);
1321 MONTHCAL_Refresh(hwnd, hdc);
1322 ReleaseDC(hwnd, hdc);
1323 }
1324
1325 return 0;
1326}
1327
1328
1329static LRESULT
1330MONTHCAL_MouseMove(HWND hwnd, WPARAM wParam, LPARAM lParam)
1331{
1332 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
1333 MCHITTESTINFO ht;
1334 HDC hdc;
1335 int oldselday, selday, hit;
1336 RECT r;
1337
1338 if(!(infoPtr->status & MC_SEL_LBUTDOWN)) return 0;
1339
1340 ht.pt.x = LOWORD(lParam);
1341 ht.pt.y = HIWORD(lParam);
1342
1343 hit = MONTHCAL_HitTest(hwnd, (LPARAM)&ht);
1344
1345 /* not on the calendar date numbers? bail out */
1346 //TRACE("hit:%x\n",hit);
1347 if((hit & MCHT_CALENDARDATE) != MCHT_CALENDARDATE) return 0;
1348
1349 selday = ht.st.wDay;
1350 oldselday = infoPtr->curSelDay;
1351 infoPtr->curSelDay = selday;
1352 MONTHCAL_CalcPosFromDay(infoPtr, selday, ht.st. wMonth, &r);
1353
1354 if(GetWindowLongA(hwnd, GWL_STYLE) & MCS_MULTISELECT) {
1355 SYSTEMTIME selArray[2];
1356 int i;
1357
1358 MONTHCAL_GetSelRange(hwnd, 0, (LPARAM)&selArray);
1359 i = 0;
1360 if(infoPtr->firstSelDay==selArray[0].wDay) i=1;
1361 //TRACE("oldRange:%d %d %d %d\n", infoPtr->firstSelDay, selArray[0].wDay, selArray[1].wDay, i);
1362 if(infoPtr->firstSelDay==selArray[1].wDay) {
1363 /* 1st time we get here: selArray[0]=selArray[1]) */
1364 /* if we're still at the first selected date, return */
1365 if(infoPtr->firstSelDay==selday) goto done;
1366 if(selday<infoPtr->firstSelDay) i = 0;
1367 }
1368
1369 if(abs(infoPtr->firstSelDay - selday) >= infoPtr->maxSelCount) {
1370 if(selday>infoPtr->firstSelDay)
1371 selday = infoPtr->firstSelDay + infoPtr->maxSelCount;
1372 else
1373 selday = infoPtr->firstSelDay - infoPtr->maxSelCount;
1374 }
1375
1376 if(selArray[i].wDay!=selday) {
1377 //TRACE("newRange:%d %d %d %d\n", infoPtr->firstSelDay, selArray[0].wDay, selArray[1].wDay, i);
1378
1379 selArray[i].wDay = selday;
1380
1381 if(selArray[0].wDay>selArray[1].wDay) {
1382 DWORD tempday;
1383 tempday = selArray[1].wDay;
1384 selArray[1].wDay = selArray[0].wDay;
1385 selArray[0].wDay = tempday;
1386 }
1387
1388 MONTHCAL_SetSelRange(hwnd, 0, (LPARAM)&selArray);
1389 }
1390 }
1391
1392done:
1393
1394 /* only redraw if the currently selected day changed */
1395 if(oldselday != infoPtr->curSelDay) {
1396 hdc = GetDC(hwnd);
1397 MONTHCAL_Refresh(hwnd, hdc);
1398 ReleaseDC(hwnd, hdc);
1399 }
1400
1401 return 0;
1402}
1403
1404
1405static LRESULT
1406MONTHCAL_Paint(HWND hwnd, WPARAM wParam)
1407{
1408 HDC hdc;
1409 PAINTSTRUCT ps;
1410
1411 hdc = (wParam==0 ? BeginPaint(hwnd, &ps) : (HDC)wParam);
1412 MONTHCAL_Refresh(hwnd, hdc);
1413 if(!wParam) EndPaint(hwnd, &ps);
1414 return 0;
1415}
1416
1417
1418static LRESULT
1419MONTHCAL_KillFocus(HWND hwnd, WPARAM wParam, LPARAM lParam)
1420{
1421 HDC hdc;
1422
1423 //TRACE("\n");
1424
1425 hdc = GetDC(hwnd);
1426 MONTHCAL_Refresh(hwnd, hdc);
1427 ReleaseDC(hwnd, hdc);
1428 InvalidateRect(hwnd, NULL, TRUE);
1429
1430 return 0;
1431}
1432
1433
1434static LRESULT
1435MONTHCAL_SetFocus(HWND hwnd, WPARAM wParam, LPARAM lParam)
1436{
1437 HDC hdc;
1438
1439 //TRACE("\n");
1440
1441 hdc = GetDC(hwnd);
1442 MONTHCAL_Refresh(hwnd, hdc);
1443 ReleaseDC(hwnd, hdc);
1444
1445 return 0;
1446}
1447
1448/* sets the size information */
1449static void MONTHCAL_UpdateSize(HWND hwnd)
1450{
1451 HDC hdc = GetDC(hwnd);
1452 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
1453 RECT *rcClient=&infoPtr->rcClient;
1454 RECT *rcDraw=&infoPtr->rcDraw;
1455 RECT *title=&infoPtr->title;
1456 RECT *prev=&infoPtr->titlebtnprev;
1457 RECT *next=&infoPtr->titlebtnnext;
1458 RECT *titlemonth=&infoPtr->titlemonth;
1459 RECT *titleyear=&infoPtr->titleyear;
1460 RECT *days=&infoPtr->days;
1461 SIZE size;
1462 TEXTMETRICA tm;
1463 DWORD dwStyle = GetWindowLongA(hwnd, GWL_STYLE);
1464 HFONT currentFont;
1465
1466 currentFont = SelectObject(hdc, infoPtr->hFont);
1467
1468 /* FIXME: need a way to determine current font, without setting it */
1469 /*
1470 if(infoPtr->hFont!=currentFont) {
1471 SelectObject(hdc, currentFont);
1472 infoPtr->hFont=currentFont;
1473 GetObjectA(currentFont, sizeof(LOGFONTA), &logFont);
1474 logFont.lfWeight=FW_BOLD;
1475 infoPtr->hBoldFont = CreateFontIndirectA(&logFont);
1476 }
1477 */
1478
1479 /* get the height and width of each day's text */
1480 GetTextMetricsA(hdc, &tm);
1481 infoPtr->textHeight = tm.tmHeight + tm.tmExternalLeading;
1482 GetTextExtentPoint32A(hdc, "Sun", 3, &size);
1483 infoPtr->textWidth = size.cx + 2;
1484
1485 /* retrieve the controls client rectangle info infoPtr->rcClient */
1486 GetClientRect(hwnd, rcClient);
1487
1488 if(dwStyle & MCS_WEEKNUMBERS)
1489 infoPtr->rcClient.right+=infoPtr->textWidth;
1490
1491 /* rcDraw is the rectangle the control is drawn in */
1492 rcDraw->left = rcClient->left;
1493 rcDraw->right = rcClient->right;
1494 rcDraw->top = rcClient->top;
1495 rcDraw->bottom = rcClient->bottom;
1496
1497 /* use DrawEdge to adjust the size of rcClient such that we */
1498 /* do not overwrite the border when drawing the control */
1499 DrawEdge((HDC)NULL, rcDraw, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1500
1501
1502 /* this is correct, the control does NOT expand vertically */
1503 /* like it does horizontally */
1504 /* make sure we don't move the controls bottom out of the client */
1505 /* area */
1506 if((rcDraw->top + 8 * infoPtr->textHeight + 5) < rcDraw->bottom) {
1507 rcDraw->bottom = rcDraw->top + 8 * infoPtr->textHeight + 5;
1508 }
1509
1510 /* calculate title area */
1511 title->top = rcClient->top + 1;
1512 title->bottom = title->top + 2 * infoPtr->textHeight + 4;
1513 title->left = rcClient->left + 1;
1514 title->right = rcClient->right - 1;
1515
1516 /* recalculate the height and width increments and offsets */
1517 infoPtr->width_increment = (infoPtr->rcDraw.right - infoPtr->rcDraw.left) / 7.0;
1518 infoPtr->height_increment = (infoPtr->rcDraw.bottom - infoPtr->rcDraw.top) / 7.0;
1519 infoPtr->left_offset = (infoPtr->rcDraw.right - infoPtr->rcDraw.left) - (infoPtr->width_increment * 7.0);
1520 infoPtr->top_offset = (infoPtr->rcDraw.bottom - infoPtr->rcDraw.top) - (infoPtr->height_increment * 7.0);
1521
1522 /* set the dimensions of the next and previous buttons and center */
1523 /* the month text vertically */
1524 prev->top = next->top = title->top + 6;
1525 prev->bottom = next->bottom = title->top + 2 * infoPtr->textHeight - 3;
1526 prev->right = title->left + 28;
1527 prev->left = title->left + 4;
1528 next->left = title->right - 28;
1529 next->right = title->right - 4;
1530
1531 /* titlemonth->left and right change based upon the current month */
1532 /* and are recalculated in refresh as the current month may change */
1533 /* without the control being resized */
1534 titlemonth->bottom = titleyear->bottom = prev->top + 2 * infoPtr->textHeight - 3;
1535 titlemonth->top = titleyear->top = title->top;
1536
1537 /* setup the dimensions of the rectangle we draw the names of the */
1538 /* days of the week in */
1539 days->left = infoPtr->left_offset;
1540 if(dwStyle & MCS_WEEKNUMBERS) days->left+=infoPtr->textWidth;
1541 days->right = days->left + infoPtr->width_increment;
1542 days->top = title->bottom + 2;
1543 days->bottom = title->bottom + infoPtr->textHeight + 2;
1544
1545 /* restore the originally selected font */
1546 SelectObject(hdc, currentFont);
1547
1548 ReleaseDC(hwnd, hdc);
1549}
1550
1551static LRESULT MONTHCAL_Size(HWND hwnd, int Width, int Height)
1552{
1553 //TRACE("(hwnd=%x, width=%d, height=%d)\n", hwnd, Width, Height);
1554
1555 MONTHCAL_UpdateSize(hwnd);
1556
1557 /* invalidate client area and erase background */
1558 InvalidateRect(hwnd, NULL, TRUE);
1559
1560 return 0;
1561}
1562
1563/* FIXME: check whether dateMin/dateMax need to be adjusted. */
1564static LRESULT
1565MONTHCAL_Create(HWND hwnd, WPARAM wParam, LPARAM lParam)
1566{
1567 MONTHCAL_INFO *infoPtr;
1568 LOGFONTA logFont;
1569
1570 /* allocate memory for info structure */
1571 infoPtr =(MONTHCAL_INFO*)COMCTL32_Alloc(sizeof(MONTHCAL_INFO));
1572 SetWindowLongA(hwnd, 0, (DWORD)infoPtr);
1573
1574 if(infoPtr == NULL) {
1575 //ERR( "could not allocate info memory!\n");
1576 return 0;
1577 }
1578 if((MONTHCAL_INFO*)GetWindowLongA(hwnd, 0) != infoPtr) {
1579 //ERR( "pointer assignment error!\n");
1580 return 0;
1581 }
1582
1583 infoPtr->hFont = GetStockObject(DEFAULT_GUI_FONT);
1584 GetObjectA(infoPtr->hFont, sizeof(LOGFONTA), &logFont);
1585 logFont.lfWeight = FW_BOLD;
1586 infoPtr->hBoldFont = CreateFontIndirectA(&logFont);
1587
1588 /* initialize info structure */
1589 /* FIXME: calculate systemtime ->> localtime(substract timezoneinfo) */
1590
1591 GetSystemTime(&infoPtr->todaysDate);
1592 infoPtr->firstDay = 0;
1593 infoPtr->currentMonth = infoPtr->todaysDate.wMonth;
1594 infoPtr->currentYear = infoPtr->todaysDate.wYear;
1595 MONTHCAL_CopyTime(&infoPtr->todaysDate, &infoPtr->minDate);
1596 MONTHCAL_CopyTime(&infoPtr->todaysDate, &infoPtr->maxDate);
1597 infoPtr->maxSelCount = 6;
1598 infoPtr->monthRange = 3;
1599 infoPtr->monthdayState = (MONTHDAYSTATE*)COMCTL32_Alloc
1600 (infoPtr->monthRange * sizeof(MONTHDAYSTATE));
1601 infoPtr->titlebk = GetSysColor(COLOR_ACTIVECAPTION);
1602 infoPtr->titletxt = GetSysColor(COLOR_WINDOW);
1603 infoPtr->monthbk = GetSysColor(COLOR_WINDOW);
1604 infoPtr->trailingtxt = GetSysColor(COLOR_GRAYTEXT);
1605 infoPtr->bk = GetSysColor(COLOR_WINDOW);
1606 infoPtr->txt = GetSysColor(COLOR_WINDOWTEXT);
1607
1608 /* call MONTHCAL_UpdateSize to set all of the dimensions */
1609 /* of the control */
1610 MONTHCAL_UpdateSize(hwnd);
1611
1612 return 0;
1613}
1614
1615
1616static LRESULT
1617MONTHCAL_Destroy(HWND hwnd, WPARAM wParam, LPARAM lParam)
1618{
1619 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
1620
1621 /* free month calendar info data */
1622 COMCTL32_Free(infoPtr);
1623
1624 return 0;
1625}
1626
1627
1628static LRESULT WINAPI
1629MONTHCAL_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1630{
1631 switch(uMsg)
1632 {
1633 case MCM_GETCURSEL:
1634 return MONTHCAL_GetCurSel(hwnd, wParam, lParam);
1635
1636 case MCM_SETCURSEL:
1637 return MONTHCAL_SetCurSel(hwnd, wParam, lParam);
1638
1639 case MCM_GETMAXSELCOUNT:
1640 return MONTHCAL_GetMaxSelCount(hwnd, wParam, lParam);
1641
1642 case MCM_SETMAXSELCOUNT:
1643 return MONTHCAL_SetMaxSelCount(hwnd, wParam, lParam);
1644
1645 case MCM_GETSELRANGE:
1646 return MONTHCAL_GetSelRange(hwnd, wParam, lParam);
1647
1648 case MCM_SETSELRANGE:
1649 return MONTHCAL_SetSelRange(hwnd, wParam, lParam);
1650
1651 case MCM_GETMONTHRANGE:
1652 return MONTHCAL_GetMonthRange(hwnd, wParam, lParam);
1653
1654 case MCM_SETDAYSTATE:
1655 return MONTHCAL_SetDayState(hwnd, wParam, lParam);
1656
1657 case MCM_GETMINREQRECT:
1658 return MONTHCAL_GetMinReqRect(hwnd, wParam, lParam);
1659
1660 case MCM_GETCOLOR:
1661 return MONTHCAL_GetColor(hwnd, wParam, lParam);
1662
1663 case MCM_SETCOLOR:
1664 return MONTHCAL_SetColor(hwnd, wParam, lParam);
1665
1666 case MCM_GETTODAY:
1667 return MONTHCAL_GetToday(hwnd, wParam, lParam);
1668
1669 case MCM_SETTODAY:
1670 return MONTHCAL_SetToday(hwnd, wParam, lParam);
1671
1672 case MCM_HITTEST:
1673 return MONTHCAL_HitTest(hwnd,lParam);
1674
1675 case MCM_GETFIRSTDAYOFWEEK:
1676 return MONTHCAL_GetFirstDayOfWeek(hwnd, wParam, lParam);
1677
1678 case MCM_SETFIRSTDAYOFWEEK:
1679 return MONTHCAL_SetFirstDayOfWeek(hwnd, wParam, lParam);
1680
1681 case MCM_GETRANGE:
1682 return MONTHCAL_GetRange(hwnd, wParam, lParam);
1683
1684 case MCM_SETRANGE:
1685 return MONTHCAL_SetRange(hwnd, wParam, lParam);
1686
1687 case MCM_GETMONTHDELTA:
1688 return MONTHCAL_GetMonthDelta(hwnd, wParam, lParam);
1689
1690 case MCM_SETMONTHDELTA:
1691 return MONTHCAL_SetMonthDelta(hwnd, wParam, lParam);
1692
1693 case MCM_GETMAXTODAYWIDTH:
1694 return MONTHCAL_GetMaxTodayWidth(hwnd);
1695
1696 case WM_GETDLGCODE:
1697 return DLGC_WANTARROWS | DLGC_WANTCHARS;
1698
1699 case WM_KILLFOCUS:
1700 return MONTHCAL_KillFocus(hwnd, wParam, lParam);
1701
1702 case WM_LBUTTONDOWN:
1703 return MONTHCAL_LButtonDown(hwnd, wParam, lParam);
1704
1705 case WM_MOUSEMOVE:
1706 return MONTHCAL_MouseMove(hwnd, wParam, lParam);
1707
1708 case WM_LBUTTONUP:
1709 return MONTHCAL_LButtonUp(hwnd, wParam, lParam);
1710
1711 case WM_PAINT:
1712 return MONTHCAL_Paint(hwnd, wParam);
1713
1714 case WM_SETFOCUS:
1715 return MONTHCAL_SetFocus(hwnd, wParam, lParam);
1716
1717 case WM_SIZE:
1718 return MONTHCAL_Size(hwnd, (int)SLOWORD(lParam), (int)SHIWORD(lParam));
1719
1720 case WM_CREATE:
1721 return MONTHCAL_Create(hwnd, wParam, lParam);
1722
1723 case WM_TIMER:
1724 return MONTHCAL_Timer(hwnd, wParam, lParam);
1725
1726 case WM_DESTROY:
1727 return MONTHCAL_Destroy(hwnd, wParam, lParam);
1728
1729 default:
1730 //if(uMsg >= WM_USER)
1731 // ERR( "unknown msg %04x wp=%08x lp=%08lx\n", uMsg, wParam, lParam);
1732 return DefWindowProcA(hwnd, uMsg, wParam, lParam);
1733 }
1734 return 0;
1735}
1736
1737
1738void
1739MONTHCAL_Register(void)
1740{
1741 WNDCLASSA wndClass;
1742
1743//SvL: Don't check this now
1744// if(GlobalFindAtomA(MONTHCAL_CLASSA)) return;
1745
1746 ZeroMemory(&wndClass, sizeof(WNDCLASSA));
1747 wndClass.style = CS_GLOBALCLASS;
1748 wndClass.lpfnWndProc = (WNDPROC)MONTHCAL_WindowProc;
1749 wndClass.cbClsExtra = 0;
1750 wndClass.cbWndExtra = sizeof(MONTHCAL_INFO *);
1751 wndClass.hCursor = LoadCursorA(0, IDC_ARROWA);
1752 wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
1753 wndClass.lpszClassName = MONTHCAL_CLASSA;
1754
1755 RegisterClassA(&wndClass);
1756}
1757
1758
1759void
1760MONTHCAL_Unregister(void)
1761{
1762 if(GlobalFindAtomA(MONTHCAL_CLASSA))
1763 UnregisterClassA(MONTHCAL_CLASSA, (HINSTANCE)NULL);
1764}
Note: See TracBrowser for help on using the repository browser.