ReactOS 0.4.17-dev-116-ga4b6fe9
monthcal.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Timedate Control Panel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/cpl/timedate/monthcal.c
5 * PURPOSE: Calander implementation
6 * COPYRIGHT: Copyright 2006 Thomas Weidenmueller <w3seek@reactos.com>
7 *
8 */
9
10#include "timedate.h"
11
12#include <windowsx.h>
13
14static const WCHAR szMonthCalWndClass[] = L"MonthCalWnd";
15
16#define MONTHCAL_HEADERBG COLOR_INACTIVECAPTION
17#define MONTHCAL_HEADERFG COLOR_INACTIVECAPTIONTEXT
18#define MONTHCAL_CTRLBG COLOR_WINDOW
19#define MONTHCAL_CTRLFG COLOR_WINDOWTEXT
20#define MONTHCAL_SELBG COLOR_ACTIVECAPTION
21#define MONTHCAL_SELFG COLOR_CAPTIONTEXT
22#define MONTHCAL_DISABLED_HEADERBG COLOR_INACTIVECAPTION
23#define MONTHCAL_DISABLED_HEADERFG COLOR_INACTIVECAPTIONTEXT
24#define MONTHCAL_DISABLED_CTRLBG COLOR_WINDOW
25#define MONTHCAL_DISABLED_CTRLFG COLOR_WINDOWTEXT
26#define MONTHCAL_DISABLED_SELBG COLOR_INACTIVECAPTION
27#define MONTHCAL_DISABLED_SELFG COLOR_INACTIVECAPTIONTEXT
28
29#define ID_DAYTIMER 1
30
31typedef struct _MONTHCALWND
32{
39 BYTE Days[6][7];
43
44 HFONT hFont;
45 HBRUSH hbHeader;
47
54
55static LRESULT
57 IN UINT code,
59{
60 LRESULT Ret = 0;
61
62 if (infoPtr->hNotify != NULL)
63 {
64 LPNMHDR pnmh = (LPNMHDR)data;
65
66 pnmh->hwndFrom = infoPtr->hSelf;
67 pnmh->idFrom = GetWindowLongPtrW(infoPtr->hSelf,
68 GWLP_ID);
69 pnmh->code = code;
70
71 Ret = SendMessageW(infoPtr->hNotify,
73 (WPARAM)pnmh->idFrom,
74 (LPARAM)pnmh);
75 }
76
77 return Ret;
78}
79
80/*
81 * For the year range 1..9999
82 * return 1 if is leap year otherwise 0
83 */
84static WORD LeapYear(IN WORD Year)
85{
86 return
87#ifdef WITH_1752
88 (Year <= 1752) ? !(Year % 4) :
89#endif
90 !(Year % 4) && ((Year % 100) || !(Year % 400));
91}
92
93static WORD
95 IN WORD Year)
96{
97 const BYTE MonthDays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0};
98
99 if(Month == 2)
100 return MonthDays[Month - 1] + LeapYear(Year);
101 else
102 {
103#ifdef WITH_1752
104 if ((Year == 1752) && (Month == 9))
105 return 19; // Special case: September 1752 has no 3rd-13th
106 else
107#endif
108 return MonthDays[Month - 1];
109 }
110}
111
112static WORD
114 IN WORD DayOfWeek)
115{
116 return (Day - DayOfWeek + 5) / 7;
117}
118
119static WORD
121 IN WORD Day,
122 IN WORD Month,
123 IN WORD Year)
124{
125 const BYTE DayOfWeek[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
126 WORD Ret;
127
128 Year -= (Month < 3);
129 Ret = (Year + (Year / 4) - (Year / 100) + (Year / 400) + DayOfWeek[Month - 1] + Day + 6) % 7;
130
131 return (7 + Ret - infoPtr->FirstDayOfWeek) % 7;
132}
133
134static WORD
136{
137 WCHAR szBuf[2] = {0};
138 WORD Ret = 0;
139
142 szBuf,
143 sizeof(szBuf) / sizeof(szBuf[0])) != 0)
144 {
145 Ret = (WORD)(szBuf[0] - TEXT('0'));
146 }
147
148 return Ret;
149}
150
151static BOOL
153 IN WORD Month,
154 IN WORD Year)
155{
156 if (Month < 1 || Month > 12 ||
157 Day == 0 || Day > MonthCalMonthLength(Month,
158 Year) ||
159 Year < 1899 || Year > 9999)
160 {
161 return FALSE;
162 }
163
164 return TRUE;
165}
166
167static VOID
169{
170 PBYTE pDay, pDayEnd;
171 WORD DayOfWeek, MonthLength, d = 0;
172 SIZE NewCellSize;
173 BOOL RepaintHeader = FALSE;
174
175 NewCellSize.cx = infoPtr->ClientSize.cx / 7;
176 NewCellSize.cy = infoPtr->ClientSize.cy / 7;
177
178 if (infoPtr->CellSize.cx != NewCellSize.cx ||
179 infoPtr->CellSize.cy != NewCellSize.cy)
180 {
181 infoPtr->CellSize = NewCellSize;
182 RepaintHeader = TRUE;
183 }
184
185 /* Update the days layout of the current month */
186 ZeroMemory(infoPtr->Days,
187 sizeof(infoPtr->Days));
188
189 DayOfWeek = MonthCalDayOfWeek(infoPtr,
190 1,
191 infoPtr->Month,
192 infoPtr->Year);
193
194 MonthLength = MonthCalMonthLength(infoPtr->Month,
195 infoPtr->Year);
196
197 pDay = &infoPtr->Days[0][DayOfWeek];
198 pDayEnd = pDay + MonthLength;
199 while (pDay != pDayEnd)
200 {
201 *(pDay++) = (BYTE)++d;
202 }
203
204 /* Repaint the control */
205 if (RepaintHeader)
206 {
207 InvalidateRect(infoPtr->hSelf,
208 NULL,
209 TRUE);
210 }
211 else
212 {
213 RECT rcClient;
214
215 rcClient.left = 0;
216 rcClient.top = infoPtr->CellSize.cy;
217 rcClient.right = infoPtr->ClientSize.cx;
218 rcClient.bottom = infoPtr->ClientSize.cy;
219
220 InvalidateRect(infoPtr->hSelf,
221 &rcClient,
222 TRUE);
223 }
224}
225
226static VOID
228{
229 SYSTEMTIME LocalTime = {0};
230 UINT uElapse;
231
232 /* Update the current date */
233 GetLocalTime(&LocalTime);
234
235 /* Calculate the number of remaining milliseconds until midnight */
236 uElapse = 1000 - (UINT)LocalTime.wMilliseconds;
237 uElapse += (59 - (UINT)LocalTime.wSecond) * 1000;
238 uElapse += (59 - (UINT)LocalTime.wMinute) * 60 * 1000;
239 uElapse += (23 - (UINT)LocalTime.wHour) * 60 * 60 * 1000;
240
241 /* Setup the new timer */
242 if (SetTimer(infoPtr->hSelf,
244 uElapse,
245 NULL) != 0)
246 {
247 infoPtr->DayTimerSet = TRUE;
248 }
249}
250
251static VOID
253{
254 WCHAR szBuf[64];
255 UINT i;
256
257 infoPtr->UIState = (DWORD)SendMessageW(GetAncestor(infoPtr->hSelf,
258 GA_PARENT),
259 WM_QUERYUISTATE,
260 0,
261 0);
262
263 /* Cache the configuration */
264 infoPtr->FirstDayOfWeek = MonthCalFirstDayOfWeek();
265
266 infoPtr->hbHeader = GetSysColorBrush(infoPtr->Enabled ? MONTHCAL_HEADERBG : MONTHCAL_DISABLED_HEADERBG);
267 infoPtr->hbSelection = GetSysColorBrush(infoPtr->Enabled ? MONTHCAL_SELBG : MONTHCAL_DISABLED_SELBG);
268
269 for (i = 0; i < 7; i++)
270 {
273 ((i + infoPtr->FirstDayOfWeek) % 7),
274 szBuf,
275 sizeof(szBuf) / sizeof(szBuf[0])) != 0)
276 {
277 infoPtr->Week[i] = szBuf[0];
278 }
279 }
280
281 /* Update the control */
282 MonthCalUpdate(infoPtr);
283}
284
285static BOOL
287 IN WORD Day,
288 OUT RECT *rcCell)
289{
290 if (Day >= 1 && Day <= MonthCalMonthLength(infoPtr->Month,
291 infoPtr->Year))
292 {
293 WORD DayOfWeek;
294
295 DayOfWeek = MonthCalDayOfWeek(infoPtr,
296 Day,
297 infoPtr->Month,
298 infoPtr->Year);
299
300 rcCell->left = DayOfWeek * infoPtr->CellSize.cx;
301 rcCell->top = (MonthCalWeekInMonth(Day,
302 DayOfWeek) + 1) * infoPtr->CellSize.cy;
303 rcCell->right = rcCell->left + infoPtr->CellSize.cx;
304 rcCell->bottom = rcCell->top + infoPtr->CellSize.cy;
305
306 return TRUE;
307 }
308
309 return FALSE;
310}
311
312static VOID
314{
315 infoPtr->Changed = TRUE;
316
317 /* Kill the day timer */
318 if (infoPtr->DayTimerSet)
319 {
320 KillTimer(infoPtr->hSelf,
322 infoPtr->DayTimerSet = FALSE;
323 }
324}
325
326
327static BOOL
329 IN WORD Day,
330 IN WORD Month,
331 IN WORD Year)
332{
334 BOOL Ret = FALSE;
335
336 sc.OldDay = infoPtr->Day;
337 sc.OldMonth = infoPtr->Month;
338 sc.OldYear = infoPtr->Year;
339 sc.NewDay = Day;
340 sc.NewMonth = Month;
341 sc.NewYear = Year;
342
343 /* Notify the parent */
344 if (!MonthCalNotifyControlParent(infoPtr,
346 &sc))
347 {
348 /* Check if we actually need to update */
349 if (infoPtr->Month != sc.NewMonth ||
350 infoPtr->Year != sc.NewYear)
351 {
352 infoPtr->Day = sc.NewDay;
353 infoPtr->Month = sc.NewMonth;
354 infoPtr->Year = sc.NewYear;
355
356 MonthCalChange(infoPtr);
357
358 /* Repaint the entire control */
359 MonthCalUpdate(infoPtr);
360
361 Ret = TRUE;
362 }
363 else if (infoPtr->Day != sc.NewDay)
364 {
365 RECT rcUpdate;
366
367 infoPtr->Day = sc.NewDay;
368
369 MonthCalChange(infoPtr);
370
371 if (MonthCalGetDayRect(infoPtr,
372 sc.OldDay,
373 &rcUpdate))
374 {
375 /* Repaint the day cells that need to be updated */
376 InvalidateRect(infoPtr->hSelf,
377 &rcUpdate,
378 TRUE);
379 if (MonthCalGetDayRect(infoPtr,
380 sc.NewDay,
381 &rcUpdate))
382 {
383 InvalidateRect(infoPtr->hSelf,
384 &rcUpdate,
385 TRUE);
386 }
387 }
388
389 Ret = TRUE;
390 }
391 }
392
393 return Ret;
394}
395
396static VOID
399{
401 SYSTEMTIME LocalTime = {0};
402
403 GetLocalTime(&LocalTime);
404
405 au.SystemTime = LocalTime;
406 if (!MonthCalNotifyControlParent(infoPtr,
408 &au))
409 {
410 if (MonthCalSetDate(infoPtr,
411 LocalTime.wDay,
412 LocalTime.wMonth,
413 LocalTime.wYear))
414 {
415 infoPtr->Changed = FALSE;
416 }
417 }
418
419 /* Kill the day timer */
420 if (infoPtr->DayTimerSet)
421 {
422 KillTimer(infoPtr->hSelf,
424 infoPtr->DayTimerSet = FALSE;
425 }
426
427 /* Setup the new day timer */
428 MonthCalSetupDayTimer(infoPtr);
429
430 if (Time != NULL)
431 {
432 *Time = LocalTime;
433 }
434}
435
436static VOID
438 IN WORD Day)
439{
440 RECT rcCell;
441
442 if (MonthCalGetDayRect(infoPtr,
443 Day,
444 &rcCell))
445 {
446 InvalidateRect(infoPtr->hSelf,
447 &rcCell,
448 TRUE);
449 }
450}
451
452static VOID
454 IN HDC hDC,
455 IN LPRECT prcUpdate)
456{
457 LONG x, y;
458 RECT rcCell;
459 COLORREF crOldText, crOldCtrlText = CLR_INVALID;
460 HFONT hOldFont;
461 INT iOldBkMode;
462
463#if MONTHCAL_CTRLBG != MONTHCAL_DISABLED_CTRLBG
464 if (!infoPtr->Enabled)
465 {
467 prcUpdate,
469 }
470#endif
471
472 iOldBkMode = SetBkMode(hDC,
474 hOldFont = (HFONT)SelectObject(hDC,
475 infoPtr->hFont);
476
477 for (y = prcUpdate->top / infoPtr->CellSize.cy;
478 y <= prcUpdate->bottom / infoPtr->CellSize.cy && y < 7;
479 y++)
480 {
481 rcCell.top = y * infoPtr->CellSize.cy;
482 rcCell.bottom = rcCell.top + infoPtr->CellSize.cy;
483
484 if (y == 0)
485 {
486 RECT rcHeader;
487
488 /* Paint the header */
489 rcHeader.left = prcUpdate->left;
490 rcHeader.top = rcCell.top;
491 rcHeader.right = prcUpdate->right;
492 rcHeader.bottom = rcCell.bottom;
493
495 &rcHeader,
496 infoPtr->hbHeader);
497
498 crOldText = SetTextColor(hDC,
500
501 for (x = prcUpdate->left / infoPtr->CellSize.cx;
502 x <= prcUpdate->right / infoPtr->CellSize.cx && x < 7;
503 x++)
504 {
505 rcCell.left = x * infoPtr->CellSize.cx;
506 rcCell.right = rcCell.left + infoPtr->CellSize.cx;
507
508 /* Write the first letter of each weekday */
510 &infoPtr->Week[x],
511 1,
512 &rcCell,
514 }
515
517 crOldText);
518 }
519 else
520 {
521 if (crOldCtrlText == CLR_INVALID)
522 {
523 crOldCtrlText = SetTextColor(hDC,
525 }
526
527 for (x = prcUpdate->left / infoPtr->CellSize.cx;
528 x <= prcUpdate->right / infoPtr->CellSize.cx && x < 7;
529 x++)
530 {
531 UINT Day = infoPtr->Days[y - 1][x];
532
533 rcCell.left = x * infoPtr->CellSize.cx;
534 rcCell.right = rcCell.left + infoPtr->CellSize.cx;
535
536 /* Write the day number */
537 if (Day != 0 && Day < 100)
538 {
539 WCHAR szDay[3];
540 INT szDayLen;
541 RECT rcText;
542 SIZE TextSize;
543
544 szDayLen = _swprintf(szDay, L"%lu", Day);
545
547 szDay,
548 szDayLen,
549 &TextSize))
550 {
551 RECT rcHighlight = { 0, 0, 0, 0 };
552
553 rcText.left = rcCell.left + (infoPtr->CellSize.cx / 2) - (TextSize.cx / 2);
554 rcText.top = rcCell.top + (infoPtr->CellSize.cy / 2) - (TextSize.cy / 2);
555 rcText.right = rcText.left + TextSize.cx;
556 rcText.bottom = rcText.top + TextSize.cy;
557
558 if (Day == infoPtr->Day)
559 {
560 SIZE TextSel;
561
562 TextSel.cx = (infoPtr->CellSize.cx * 2) / 3;
563 TextSel.cy = (infoPtr->CellSize.cy * 3) / 4;
564
565 if (TextSel.cx < rcText.right - rcText.left)
566 TextSel.cx = rcText.right - rcText.left;
567 if (TextSel.cy < rcText.bottom - rcText.top)
568 TextSel.cy = rcText.bottom - rcText.top;
569
570 rcHighlight.left = rcCell.left + (infoPtr->CellSize.cx / 2) - (TextSel.cx / 2);
571 rcHighlight.right = rcHighlight.left + TextSel.cx;
572 rcHighlight.top = rcCell.top + (infoPtr->CellSize.cy / 2) - (TextSel.cy / 2);
573 rcHighlight.bottom = rcHighlight.top + TextSel.cy;
574
575 InflateRect(&rcHighlight,
576 GetSystemMetrics(SM_CXFOCUSBORDER),
577 GetSystemMetrics(SM_CYFOCUSBORDER));
578
579 if (!FillRect(hDC,
580 &rcHighlight,
581 infoPtr->hbSelection))
582 {
583 goto FailNoHighlight;
584 }
585
586 /* Highlight the selected day */
587 crOldText = SetTextColor(hDC,
589 }
590 else
591 {
592FailNoHighlight:
593 /* Don't change the text color, we're not highlighting it... */
594 crOldText = CLR_INVALID;
595 }
596
598 rcText.left,
599 rcText.top,
600 szDay,
601 szDayLen);
602
603 if (Day == infoPtr->Day && crOldText != CLR_INVALID)
604 {
605 if (infoPtr->HasFocus && infoPtr->Enabled && !(infoPtr->UIState & UISF_HIDEFOCUS))
606 {
607 COLORREF crOldBk;
608
609 crOldBk = SetBkColor(hDC,
611
613 &rcHighlight);
614
616 crOldBk);
617 }
618
620 crOldText);
621 }
622 }
623 }
624 }
625 }
626 }
627
628 if (crOldCtrlText != CLR_INVALID)
629 {
631 crOldCtrlText);
632 }
633
635 iOldBkMode);
637 (HGDIOBJ)hOldFont);
638}
639
640static HFONT
642 IN HFONT hFont,
643 IN BOOL Redraw)
644{
645 HFONT hOldFont = infoPtr->hFont;
646 infoPtr->hFont = hFont;
647
648 if (Redraw)
649 {
650 InvalidateRect(infoPtr->hSelf,
651 NULL,
652 TRUE);
653 }
654
655 return hOldFont;
656}
657
658static WORD
660 IN INT x,
661 IN INT y)
662{
663 WORD Ret = 0;
664
665 if (infoPtr->CellSize.cx != 0 && infoPtr->CellSize.cy != 0 &&
666 x >= 0 && y >= 0)
667 {
668 x /= infoPtr->CellSize.cx;
669 y /= infoPtr->CellSize.cy;
670
671 if (x < 7 && y != 0 && y < 7)
672 {
673 Ret = (WORD)infoPtr->Days[y - 1][x];
674 }
675 }
676
677 return Ret;
678}
679
680static LRESULT CALLBACK
682 IN UINT uMsg,
685{
686 PMONTHCALWND infoPtr;
687 LRESULT Ret = 0;
688
690 0);
691
692 if (infoPtr == NULL && uMsg != WM_CREATE)
693 {
694 goto HandleDefaultMessage;
695 }
696
697 switch (uMsg)
698 {
699#if MONTHCAL_CTRLBG != MONTHCAL_DISABLED_CTRLBG
700 case WM_ERASEBKGND:
701 Ret = !infoPtr->Enabled;
702 break;
703#endif
704
705 case WM_PAINT:
706 case WM_PRINTCLIENT:
707 {
708 if (infoPtr->CellSize.cx != 0 && infoPtr->CellSize.cy != 0)
709 {
710 PAINTSTRUCT ps;
711 HDC hDC;
712
713 if (wParam != 0)
714 {
715 if (!GetUpdateRect(hwnd,
716 &ps.rcPaint,
717 TRUE))
718 {
719 break;
720 }
721 hDC = (HDC)wParam;
722 }
723 else
724 {
726 &ps);
727 if (hDC == NULL)
728 {
729 break;
730 }
731 }
732
733 MonthCalPaint(infoPtr,
734 hDC,
735 &ps.rcPaint);
736
737 if (wParam == 0)
738 {
740 &ps);
741 }
742 }
743 break;
744 }
745
746 case WM_LBUTTONDBLCLK:
747 case WM_LBUTTONDOWN:
748 {
749 WORD SelDay;
750
751 SelDay = MonthCalPtToDay(infoPtr,
754 if (SelDay != 0 && SelDay != infoPtr->Day)
755 {
756 MonthCalSetDate(infoPtr,
757 SelDay,
758 infoPtr->Month,
759 infoPtr->Year);
760 }
761
762 /* Fall through */
763 }
764
765 case WM_MBUTTONDOWN:
766 case WM_RBUTTONDOWN:
767 {
768 if (!infoPtr->HasFocus)
769 {
770 SetFocus(hwnd);
771 }
772 break;
773 }
774
775 case WM_KEYDOWN:
776 {
777 WORD NewDay = 0;
778
779 switch (wParam)
780 {
781 case VK_UP:
782 {
783 if (infoPtr->Day > 7)
784 {
785 NewDay = infoPtr->Day - 7;
786 }
787 break;
788 }
789
790 case VK_DOWN:
791 {
792 if (infoPtr->Day + 7 <= MonthCalMonthLength(infoPtr->Month,
793 infoPtr->Year))
794 {
795 NewDay = infoPtr->Day + 7;
796 }
797 break;
798 }
799
800 case VK_LEFT:
801 {
802 if (infoPtr->Day > 1)
803 {
804 NewDay = infoPtr->Day - 1;
805 }
806 break;
807 }
808
809 case VK_RIGHT:
810 {
811 if (infoPtr->Day < MonthCalMonthLength(infoPtr->Month,
812 infoPtr->Year))
813 {
814 NewDay = infoPtr->Day + 1;
815 }
816 break;
817 }
818 }
819
820 /* Update the selection */
821 if (NewDay != 0)
822 {
823 MonthCalSetDate(infoPtr,
824 NewDay,
825 infoPtr->Month,
826 infoPtr->Year);
827 }
828
829 goto HandleDefaultMessage;
830 }
831
832 case WM_GETDLGCODE:
833 {
834 INT virtKey;
835
836 virtKey = (lParam != 0 ? (INT)((LPMSG)lParam)->wParam : 0);
837 switch (virtKey)
838 {
839 case VK_TAB:
840 {
841 /* Change the UI status */
843 GA_PARENT),
844 WM_CHANGEUISTATE,
845 MAKEWPARAM(UIS_INITIALIZE,
846 0),
847 0);
848 break;
849 }
850 }
851
852 Ret |= DLGC_WANTARROWS;
853 break;
854 }
855
856 case WM_SETFOCUS:
857 {
858 infoPtr->HasFocus = TRUE;
859 MonthCalRepaintDay(infoPtr,
860 infoPtr->Day);
861 break;
862 }
863
864 case WM_KILLFOCUS:
865 {
866 infoPtr->HasFocus = FALSE;
867 MonthCalRepaintDay(infoPtr,
868 infoPtr->Day);
869 break;
870 }
871
872 case WM_UPDATEUISTATE:
873 {
874 DWORD OldUIState;
875
876 Ret = DefWindowProcW(hwnd,
877 uMsg,
878 wParam,
879 lParam);
880
881 OldUIState = infoPtr->UIState;
882 switch (LOWORD(wParam))
883 {
884 case UIS_SET:
885 infoPtr->UIState |= HIWORD(wParam);
886 break;
887
888 case UIS_CLEAR:
889 infoPtr->UIState &= ~HIWORD(wParam);
890 break;
891 }
892
893 if (infoPtr->UIState != OldUIState)
894 {
895 MonthCalRepaintDay(infoPtr,
896 infoPtr->Day);
897 }
898 break;
899 }
900
901 case MCCM_SETDATE:
902 {
903 WORD Day, Month, Year, DaysCount;
904
905 Day = LOWORD(wParam);
906 Month = HIWORD(wParam);
907 Year = LOWORD(lParam);
908
909 if (Day == (WORD)-1)
910 Day = infoPtr->Day;
911 if (Month == (WORD)-1)
912 Month = infoPtr->Month;
913 if (Year == (WORD)-1)
914 Year = infoPtr->Year;
915
916 DaysCount = MonthCalMonthLength(Month,
917 Year);
918 if (Day > DaysCount)
919 Day = DaysCount;
920
921 if (MonthCalValidDate(Day,
922 Month,
923 Year))
924 {
925 if (Day != infoPtr->Day ||
926 Month != infoPtr->Month ||
927 Year != infoPtr->Year)
928 {
929 Ret = MonthCalSetDate(infoPtr,
930 Day,
931 Month,
932 Year);
933 }
934 }
935 break;
936 }
937
938 case MCCM_GETDATE:
939 {
940 LPSYSTEMTIME lpSystemTime = (LPSYSTEMTIME)wParam;
941
942 lpSystemTime->wYear = infoPtr->Year;
943 lpSystemTime->wMonth = infoPtr->Month;
944 lpSystemTime->wDay = infoPtr->Day;
945
946 Ret = TRUE;
947 break;
948 }
949
950 case MCCM_RESET:
951 {
952 MonthCalSetLocalTime(infoPtr,
953 NULL);
954 Ret = TRUE;
955 break;
956 }
957
958 case MCCM_CHANGED:
959 {
960 Ret = infoPtr->Changed;
961 break;
962 }
963
964 case WM_TIMER:
965 {
966 switch (wParam)
967 {
968 case ID_DAYTIMER:
969 {
970 /* Kill the timer */
973 infoPtr->DayTimerSet = FALSE;
974
975 if (!infoPtr->Changed)
976 {
977 /* Update the system time and setup the new day timer */
978 MonthCalSetLocalTime(infoPtr,
979 NULL);
980
981 /* Update the control */
982 MonthCalUpdate(infoPtr);
983 }
984 break;
985 }
986 }
987 break;
988 }
989
990 case WM_SETFONT:
991 {
992 Ret = (LRESULT)MonthCalChangeFont(infoPtr,
993 (HFONT)wParam,
994 (BOOL)LOWORD(lParam));
995 break;
996 }
997
998 case WM_SIZE:
999 {
1000 infoPtr->ClientSize.cx = LOWORD(lParam);
1001 infoPtr->ClientSize.cy = HIWORD(lParam);
1002 infoPtr->CellSize.cx = infoPtr->ClientSize.cx / 7;
1003 infoPtr->CellSize.cy = infoPtr->ClientSize.cy / 7;
1004
1005 /* Repaint the control */
1007 NULL,
1008 TRUE);
1009 break;
1010 }
1011
1012 case WM_GETFONT:
1013 {
1014 Ret = (LRESULT)infoPtr->hFont;
1015 break;
1016 }
1017
1018 case WM_ENABLE:
1019 {
1020 infoPtr->Enabled = ((BOOL)wParam != FALSE);
1021 MonthCalReload(infoPtr);
1022 break;
1023 }
1024
1025 case WM_STYLECHANGED:
1026 {
1027 if (wParam == GWL_STYLE)
1028 {
1029 unsigned int OldEnabled = infoPtr->Enabled;
1030 infoPtr->Enabled = !(((LPSTYLESTRUCT)lParam)->styleNew & WS_DISABLED);
1031
1032 if (OldEnabled != infoPtr->Enabled)
1033 {
1034 MonthCalReload(infoPtr);
1035 }
1036 }
1037 break;
1038 }
1039
1040 case WM_CREATE:
1041 {
1042 infoPtr = (MONTHCALWND*) HeapAlloc(GetProcessHeap(),
1043 0,
1044 sizeof(MONTHCALWND));
1045 if (infoPtr == NULL)
1046 {
1047 Ret = (LRESULT)-1;
1048 break;
1049 }
1050
1052 0,
1053 (LONG_PTR)infoPtr);
1054
1055 ZeroMemory(infoPtr,
1056 sizeof(MONTHCALWND));
1057
1058 infoPtr->hSelf = hwnd;
1059 infoPtr->hNotify = ((LPCREATESTRUCTW)lParam)->hwndParent;
1060 infoPtr->Enabled = !(((LPCREATESTRUCTW)lParam)->style & WS_DISABLED);
1061
1062 MonthCalSetLocalTime(infoPtr,
1063 NULL);
1064
1065 MonthCalReload(infoPtr);
1066 break;
1067 }
1068
1069 case WM_DESTROY:
1070 {
1072 0,
1073 infoPtr);
1075 0,
1076 (DWORD_PTR)NULL);
1077 break;
1078 }
1079
1080 default:
1081 {
1082HandleDefaultMessage:
1083 Ret = DefWindowProcW(hwnd,
1084 uMsg,
1085 wParam,
1086 lParam);
1087 break;
1088 }
1089 }
1090
1091 return Ret;
1092}
1093
1094BOOL
1096{
1097 WNDCLASSW wc = {0};
1098
1099 wc.style = CS_DBLCLKS;
1101 wc.cbWndExtra = sizeof(PMONTHCALWND);
1102 wc.hInstance = hInstance;
1104 (LPWSTR)IDC_ARROW);
1105 wc.hbrBackground = (HBRUSH)(MONTHCAL_CTRLBG + 1);
1107
1108 return RegisterClassW(&wc) != 0;
1109}
1110
1111VOID
1113{
1115 hInstance);
1116}
static HDC hDC
Definition: 3dtext.c:33
HFONT hFont
Definition: main.c:53
HINSTANCE hInstance
Definition: charmap.c:19
WPARAM wParam
Definition: combotst.c:138
LPARAM lParam
Definition: combotst.c:139
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static WORD MonthCalDayOfWeek(IN PMONTHCALWND infoPtr, IN WORD Day, IN WORD Month, IN WORD Year)
Definition: monthcal.c:120
static VOID MonthCalUpdate(IN PMONTHCALWND infoPtr)
Definition: monthcal.c:168
#define MONTHCAL_DISABLED_HEADERFG
Definition: monthcal.c:23
static WORD MonthCalPtToDay(IN PMONTHCALWND infoPtr, IN INT x, IN INT y)
Definition: monthcal.c:659
BOOL RegisterMonthCalControl(IN HINSTANCE hInstance)
Definition: monthcal.c:1095
#define MONTHCAL_SELFG
Definition: monthcal.c:21
#define MONTHCAL_DISABLED_HEADERBG
Definition: monthcal.c:22
static BOOL MonthCalValidDate(IN WORD Day, IN WORD Month, IN WORD Year)
Definition: monthcal.c:152
static VOID MonthCalChange(IN PMONTHCALWND infoPtr)
Definition: monthcal.c:313
static WORD MonthCalWeekInMonth(IN WORD Day, IN WORD DayOfWeek)
Definition: monthcal.c:113
struct _MONTHCALWND * PMONTHCALWND
#define MONTHCAL_CTRLFG
Definition: monthcal.c:19
#define MONTHCAL_SELBG
Definition: monthcal.c:20
#define MONTHCAL_CTRLBG
Definition: monthcal.c:18
#define MONTHCAL_DISABLED_SELFG
Definition: monthcal.c:27
static VOID MonthCalSetLocalTime(IN PMONTHCALWND infoPtr, OUT SYSTEMTIME *Time)
Definition: monthcal.c:397
static VOID MonthCalRepaintDay(IN PMONTHCALWND infoPtr, IN WORD Day)
Definition: monthcal.c:437
static WORD LeapYear(IN WORD Year)
Definition: monthcal.c:84
static LRESULT CALLBACK MonthCalWndProc(IN HWND hwnd, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam)
Definition: monthcal.c:681
#define MONTHCAL_DISABLED_CTRLFG
Definition: monthcal.c:25
struct _MONTHCALWND MONTHCALWND
static VOID MonthCalReload(IN PMONTHCALWND infoPtr)
Definition: monthcal.c:252
static WORD MonthCalFirstDayOfWeek(VOID)
Definition: monthcal.c:135
static const WCHAR szMonthCalWndClass[]
Definition: monthcal.c:14
static BOOL MonthCalGetDayRect(IN PMONTHCALWND infoPtr, IN WORD Day, OUT RECT *rcCell)
Definition: monthcal.c:286
VOID UnregisterMonthCalControl(IN HINSTANCE hInstance)
Definition: monthcal.c:1112
#define MONTHCAL_HEADERFG
Definition: monthcal.c:17
static BOOL MonthCalSetDate(IN PMONTHCALWND infoPtr, IN WORD Day, IN WORD Month, IN WORD Year)
Definition: monthcal.c:328
#define MONTHCAL_HEADERBG
Definition: monthcal.c:16
#define MONTHCAL_DISABLED_SELBG
Definition: monthcal.c:26
static HFONT MonthCalChangeFont(IN PMONTHCALWND infoPtr, IN HFONT hFont, IN BOOL Redraw)
Definition: monthcal.c:641
static WORD MonthCalMonthLength(IN WORD Month, IN WORD Year)
Definition: monthcal.c:94
#define MONTHCAL_DISABLED_CTRLBG
Definition: monthcal.c:24
static VOID MonthCalPaint(IN PMONTHCALWND infoPtr, IN HDC hDC, IN LPRECT prcUpdate)
Definition: monthcal.c:453
static LRESULT MonthCalNotifyControlParent(IN PMONTHCALWND infoPtr, IN UINT code, IN OUT PVOID data)
Definition: monthcal.c:56
static VOID MonthCalSetupDayTimer(IN PMONTHCALWND infoPtr)
Definition: monthcal.c:227
#define ID_DAYTIMER
Definition: monthcal.c:29
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
#define CALLBACK
Definition: compat.h:35
VOID WINAPI GetLocalTime(OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:272
INT WINAPI GetLocaleInfoW(LCID lcid, LCTYPE lctype, LPWSTR buffer, INT len)
Definition: locale.c:1675
#define L(x)
Definition: resources.c:13
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble right
Definition: glext.h:10859
GLint GLint bottom
Definition: glext.h:7726
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define TEXT(s)
Definition: k32.h:28
#define d
Definition: ke_i.h:81
#define ZeroMemory
Definition: minwinbase.h:31
struct _SYSTEMTIME * LPSYSTEMTIME
Definition: time.c:27
LONG_PTR LPARAM
Definition: minwindef.h:175
LONG_PTR LRESULT
Definition: minwindef.h:176
UINT_PTR WPARAM
Definition: minwindef.h:174
#define _swprintf(buf, format,...)
Definition: sprintf.c:56
static HDC
Definition: imagelist.c:88
static PLARGE_INTEGER Time
Definition: time.c:37
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
unsigned int UINT
Definition: ndis.h:50
#define BOOL
Definition: nt_native.h:43
#define DWORD
Definition: nt_native.h:44
#define LOCALE_USER_DEFAULT
INT WINAPI DrawTextW(HDC hdc, LPCWSTR str, INT count, LPRECT rect, UINT flags)
Definition: defwnd.c:16
#define LRESULT
Definition: ole.h:14
#define LOWORD(l)
Definition: pedump.c:82
BYTE * PBYTE
Definition: pedump.c:66
short WCHAR
Definition: pedump.c:58
long LONG
Definition: pedump.c:60
#define WS_DISABLED
Definition: pedump.c:621
#define INT
Definition: polytest.cpp:20
#define WM_PRINTCLIENT
Definition: richedit.h:70
#define WM_NOTIFY
Definition: richedit.h:61
HFONT hFont
Definition: monthcal.c:44
UINT DayTimerSet
Definition: monthcal.c:50
SIZE CellSize
Definition: monthcal.c:41
WORD Month
Definition: monthcal.c:36
UINT HasFocus
Definition: monthcal.c:52
UINT Changed
Definition: monthcal.c:49
HWND hSelf
Definition: monthcal.c:33
WCHAR Week[7]
Definition: monthcal.c:40
HBRUSH hbSelection
Definition: monthcal.c:46
UINT Enabled
Definition: monthcal.c:51
SIZE ClientSize
Definition: monthcal.c:42
HBRUSH hbHeader
Definition: monthcal.c:45
BYTE Days[6][7]
Definition: monthcal.c:39
WORD Day
Definition: monthcal.c:35
WORD FirstDayOfWeek
Definition: monthcal.c:38
WORD Year
Definition: monthcal.c:37
DWORD UIState
Definition: monthcal.c:48
HWND hNotify
Definition: monthcal.c:34
SYSTEMTIME SystemTime
Definition: timedate.h:101
LONG cx
Definition: kdterminal.h:27
LONG cy
Definition: kdterminal.h:28
WORD wMilliseconds
Definition: minwinbase.h:263
WORD wSecond
Definition: minwinbase.h:262
WORD wMinute
Definition: minwinbase.h:261
LPCWSTR lpszClassName
Definition: winuser.h:3293
HBRUSH hbrBackground
Definition: winuser.h:3291
HINSTANCE hInstance
Definition: winuser.h:3288
UINT style
Definition: winuser.h:3284
WNDPROC lpfnWndProc
Definition: winuser.h:3285
int cbWndExtra
Definition: winuser.h:3287
HCURSOR hCursor
Definition: winuser.h:3290
Definition: inflate.c:139
UINT_PTR idFrom
Definition: winuser.h:3266
UINT code
Definition: winuser.h:3267
HWND hwndFrom
Definition: winuser.h:3265
LONG right
Definition: windef.h:108
LONG bottom
Definition: windef.h:109
LONG top
Definition: windef.h:107
LONG left
Definition: windef.h:106
#define MCCM_GETDATE
Definition: timedate.h:82
#define MCCN_AUTOUPDATE
Definition: timedate.h:97
#define MCCM_SETDATE
Definition: timedate.h:81
#define MCCN_SELCHANGE
Definition: timedate.h:86
#define MCCM_RESET
Definition: timedate.h:83
#define MCCM_CHANGED
Definition: timedate.h:84
uint32_t DWORD_PTR
Definition: typedefs.h:65
uint16_t * LPWSTR
Definition: typedefs.h:56
int32_t INT
Definition: typedefs.h:58
#define IN
Definition: typedefs.h:39
#define HIWORD(l)
Definition: typedefs.h:247
#define OUT
Definition: typedefs.h:40
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
DWORD COLORREF
Definition: windef.h:100
#define GET_Y_LPARAM(lp)
Definition: windowsx.h:300
#define GET_X_LPARAM(lp)
Definition: windowsx.h:299
COLORREF WINAPI SetBkColor(_In_ HDC, _In_ COLORREF)
Definition: dc.c:999
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1546
#define TRANSPARENT
Definition: wingdi.h:950
#define CLR_INVALID
Definition: wingdi.h:883
BOOL WINAPI TextOutW(_In_ HDC hdc, _In_ int x, _In_ int y, _In_reads_(c) LPCWSTR lpString, _In_ int c)
int WINAPI FillRect(HDC, LPCRECT, HBRUSH)
int WINAPI SetBkMode(_In_ HDC, _In_ int)
Definition: dc.c:1056
COLORREF WINAPI SetTextColor(_In_ HDC, _In_ COLORREF)
Definition: text.c:917
BOOL WINAPI GetTextExtentPoint32W(_In_ HDC hdc, _In_reads_(c) LPCWSTR lpString, _In_ int c, _Out_ LPSIZE psizl)
#define LOCALE_SABBREVDAYNAME1
Definition: winnls.h:91
#define LOCALE_IFIRSTDAYOFWEEK
Definition: winnls.h:82
#define WM_PAINT
Definition: winuser.h:1648
#define WM_ERASEBKGND
Definition: winuser.h:1653
DWORD WINAPI GetSysColor(_In_ int)
#define MAKEWPARAM(l, h)
Definition: winuser.h:4117
#define DT_NOPREFIX
Definition: winuser.h:537
#define GetWindowLongPtrW
Definition: winuser.h:4983
#define VK_TAB
Definition: winuser.h:2235
#define WM_ENABLE
Definition: winuser.h:1643
#define DT_CENTER
Definition: winuser.h:527
LRESULT WINAPI DefWindowProcW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define WM_CREATE
Definition: winuser.h:1636
#define WM_SIZE
Definition: winuser.h:1639
HBRUSH WINAPI GetSysColorBrush(_In_ int)
#define DT_SINGLELINE
Definition: winuser.h:540
#define WM_LBUTTONDBLCLK
Definition: winuser.h:1806
ATOM WINAPI RegisterClassW(_In_ CONST WNDCLASSW *)
#define IDC_ARROW
Definition: winuser.h:695
#define VK_UP
Definition: winuser.h:2261
#define WM_SETFOCUS
Definition: winuser.h:1641
#define GA_PARENT
Definition: winuser.h:2892
#define CS_DBLCLKS
Definition: winuser.h:659
#define WM_LBUTTONDOWN
Definition: winuser.h:1804
HCURSOR WINAPI LoadCursorW(_In_opt_ HINSTANCE, _In_ LPCWSTR)
Definition: cursoricon.c:2474
#define WM_GETFONT
Definition: winuser.h:1679
UINT_PTR WINAPI SetTimer(_In_opt_ HWND, _In_ UINT_PTR, _In_ UINT, _In_opt_ TIMERPROC)
#define WM_RBUTTONDOWN
Definition: winuser.h:1807
struct tagSTYLESTRUCT * LPSTYLESTRUCT
HWND WINAPI SetFocus(_In_opt_ HWND)
#define WM_SETFONT
Definition: winuser.h:1678
#define WM_TIMER
Definition: winuser.h:1770
BOOL WINAPI EndPaint(_In_ HWND, _In_ const PAINTSTRUCT *)
#define DLGC_WANTARROWS
Definition: winuser.h:2652
struct tagNMHDR * LPNMHDR
#define DT_VCENTER
Definition: winuser.h:543
#define VK_LEFT
Definition: winuser.h:2260
#define VK_RIGHT
Definition: winuser.h:2262
#define VK_DOWN
Definition: winuser.h:2263
#define GWLP_ID
Definition: winuser.h:871
#define WM_DESTROY
Definition: winuser.h:1637
BOOL WINAPI UnregisterClassW(_In_ LPCWSTR, HINSTANCE)
#define WM_KEYDOWN
Definition: winuser.h:1743
BOOL WINAPI DrawFocusRect(_In_ HDC, _In_ LPCRECT)
BOOL WINAPI InvalidateRect(_In_opt_ HWND, _In_opt_ LPCRECT, _In_ BOOL)
HDC WINAPI BeginPaint(_In_ HWND, _Out_ LPPAINTSTRUCT)
BOOL WINAPI KillTimer(_In_opt_ HWND, _In_ UINT_PTR)
#define SetWindowLongPtrW
Definition: winuser.h:5512
BOOL WINAPI InflateRect(_Inout_ LPRECT, _In_ int, _In_ int)
#define GWL_STYLE
Definition: winuser.h:863
BOOL WINAPI GetUpdateRect(_In_ HWND, _Out_opt_ LPRECT, _In_ BOOL)
#define WM_KILLFOCUS
Definition: winuser.h:1642
struct tagCREATESTRUCTW * LPCREATESTRUCTW
int WINAPI GetSystemMetrics(_In_ int)
HWND WINAPI GetAncestor(_In_ HWND, _In_ UINT)
Definition: window.c:929
#define WM_GETDLGCODE
Definition: winuser.h:1717
#define WM_MBUTTONDOWN
Definition: winuser.h:1810
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
unsigned char BYTE
Definition: xxhash.c:193