ReactOS 0.4.15-dev-8235-gcd88a97
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
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,
545 L"%lu",
546 Day);
547
549 szDay,
550 szDayLen,
551 &TextSize))
552 {
553 RECT rcHighlight = { 0, 0, 0, 0 };
554
555 rcText.left = rcCell.left + (infoPtr->CellSize.cx / 2) - (TextSize.cx / 2);
556 rcText.top = rcCell.top + (infoPtr->CellSize.cy / 2) - (TextSize.cy / 2);
557 rcText.right = rcText.left + TextSize.cx;
558 rcText.bottom = rcText.top + TextSize.cy;
559
560 if (Day == infoPtr->Day)
561 {
562 SIZE TextSel;
563
564 TextSel.cx = (infoPtr->CellSize.cx * 2) / 3;
565 TextSel.cy = (infoPtr->CellSize.cy * 3) / 4;
566
567 if (TextSel.cx < rcText.right - rcText.left)
568 TextSel.cx = rcText.right - rcText.left;
569 if (TextSel.cy < rcText.bottom - rcText.top)
570 TextSel.cy = rcText.bottom - rcText.top;
571
572 rcHighlight.left = rcCell.left + (infoPtr->CellSize.cx / 2) - (TextSel.cx / 2);
573 rcHighlight.right = rcHighlight.left + TextSel.cx;
574 rcHighlight.top = rcCell.top + (infoPtr->CellSize.cy / 2) - (TextSel.cy / 2);
575 rcHighlight.bottom = rcHighlight.top + TextSel.cy;
576
577 InflateRect(&rcHighlight,
578 GetSystemMetrics(SM_CXFOCUSBORDER),
579 GetSystemMetrics(SM_CYFOCUSBORDER));
580
581 if (!FillRect(hDC,
582 &rcHighlight,
583 infoPtr->hbSelection))
584 {
585 goto FailNoHighlight;
586 }
587
588 /* Highlight the selected day */
589 crOldText = SetTextColor(hDC,
591 }
592 else
593 {
594FailNoHighlight:
595 /* Don't change the text color, we're not highlighting it... */
596 crOldText = CLR_INVALID;
597 }
598
600 rcText.left,
601 rcText.top,
602 szDay,
603 szDayLen);
604
605 if (Day == infoPtr->Day && crOldText != CLR_INVALID)
606 {
607 if (infoPtr->HasFocus && infoPtr->Enabled && !(infoPtr->UIState & UISF_HIDEFOCUS))
608 {
609 COLORREF crOldBk;
610
611 crOldBk = SetBkColor(hDC,
613
615 &rcHighlight);
616
618 crOldBk);
619 }
620
622 crOldText);
623 }
624 }
625 }
626 }
627 }
628 }
629
630 if (crOldCtrlText != CLR_INVALID)
631 {
633 crOldCtrlText);
634 }
635
637 iOldBkMode);
639 (HGDIOBJ)hOldFont);
640}
641
642static HFONT
644 IN HFONT hFont,
645 IN BOOL Redraw)
646{
647 HFONT hOldFont = infoPtr->hFont;
648 infoPtr->hFont = hFont;
649
650 if (Redraw)
651 {
652 InvalidateRect(infoPtr->hSelf,
653 NULL,
654 TRUE);
655 }
656
657 return hOldFont;
658}
659
660static WORD
662 IN INT x,
663 IN INT y)
664{
665 WORD Ret = 0;
666
667 if (infoPtr->CellSize.cx != 0 && infoPtr->CellSize.cy != 0 &&
668 x >= 0 && y >= 0)
669 {
670 x /= infoPtr->CellSize.cx;
671 y /= infoPtr->CellSize.cy;
672
673 if (x < 7 && y != 0 && y < 7)
674 {
675 Ret = (WORD)infoPtr->Days[y - 1][x];
676 }
677 }
678
679 return Ret;
680}
681
682static LRESULT CALLBACK
684 IN UINT uMsg,
687{
688 PMONTHCALWND infoPtr;
689 LRESULT Ret = 0;
690
692 0);
693
694 if (infoPtr == NULL && uMsg != WM_CREATE)
695 {
696 goto HandleDefaultMessage;
697 }
698
699 switch (uMsg)
700 {
701#if MONTHCAL_CTRLBG != MONTHCAL_DISABLED_CTRLBG
702 case WM_ERASEBKGND:
703 Ret = !infoPtr->Enabled;
704 break;
705#endif
706
707 case WM_PAINT:
708 case WM_PRINTCLIENT:
709 {
710 if (infoPtr->CellSize.cx != 0 && infoPtr->CellSize.cy != 0)
711 {
712 PAINTSTRUCT ps;
713 HDC hDC;
714
715 if (wParam != 0)
716 {
717 if (!GetUpdateRect(hwnd,
718 &ps.rcPaint,
719 TRUE))
720 {
721 break;
722 }
723 hDC = (HDC)wParam;
724 }
725 else
726 {
728 &ps);
729 if (hDC == NULL)
730 {
731 break;
732 }
733 }
734
735 MonthCalPaint(infoPtr,
736 hDC,
737 &ps.rcPaint);
738
739 if (wParam == 0)
740 {
742 &ps);
743 }
744 }
745 break;
746 }
747
748 case WM_LBUTTONDBLCLK:
749 case WM_LBUTTONDOWN:
750 {
751 WORD SelDay;
752
753 SelDay = MonthCalPtToDay(infoPtr,
756 if (SelDay != 0 && SelDay != infoPtr->Day)
757 {
758 MonthCalSetDate(infoPtr,
759 SelDay,
760 infoPtr->Month,
761 infoPtr->Year);
762 }
763
764 /* Fall through */
765 }
766
767 case WM_MBUTTONDOWN:
768 case WM_RBUTTONDOWN:
769 {
770 if (!infoPtr->HasFocus)
771 {
772 SetFocus(hwnd);
773 }
774 break;
775 }
776
777 case WM_KEYDOWN:
778 {
779 WORD NewDay = 0;
780
781 switch (wParam)
782 {
783 case VK_UP:
784 {
785 if (infoPtr->Day > 7)
786 {
787 NewDay = infoPtr->Day - 7;
788 }
789 break;
790 }
791
792 case VK_DOWN:
793 {
794 if (infoPtr->Day + 7 <= MonthCalMonthLength(infoPtr->Month,
795 infoPtr->Year))
796 {
797 NewDay = infoPtr->Day + 7;
798 }
799 break;
800 }
801
802 case VK_LEFT:
803 {
804 if (infoPtr->Day > 1)
805 {
806 NewDay = infoPtr->Day - 1;
807 }
808 break;
809 }
810
811 case VK_RIGHT:
812 {
813 if (infoPtr->Day < MonthCalMonthLength(infoPtr->Month,
814 infoPtr->Year))
815 {
816 NewDay = infoPtr->Day + 1;
817 }
818 break;
819 }
820 }
821
822 /* Update the selection */
823 if (NewDay != 0)
824 {
825 MonthCalSetDate(infoPtr,
826 NewDay,
827 infoPtr->Month,
828 infoPtr->Year);
829 }
830
831 goto HandleDefaultMessage;
832 }
833
834 case WM_GETDLGCODE:
835 {
836 INT virtKey;
837
838 virtKey = (lParam != 0 ? (INT)((LPMSG)lParam)->wParam : 0);
839 switch (virtKey)
840 {
841 case VK_TAB:
842 {
843 /* Change the UI status */
845 GA_PARENT),
846 WM_CHANGEUISTATE,
847 MAKEWPARAM(UIS_INITIALIZE,
848 0),
849 0);
850 break;
851 }
852 }
853
854 Ret |= DLGC_WANTARROWS;
855 break;
856 }
857
858 case WM_SETFOCUS:
859 {
860 infoPtr->HasFocus = TRUE;
861 MonthCalRepaintDay(infoPtr,
862 infoPtr->Day);
863 break;
864 }
865
866 case WM_KILLFOCUS:
867 {
868 infoPtr->HasFocus = FALSE;
869 MonthCalRepaintDay(infoPtr,
870 infoPtr->Day);
871 break;
872 }
873
874 case WM_UPDATEUISTATE:
875 {
876 DWORD OldUIState;
877
878 Ret = DefWindowProcW(hwnd,
879 uMsg,
880 wParam,
881 lParam);
882
883 OldUIState = infoPtr->UIState;
884 switch (LOWORD(wParam))
885 {
886 case UIS_SET:
887 infoPtr->UIState |= HIWORD(wParam);
888 break;
889
890 case UIS_CLEAR:
891 infoPtr->UIState &= ~HIWORD(wParam);
892 break;
893 }
894
895 if (infoPtr->UIState != OldUIState)
896 {
897 MonthCalRepaintDay(infoPtr,
898 infoPtr->Day);
899 }
900 break;
901 }
902
903 case MCCM_SETDATE:
904 {
905 WORD Day, Month, Year, DaysCount;
906
907 Day = LOWORD(wParam);
908 Month = HIWORD(wParam);
909 Year = LOWORD(lParam);
910
911 if (Day == (WORD)-1)
912 Day = infoPtr->Day;
913 if (Month == (WORD)-1)
914 Month = infoPtr->Month;
915 if (Year == (WORD)-1)
916 Year = infoPtr->Year;
917
918 DaysCount = MonthCalMonthLength(Month,
919 Year);
920 if (Day > DaysCount)
921 Day = DaysCount;
922
923 if (MonthCalValidDate(Day,
924 Month,
925 Year))
926 {
927 if (Day != infoPtr->Day ||
928 Month != infoPtr->Month ||
929 Year != infoPtr->Year)
930 {
931 Ret = MonthCalSetDate(infoPtr,
932 Day,
933 Month,
934 Year);
935 }
936 }
937 break;
938 }
939
940 case MCCM_GETDATE:
941 {
942 LPSYSTEMTIME lpSystemTime = (LPSYSTEMTIME)wParam;
943
944 lpSystemTime->wYear = infoPtr->Year;
945 lpSystemTime->wMonth = infoPtr->Month;
946 lpSystemTime->wDay = infoPtr->Day;
947
948 Ret = TRUE;
949 break;
950 }
951
952 case MCCM_RESET:
953 {
954 MonthCalSetLocalTime(infoPtr,
955 NULL);
956 Ret = TRUE;
957 break;
958 }
959
960 case MCCM_CHANGED:
961 {
962 Ret = infoPtr->Changed;
963 break;
964 }
965
966 case WM_TIMER:
967 {
968 switch (wParam)
969 {
970 case ID_DAYTIMER:
971 {
972 /* Kill the timer */
975 infoPtr->DayTimerSet = FALSE;
976
977 if (!infoPtr->Changed)
978 {
979 /* Update the system time and setup the new day timer */
980 MonthCalSetLocalTime(infoPtr,
981 NULL);
982
983 /* Update the control */
984 MonthCalUpdate(infoPtr);
985 }
986 break;
987 }
988 }
989 break;
990 }
991
992 case WM_SETFONT:
993 {
994 Ret = (LRESULT)MonthCalChangeFont(infoPtr,
995 (HFONT)wParam,
996 (BOOL)LOWORD(lParam));
997 break;
998 }
999
1000 case WM_SIZE:
1001 {
1002 infoPtr->ClientSize.cx = LOWORD(lParam);
1003 infoPtr->ClientSize.cy = HIWORD(lParam);
1004 infoPtr->CellSize.cx = infoPtr->ClientSize.cx / 7;
1005 infoPtr->CellSize.cy = infoPtr->ClientSize.cy / 7;
1006
1007 /* Repaint the control */
1009 NULL,
1010 TRUE);
1011 break;
1012 }
1013
1014 case WM_GETFONT:
1015 {
1016 Ret = (LRESULT)infoPtr->hFont;
1017 break;
1018 }
1019
1020 case WM_ENABLE:
1021 {
1022 infoPtr->Enabled = ((BOOL)wParam != FALSE);
1023 MonthCalReload(infoPtr);
1024 break;
1025 }
1026
1027 case WM_STYLECHANGED:
1028 {
1029 if (wParam == GWL_STYLE)
1030 {
1031 unsigned int OldEnabled = infoPtr->Enabled;
1032 infoPtr->Enabled = !(((LPSTYLESTRUCT)lParam)->styleNew & WS_DISABLED);
1033
1034 if (OldEnabled != infoPtr->Enabled)
1035 {
1036 MonthCalReload(infoPtr);
1037 }
1038 }
1039 break;
1040 }
1041
1042 case WM_CREATE:
1043 {
1044 infoPtr = (MONTHCALWND*) HeapAlloc(GetProcessHeap(),
1045 0,
1046 sizeof(MONTHCALWND));
1047 if (infoPtr == NULL)
1048 {
1049 Ret = (LRESULT)-1;
1050 break;
1051 }
1052
1054 0,
1055 (LONG_PTR)infoPtr);
1056
1057 ZeroMemory(infoPtr,
1058 sizeof(MONTHCALWND));
1059
1060 infoPtr->hSelf = hwnd;
1061 infoPtr->hNotify = ((LPCREATESTRUCTW)lParam)->hwndParent;
1062 infoPtr->Enabled = !(((LPCREATESTRUCTW)lParam)->style & WS_DISABLED);
1063
1064 MonthCalSetLocalTime(infoPtr,
1065 NULL);
1066
1067 MonthCalReload(infoPtr);
1068 break;
1069 }
1070
1071 case WM_DESTROY:
1072 {
1074 0,
1075 infoPtr);
1077 0,
1078 (DWORD_PTR)NULL);
1079 break;
1080 }
1081
1082 default:
1083 {
1084HandleDefaultMessage:
1085 Ret = DefWindowProcW(hwnd,
1086 uMsg,
1087 wParam,
1088 lParam);
1089 break;
1090 }
1091 }
1092
1093 return Ret;
1094}
1095
1096BOOL
1098{
1099 WNDCLASSW wc = {0};
1100
1101 wc.style = CS_DBLCLKS;
1103 wc.cbWndExtra = sizeof(PMONTHCALWND);
1104 wc.hInstance = hInstance;
1106 (LPWSTR)IDC_ARROW);
1107 wc.hbrBackground = (HBRUSH)(MONTHCAL_CTRLBG + 1);
1109
1110 return RegisterClassW(&wc) != 0;
1111}
1112
1113VOID
1115{
1117 hInstance);
1118}
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:661
BOOL RegisterMonthCalControl(IN HINSTANCE hInstance)
Definition: monthcal.c:1097
#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:683
#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:1114
#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:643
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:286
INT WINAPI GetLocaleInfoW(LCID lcid, LCTYPE lctype, LPWSTR buffer, INT len)
Definition: locale.c:1665
#define swprintf
Definition: precomp.h:40
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
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:26
#define d
Definition: ke_i.h:81
static HDC
Definition: imagelist.c:92
static DWORD *static HFONT(WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDVA *)
static PLARGE_INTEGER Time
Definition: time.c:105
__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 L(x)
Definition: ntvdm.h:50
#define LRESULT
Definition: ole.h:14
#define LOWORD(l)
Definition: pedump.c:82
BYTE * PBYTE
Definition: pedump.c:66
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 wYear
Definition: winbase.h:905
WORD wMilliseconds
Definition: winbase.h:912
WORD wMonth
Definition: winbase.h:906
WORD wHour
Definition: winbase.h:909
WORD wSecond
Definition: winbase.h:911
WORD wMinute
Definition: winbase.h:910
WORD wDay
Definition: winbase.h:908
LPCWSTR lpszClassName
Definition: winuser.h:3185
HBRUSH hbrBackground
Definition: winuser.h:3183
HINSTANCE hInstance
Definition: winuser.h:3180
UINT style
Definition: winuser.h:3176
WNDPROC lpfnWndProc
Definition: winuser.h:3177
int cbWndExtra
Definition: winuser.h:3179
HCURSOR hCursor
Definition: winuser.h:3182
Definition: inflate.c:139
UINT_PTR idFrom
Definition: winuser.h:3158
UINT code
Definition: winuser.h:3159
HWND hwndFrom
Definition: winuser.h:3157
LONG right
Definition: windef.h:308
LONG bottom
Definition: windef.h:309
LONG top
Definition: windef.h:307
LONG left
Definition: windef.h:306
#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
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
#define ZeroMemory
Definition: winbase.h:1712
struct _SYSTEMTIME * LPSYSTEMTIME
Definition: time.c:27
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
LONG_PTR LPARAM
Definition: windef.h:208
LONG_PTR LRESULT
Definition: windef.h:209
UINT_PTR WPARAM
Definition: windef.h:207
DWORD COLORREF
Definition: windef.h:300
#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:1539
#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:918
BOOL WINAPI GetTextExtentPoint32W(_In_ HDC hdc, _In_reads_(c) LPCWSTR lpString, _In_ int c, _Out_ LPSIZE psizl)
#define LOCALE_SABBREVDAYNAME1
Definition: winnls.h:84
#define LOCALE_IFIRSTDAYOFWEEK
Definition: winnls.h:75
#define WM_PAINT
Definition: winuser.h:1620
#define WM_ERASEBKGND
Definition: winuser.h:1625
DWORD WINAPI GetSysColor(_In_ int)
#define MAKEWPARAM(l, h)
Definition: winuser.h:4009
#define DT_NOPREFIX
Definition: winuser.h:537
#define GetWindowLongPtrW
Definition: winuser.h:4829
#define VK_TAB
Definition: winuser.h:2199
#define WM_ENABLE
Definition: winuser.h:1615
#define DT_CENTER
Definition: winuser.h:527
LRESULT WINAPI DefWindowProcW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define WM_CREATE
Definition: winuser.h:1608
#define WM_SIZE
Definition: winuser.h:1611
HBRUSH WINAPI GetSysColorBrush(_In_ int)
#define DT_SINGLELINE
Definition: winuser.h:540
#define WM_LBUTTONDBLCLK
Definition: winuser.h:1778
ATOM WINAPI RegisterClassW(_In_ CONST WNDCLASSW *)
#define IDC_ARROW
Definition: winuser.h:687
#define VK_UP
Definition: winuser.h:2225
#define WM_SETFOCUS
Definition: winuser.h:1613
#define GA_PARENT
Definition: winuser.h:2788
#define CS_DBLCLKS
Definition: winuser.h:651
#define WM_LBUTTONDOWN
Definition: winuser.h:1776
HCURSOR WINAPI LoadCursorW(_In_opt_ HINSTANCE, _In_ LPCWSTR)
Definition: cursoricon.c:2136
#define WM_GETFONT
Definition: winuser.h:1651
UINT_PTR WINAPI SetTimer(_In_opt_ HWND, _In_ UINT_PTR, _In_ UINT, _In_opt_ TIMERPROC)
#define WM_RBUTTONDOWN
Definition: winuser.h:1779
struct tagSTYLESTRUCT * LPSTYLESTRUCT
HWND WINAPI SetFocus(_In_opt_ HWND)
#define WM_SETFONT
Definition: winuser.h:1650
#define WM_TIMER
Definition: winuser.h:1742
BOOL WINAPI EndPaint(_In_ HWND, _In_ const PAINTSTRUCT *)
#define DLGC_WANTARROWS
Definition: winuser.h:2610
struct tagNMHDR * LPNMHDR
#define DT_VCENTER
Definition: winuser.h:543
#define VK_LEFT
Definition: winuser.h:2224
#define VK_RIGHT
Definition: winuser.h:2226
#define VK_DOWN
Definition: winuser.h:2227
#define GWLP_ID
Definition: winuser.h:860
#define WM_DESTROY
Definition: winuser.h:1609
BOOL WINAPI UnregisterClassW(_In_ LPCWSTR, HINSTANCE)
#define WM_KEYDOWN
Definition: winuser.h:1715
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:5355
BOOL WINAPI InflateRect(_Inout_ LPRECT, _In_ int, _In_ int)
#define GWL_STYLE
Definition: winuser.h:852
BOOL WINAPI GetUpdateRect(_In_ HWND, _Out_opt_ LPRECT, _In_ BOOL)
#define WM_KILLFOCUS
Definition: winuser.h:1614
struct tagCREATESTRUCTW * LPCREATESTRUCTW
int WINAPI GetSystemMetrics(_In_ int)
HWND WINAPI GetAncestor(_In_ HWND, _In_ UINT)
#define WM_GETDLGCODE
Definition: winuser.h:1689
#define WM_MBUTTONDOWN
Definition: winuser.h:1782
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
unsigned char BYTE
Definition: xxhash.c:193