2 * Date and time picker control
4 * Copyright 1998, 1999 Eric Kohl
5 * Copyright 1999, 2000 Alex Priem <alexp@sci.kun.nl>
6 * Copyright 2000 Chris Morgan <cmorgan@wpi.edu>
11 * - All notifications.
24 #include "debugtools.h"
26 DEFAULT_DEBUG_CHANNEL(datetime
);
29 #define DATETIME_GetInfoPtr(hwnd) ((DATETIME_INFO *)GetWindowLongA (hwnd, 0))
31 static BOOL
DATETIME_SendSimpleNotify (HWND hwnd
, UINT code
);
32 static BOOL
DATETIME_SendDateTimeChangeNotify (HWND hwnd
);
33 extern void MONTHCAL_CopyTime(const SYSTEMTIME
*from
, SYSTEMTIME
*to
);
34 static const char * const days
[] = {"Sunday", "Monday", "Tuesday", "Wednesday",
35 "Thursday", "Friday", "Saturday", NULL
};
36 static const char *allowedformatchars
= {"dhHmMstyX'"};
37 static const int maxrepetition
[] = {4,2,2,2,4,2,2,3,-1,-1};
41 DATETIME_GetSystemTime (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
43 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
44 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
45 SYSTEMTIME
*lprgSysTimeArray
=(SYSTEMTIME
*) lParam
;
47 if (!lParam
) return GDT_NONE
;
49 if ((dwStyle
& DTS_SHOWNONE
) &&
50 (SendMessageA (infoPtr
->hwndCheckbut
, BM_GETCHECK
, 0, 0)))
53 MONTHCAL_CopyTime (&infoPtr
->date
, lprgSysTimeArray
);
60 DATETIME_SetSystemTime (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
62 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
63 SYSTEMTIME
*lprgSysTimeArray
=(SYSTEMTIME
*) lParam
;
65 if (!lParam
) return 0;
67 if (lParam
==GDT_VALID
)
68 MONTHCAL_CopyTime (lprgSysTimeArray
, &infoPtr
->date
);
69 if (lParam
==GDT_NONE
) {
70 infoPtr
->dateValid
=FALSE
;
71 SendMessageA (infoPtr
->hwndCheckbut
, BM_SETCHECK
, 0, 0);
78 DATETIME_GetMonthCalColor (HWND hwnd
, WPARAM wParam
)
80 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
82 return SendMessageA (infoPtr
->hMonthCal
, MCM_GETCOLOR
, wParam
, 0);
87 DATETIME_SetMonthCalColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
89 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
91 return SendMessageA (infoPtr
->hMonthCal
, MCM_SETCOLOR
, wParam
, lParam
);
95 /* FIXME: need to get way to force font into monthcal structure */
97 DATETIME_GetMonthCal (HWND hwnd
)
99 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
101 return infoPtr
->hMonthCal
;
106 /* FIXME: need to get way to force font into monthcal structure */
109 DATETIME_GetMonthCalFont (HWND hwnd
)
117 DATETIME_SetMonthCalFont (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
125 Split up a formattxt in actions.
126 See ms documentation for the meaning of the letter codes/'specifiers'.
129 *'dddddd' is handled as 'dddd' plus 'dd'.
130 *unrecognized formats are strings (here given the type DT_STRING;
131 start of the string is encoded in lower bits of DT_STRING.
132 Therefore, 'string' ends finally up as '<show seconds>tring'.
138 DATETIME_UseFormat (DATETIME_INFO
*infoPtr
, const char *formattxt
)
141 int *nrFields
=& infoPtr
->nrFields
;
143 TRACE ("%s\n",formattxt
);
147 infoPtr
->fieldspec
[*nrFields
]=0;
148 len
=strlen(allowedformatchars
);
151 for (i
=0; i
<strlen (formattxt
); i
++) {
152 TRACE ("\n%d %c:",i
, formattxt
[i
]);
153 for (j
=0; j
<len
; j
++) {
154 if (allowedformatchars
[j
]==formattxt
[i
]) {
155 TRACE ("%c[%d,%x]",allowedformatchars
[j
], *nrFields
,
156 infoPtr
->fieldspec
[*nrFields
]);
157 if ((*nrFields
==0) && (infoPtr
->fieldspec
[*nrFields
]==0)) {
158 infoPtr
->fieldspec
[*nrFields
]=(j
<<4) +1;
161 if (infoPtr
->fieldspec
[*nrFields
]>>4!=j
) {
163 infoPtr
->fieldspec
[*nrFields
]=(j
<<4) +1;
166 if ((infoPtr
->fieldspec
[*nrFields
] & 0x0f)==maxrepetition
[j
]) {
168 infoPtr
->fieldspec
[*nrFields
]=(j
<<4) +1;
171 infoPtr
->fieldspec
[*nrFields
]++;
173 } /* if allowedformatchar */
177 /* char is not a specifier: handle char like a string */
179 if ((*nrFields
==0) && (infoPtr
->fieldspec
[*nrFields
]==0)) {
180 infoPtr
->fieldspec
[*nrFields
]=DT_STRING
+k
;
181 infoPtr
->buflen
[*nrFields
]=0;
183 if ((infoPtr
->fieldspec
[*nrFields
] & DT_STRING
)!=DT_STRING
) {
185 infoPtr
->fieldspec
[*nrFields
]=DT_STRING
+k
;
186 infoPtr
->buflen
[*nrFields
]=0;
188 infoPtr
->textbuf
[k
]=formattxt
[i
];
190 infoPtr
->buflen
[*nrFields
]++;
193 if (*nrFields
==infoPtr
->nrFieldsAllocated
) {
194 FIXME ("out of memory; should reallocate. crash ahead.\n");
201 if (infoPtr
->fieldspec
[*nrFields
]!=0) (*nrFields
)++;
206 DATETIME_SetFormat (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
208 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
211 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
213 if (dwStyle
& DTS_LONGDATEFORMAT
)
214 DATETIME_UseFormat (infoPtr
, "dddd, MMMM dd, yyy");
215 else if (dwStyle
& DTS_TIMEFORMAT
)
216 DATETIME_UseFormat (infoPtr
, "h:mm:ss tt");
217 else /* DTS_SHORTDATEFORMAT */
218 DATETIME_UseFormat (infoPtr
, "M/d/yy");
221 DATETIME_UseFormat (infoPtr
, (char *) lParam
);
223 return infoPtr
->nrFields
;
228 DATETIME_SetFormatW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
234 int len
= lstrlenW ((LPWSTR
) lParam
)+1;
236 buf
= (LPSTR
) COMCTL32_Alloc (len
);
237 lstrcpyWtoA (buf
, (LPWSTR
) lParam
);
238 retval
=DATETIME_SetFormat (hwnd
, 0, (LPARAM
) buf
);
243 return DATETIME_SetFormat (hwnd
, 0, 0);
249 DATETIME_ReturnTxt (DATETIME_INFO
*infoPtr
, int count
, char *result
)
251 SYSTEMTIME date
= infoPtr
->date
;
255 TRACE ("%d,%d\n", infoPtr
->nrFields
, count
);
256 if ((count
>infoPtr
->nrFields
) || (count
<0)) {
257 WARN ("buffer overrun, have %d want %d\n", infoPtr
->nrFields
, count
);
261 if (!infoPtr
->fieldspec
) return;
263 spec
=infoPtr
->fieldspec
[count
];
264 if (spec
& DT_STRING
) {
265 int txtlen
=infoPtr
->buflen
[count
];
267 strncpy (result
, infoPtr
->textbuf
+ (spec
&~ DT_STRING
), txtlen
);
269 TRACE ("arg%d=%x->[%s]\n",count
,infoPtr
->fieldspec
[count
],result
);
279 sprintf (result
,"%d",date
.wDay
);
282 sprintf (result
,"%.2d",date
.wDay
);
285 sprintf (result
,"%.3s",days
[date
.wDayOfWeek
]);
288 strcpy (result
,days
[date
.wDayOfWeek
]);
292 sprintf (result
,"%d",date
.wHour
-12);
294 sprintf (result
,"%d",date
.wHour
);
298 sprintf (result
,"%.2d",date
.wHour
-12);
300 sprintf (result
,"%.2d",date
.wHour
);
303 sprintf (result
,"%d",date
.wHour
);
306 sprintf (result
,"%.2d",date
.wHour
);
309 sprintf (result
,"%d",date
.wSecond
);
312 sprintf (result
,"%.2d",date
.wSecond
);
315 sprintf (result
,"%d",date
.wMinute
);
318 sprintf (result
,"%.2d",date
.wMinute
);
321 sprintf (result
,"%d",date
.wMonth
);
324 sprintf (result
,"%.2d",date
.wMonth
);
327 sprintf (result
,"%.3s",monthtxt
[date
.wMonth
-1]);
330 strcpy (result
,monthtxt
[date
.wMonth
-1]);
340 strcpy (result
,"AM");
342 strcpy (result
,"PM");
345 FIXME ("Not implemented\n");
346 strcpy (result
,"xxx");
349 sprintf (result
,"%d",date
.wYear
-10* (int) floor(date
.wYear
/10));
352 sprintf (result
,"%.2d",date
.wYear
-100* (int) floor(date
.wYear
/100));
355 sprintf (result
,"%d",date
.wYear
);
359 TRACE ("arg%d=%x->[%s]\n",count
,infoPtr
->fieldspec
[count
],result
);
364 DATETIME_IncreaseField (DATETIME_INFO
*infoPtr
, int number
)
366 SYSTEMTIME
*date
= &infoPtr
->date
;
369 TRACE ("%d\n",number
);
370 if ((number
>infoPtr
->nrFields
) || (number
<0)) return;
372 spec
=infoPtr
->fieldspec
[number
];
373 if ((spec
& DTHT_DATEFIELD
)==0) return;
381 if (date
->wDay
>mdays
[date
->wMonth
-1]) date
->wDay
=1;
388 if (date
->wHour
>23) date
->wHour
=0;
393 if (date
->wSecond
>59) date
->wSecond
=0;
398 if (date
->wMinute
>59) date
->wMinute
=0;
405 if (date
->wMonth
>12) date
->wMonth
=1;
406 if (date
->wDay
>mdays
[date
->wMonth
-1])
407 date
->wDay
=mdays
[date
->wMonth
-1];
412 if (date
->wHour
>23) date
->wHour
-=24;
415 FIXME ("Not implemented\n");
428 DATETIME_DecreaseField (DATETIME_INFO
*infoPtr
, int number
)
430 SYSTEMTIME
*date
= & infoPtr
->date
;
433 TRACE ("%d\n",number
);
434 if ((number
>infoPtr
->nrFields
) || (number
<0)) return;
436 spec
= infoPtr
->fieldspec
[number
];
437 if ((spec
& DTHT_DATEFIELD
)==0) return;
447 if (date
->wDay
<1) date
->wDay
=mdays
[date
->wMonth
-1];
480 if (date
->wDay
>mdays
[date
->wMonth
-1])
481 date
->wDay
=mdays
[date
->wMonth
-1];
491 FIXME ("Not implemented\n");
504 DATETIME_ResetFieldDown (DATETIME_INFO
*infoPtr
, int number
)
506 SYSTEMTIME
*date
= &infoPtr
->date
;
509 TRACE ("%d\n",number
);
510 if ((number
>infoPtr
->nrFields
) || (number
<0)) return;
512 spec
= infoPtr
->fieldspec
[number
];
513 if ((spec
& DTHT_DATEFIELD
)==0) return;
545 FIXME ("Not implemented\n");
549 /* FYI: On 9/14/1752 the calender changed and England and the American */
550 /* colonies changed to the Gregorian calender. This change involved */
551 /* having September 14th following September 2nd. So no date algorithms */
552 /* work before that date. */
557 date
->wDay
= 14; /* overactive ms-programmers..*/
567 DATETIME_ResetFieldUp (DATETIME_INFO
*infoPtr
, int number
)
569 SYSTEMTIME
*date
= & infoPtr
->date
;
572 if ((number
>infoPtr
->nrFields
) || (number
<0)) return;
574 spec
=infoPtr
->fieldspec
[number
];
575 if ((spec
& DTHT_DATEFIELD
)==0) return;
582 date
->wDay
=mdays
[date
->wMonth
-1];
606 FIXME ("Not implemented\n");
611 date
->wYear
=9999; /* Y10K problem? naaah. */
618 static void DATETIME_Refresh (HWND hwnd
, HDC hdc
)
621 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
624 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
625 RECT
*rcDraw
= &infoPtr
->rcDraw
;
626 RECT
*rcClient
= &infoPtr
->rcClient
;
627 RECT
*calbutton
= &infoPtr
->calbutton
;
628 RECT
*checkbox
= &infoPtr
->checkbox
;
631 COLORREF oldBk
, oldTextColor
;
633 /* draw control edge */
634 hbr
= CreateSolidBrush(RGB(255, 255, 255));
635 FillRect(hdc
, rcClient
, hbr
);
636 DrawEdge(hdc
, rcClient
, EDGE_SUNKEN
, BF_RECT
);
639 if (infoPtr
->dateValid
) {
642 oldFont
= SelectObject (hdc
, infoPtr
->hFont
);
644 DATETIME_ReturnTxt (infoPtr
, 0, txt
);
645 GetTextExtentPoint32A (hdc
, txt
, strlen (txt
), &size
);
646 rcDraw
->bottom
= size
.cy
+2;
648 if (dwStyle
& DTS_SHOWNONE
) checkbox
->right
= 18;
650 prevright
= checkbox
->right
;
652 for (i
=0; i
<infoPtr
->nrFields
; i
++) {
653 DATETIME_ReturnTxt (infoPtr
, i
, txt
);
654 GetTextExtentPoint32A (hdc
, txt
, strlen (txt
), &size
);
655 field
= & infoPtr
->fieldRect
[i
];
656 field
->left
= prevright
;
657 field
->right
= prevright
+size
.cx
;
658 field
->top
= rcDraw
->top
;
659 field
->bottom
= rcDraw
->bottom
;
660 prevright
= field
->right
;
662 if ((infoPtr
->haveFocus
) && (i
==infoPtr
->select
)) {
663 hbr
= CreateSolidBrush (GetSysColor (COLOR_ACTIVECAPTION
));
664 FillRect(hdc
, field
, hbr
);
665 oldBk
= SetBkColor (hdc
, GetSysColor(COLOR_ACTIVECAPTION
));
666 oldTextColor
= SetTextColor (hdc
, GetSysColor(COLOR_WINDOW
));
668 DrawTextA ( hdc
, txt
, strlen(txt
), field
,
669 DT_RIGHT
| DT_VCENTER
| DT_SINGLELINE
);
670 SetBkColor (hdc
, oldBk
);
671 SetTextColor (hdc
, oldTextColor
);
674 DrawTextA ( hdc
, txt
, strlen(txt
), field
,
675 DT_RIGHT
| DT_VCENTER
| DT_SINGLELINE
);
678 SelectObject (hdc
, oldFont
);
681 if (!(dwStyle
& DTS_UPDOWN
)) {
682 DrawFrameControl(hdc
, calbutton
, DFC_SCROLL
,
683 DFCS_SCROLLDOWN
| (infoPtr
->bCalDepressed
? DFCS_PUSHED
: 0) |
684 (dwStyle
& WS_DISABLED
? DFCS_INACTIVE
: 0) );
690 DATETIME_HitTest (HWND hwnd
, DATETIME_INFO
*infoPtr
, POINT pt
)
694 TRACE ("%ld, %ld\n",pt
.x
,pt
.y
);
697 if (PtInRect (&infoPtr
->calbutton
, pt
))
698 {retval
= DTHT_MCPOPUP
; TRACE("Hit in calbutton(DTHT_MCPOPUP)\n"); goto done
; }
699 if (PtInRect (&infoPtr
->checkbox
, pt
))
700 {retval
= DTHT_CHECKBOX
; TRACE("Hit in checkbox(DTHT_CHECKBOX)\n"); goto done
; }
702 for (i
=0; i
<infoPtr
->nrFields
; i
++) {
703 if (PtInRect (&infoPtr
->fieldRect
[i
], pt
)) {
705 TRACE("Hit in date text in field %d\n", i
);
716 DATETIME_LButtonDown (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
718 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
719 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
725 old
= infoPtr
->select
;
726 pt
.x
= (INT
)LOWORD(lParam
);
727 pt
.y
= (INT
)HIWORD(lParam
);
729 new = DATETIME_HitTest (hwnd
, infoPtr
, pt
);
731 /* FIXME: might be conditions where we don't want to update infoPtr->select */
732 infoPtr
->select
= new;
734 if (infoPtr
->select
!= old
) {
735 infoPtr
->haveFocus
= DTHT_GOTFOCUS
;
738 if (infoPtr
->select
== DTHT_MCPOPUP
) {
739 /* FIXME: button actually is only depressed during dropdown of the */
740 /* calender control and when the mouse is over the button window */
741 infoPtr
->bCalDepressed
= TRUE
;
743 /* recalculate the position of the monthcal popup */
744 if(dwStyle
& DTS_RIGHTALIGN
)
745 infoPtr
->monthcal_pos
.x
= infoPtr
->rcClient
.right
- ((infoPtr
->calbutton
.right
-
746 infoPtr
->calbutton
.left
) + 145);
748 infoPtr
->monthcal_pos
.x
= 8;
750 infoPtr
->monthcal_pos
.y
= infoPtr
->rcClient
.bottom
;
751 ClientToScreen (hwnd
, &(infoPtr
->monthcal_pos
));
752 SetWindowPos(infoPtr
->hMonthCal
, 0, infoPtr
->monthcal_pos
.x
,
753 infoPtr
->monthcal_pos
.y
, 145, 150, 0);
755 if(IsWindowVisible(infoPtr
->hMonthCal
))
756 ShowWindow(infoPtr
->hMonthCal
, SW_HIDE
);
758 ShowWindow(infoPtr
->hMonthCal
, SW_SHOW
);
760 TRACE ("dt:%x mc:%x mc parent:%x, desktop:%x, mcpp:%x\n",
761 hwnd
,infoPtr
->hMonthCal
,
762 GetParent (infoPtr
->hMonthCal
),
764 GetParent (GetParent (infoPtr
->hMonthCal
)));
765 DATETIME_SendSimpleNotify (hwnd
, DTN_DROPDOWN
);
768 InvalidateRect(hwnd
, NULL
, FALSE
);
775 DATETIME_LButtonUp (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
777 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
781 if(infoPtr
->bCalDepressed
== TRUE
) {
782 infoPtr
->bCalDepressed
= FALSE
;
783 RedrawWindow(hwnd
, &(infoPtr
->calbutton
), 0, RDW_ERASE
|RDW_INVALIDATE
);
791 DATETIME_Paint (HWND hwnd
, WPARAM wParam
)
796 hdc
= wParam
==0 ? BeginPaint (hwnd
, &ps
) : (HDC
)wParam
;
797 DATETIME_Refresh (hwnd
, hdc
);
799 EndPaint (hwnd
, &ps
);
805 DATETIME_ParentNotify (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
807 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
808 LPNMHDR lpnmh
= (LPNMHDR
) lParam
;
810 TRACE ("%x,%lx\n",wParam
, lParam
);
811 TRACE ("Got notification %x from %x\n", lpnmh
->code
, lpnmh
->hwndFrom
);
812 TRACE ("info: %x %x %x\n",hwnd
,infoPtr
->hMonthCal
,infoPtr
->hUpdown
);
818 DATETIME_Notify (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
821 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
822 LPNMHDR lpnmh
= (LPNMHDR
) lParam
;
824 TRACE ("%x,%lx\n",wParam
, lParam
);
825 TRACE ("Got notification %x from %x\n", lpnmh
->code
, lpnmh
->hwndFrom
);
826 TRACE ("info: %x %x %x\n",hwnd
,infoPtr
->hMonthCal
,infoPtr
->hUpdown
);
832 DATETIME_KeyDown (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
834 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
837 TRACE("%x %lx %x\n",wParam
, lParam
, infoPtr
->select
);
839 FieldNum
= infoPtr
->select
& DTHT_DATEFIELD
;
841 if (!(infoPtr
->haveFocus
)) return 0;
842 if ((FieldNum
==0) && (infoPtr
->select
)) return 0;
844 if (infoPtr
->select
& FORMATCALLMASK
) {
845 FIXME ("Callbacks not implemented yet\n");
851 DATETIME_IncreaseField (infoPtr
,FieldNum
);
852 DATETIME_SendDateTimeChangeNotify (hwnd
);
856 DATETIME_DecreaseField (infoPtr
,FieldNum
);
857 DATETIME_SendDateTimeChangeNotify (hwnd
);
860 DATETIME_ResetFieldDown (infoPtr
,FieldNum
);
861 DATETIME_SendDateTimeChangeNotify (hwnd
);
864 DATETIME_ResetFieldUp(infoPtr
,FieldNum
);
865 DATETIME_SendDateTimeChangeNotify (hwnd
);
869 if (infoPtr
->select
==0) {
870 infoPtr
->select
= infoPtr
->nrFields
- 1;
875 while ((infoPtr
->fieldspec
[infoPtr
->select
] & DT_STRING
) && (wrap
<2));
880 if (infoPtr
->select
==infoPtr
->nrFields
) {
885 while ((infoPtr
->fieldspec
[infoPtr
->select
] & DT_STRING
) && (wrap
<2));
889 InvalidateRect(hwnd
, NULL
, FALSE
);
896 DATETIME_KillFocus (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
898 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
902 if (infoPtr
->haveFocus
) {
903 DATETIME_SendSimpleNotify (hwnd
, NM_KILLFOCUS
);
904 infoPtr
->haveFocus
= 0;
907 InvalidateRect (hwnd
, NULL
, TRUE
);
914 DATETIME_SetFocus (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
916 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
920 if (infoPtr
->haveFocus
==0) {
921 DATETIME_SendSimpleNotify (hwnd
, NM_SETFOCUS
);
922 infoPtr
->haveFocus
= DTHT_GOTFOCUS
;
925 InvalidateRect(hwnd
, NULL
, FALSE
);
932 DATETIME_SendDateTimeChangeNotify (HWND hwnd
)
935 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
936 NMDATETIMECHANGE dtdtc
;
939 dtdtc
.nmhdr
.hwndFrom
= hwnd
;
940 dtdtc
.nmhdr
.idFrom
= GetWindowLongA( hwnd
, GWL_ID
);
941 dtdtc
.nmhdr
.code
= DTN_DATETIMECHANGE
;
943 if ((GetWindowLongA (hwnd
, GWL_STYLE
) & DTS_SHOWNONE
))
944 dtdtc
.dwFlags
= GDT_NONE
;
946 dtdtc
.dwFlags
= GDT_VALID
;
948 MONTHCAL_CopyTime (&infoPtr
->date
, &dtdtc
.st
);
949 return (BOOL
) SendMessageA (GetParent (hwnd
), WM_NOTIFY
,
950 (WPARAM
)dtdtc
.nmhdr
.idFrom
, (LPARAM
)&dtdtc
);
955 DATETIME_SendSimpleNotify (HWND hwnd
, UINT code
)
960 nmhdr
.hwndFrom
= hwnd
;
961 nmhdr
.idFrom
= GetWindowLongA( hwnd
, GWL_ID
);
964 return (BOOL
) SendMessageA (GetParent (hwnd
), WM_NOTIFY
,
965 (WPARAM
)nmhdr
.idFrom
, (LPARAM
)&nmhdr
);
969 DATETIME_Size (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
971 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr(hwnd
);
972 DWORD dwStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
975 infoPtr
->rcClient
.bottom
= HIWORD(lParam
);
976 infoPtr
->rcClient
.right
= LOWORD(lParam
);
978 TRACE("Height=%d, Width=%d\n", infoPtr
->rcClient
.bottom
, infoPtr
->rcClient
.right
);
980 /* use DrawEdge to adjust the size of rcEdge to get rcDraw */
981 memcpy((&infoPtr
->rcDraw
), (&infoPtr
->rcClient
), sizeof(infoPtr
->rcDraw
));
983 DrawEdge((HDC
)NULL
, &(infoPtr
->rcDraw
), EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
985 /* set the size of the button that drops the calender down */
986 /* FIXME: account for style that allows button on left side */
987 infoPtr
->calbutton
.top
= infoPtr
->rcDraw
.top
;
988 infoPtr
->calbutton
.bottom
= infoPtr
->rcDraw
.bottom
;
989 infoPtr
->calbutton
.left
= infoPtr
->rcDraw
.right
-15;
990 infoPtr
->calbutton
.right
= infoPtr
->rcDraw
.right
;
992 /* set enable/disable button size for show none style being enabled */
993 /* FIXME: these dimensions are completely incorrect */
994 infoPtr
->checkbox
.top
= infoPtr
->rcDraw
.top
;
995 infoPtr
->checkbox
.bottom
= infoPtr
->rcDraw
.bottom
;
996 infoPtr
->checkbox
.left
= infoPtr
->rcDraw
.left
;
997 infoPtr
->checkbox
.right
= infoPtr
->rcDraw
.left
+ 10;
999 /* update the position of the monthcal control */
1000 if(dwStyle
& DTS_RIGHTALIGN
)
1001 infoPtr
->monthcal_pos
.x
= infoPtr
->rcClient
.right
- ((infoPtr
->calbutton
.right
-
1002 infoPtr
->calbutton
.left
) + 145);
1004 infoPtr
->monthcal_pos
.x
= 8;
1006 infoPtr
->monthcal_pos
.y
= infoPtr
->rcClient
.bottom
;
1007 ClientToScreen (hwnd
, &(infoPtr
->monthcal_pos
));
1008 SetWindowPos(infoPtr
->hMonthCal
, 0, infoPtr
->monthcal_pos
.x
,
1009 infoPtr
->monthcal_pos
.y
,
1012 InvalidateRect(hwnd
, NULL
, FALSE
);
1019 DATETIME_Create (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1021 DATETIME_INFO
*infoPtr
;
1022 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
1024 /* allocate memory for info structure */
1025 infoPtr
= (DATETIME_INFO
*)COMCTL32_Alloc (sizeof(DATETIME_INFO
));
1026 if (infoPtr
== NULL
) {
1027 ERR("could not allocate info memory!\n");
1031 SetWindowLongA (hwnd
, 0, (DWORD
)infoPtr
);
1033 if (dwStyle
& DTS_SHOWNONE
) {
1034 infoPtr
->hwndCheckbut
=CreateWindowExA (0,"button", 0,
1035 WS_CHILD
| WS_VISIBLE
| BS_AUTOCHECKBOX
,
1038 0, GetWindowLongA (hwnd
, GWL_HINSTANCE
), 0);
1039 SendMessageA (infoPtr
->hwndCheckbut
, BM_SETCHECK
, 1, 0);
1042 if (dwStyle
& DTS_UPDOWN
) {
1043 infoPtr
->hUpdown
=CreateUpDownControl (
1044 WS_CHILD
| WS_BORDER
| WS_VISIBLE
,
1047 UD_MAXVAL
, UD_MINVAL
, 0);
1050 infoPtr
->fieldspec
= (int *) COMCTL32_Alloc (32*sizeof(int));
1051 infoPtr
->fieldRect
= (RECT
*) COMCTL32_Alloc (32*sizeof(RECT
));
1052 infoPtr
->buflen
= (int *) COMCTL32_Alloc (32*sizeof(int));
1053 infoPtr
->nrFieldsAllocated
= 32;
1055 DATETIME_SetFormat (hwnd
, 0, 0);
1057 /* create the monthcal control */
1058 infoPtr
->hMonthCal
= CreateWindowExA (0,"SysMonthCal32", 0,
1059 WS_BORDER
| WS_POPUP
| WS_CLIPSIBLINGS
,
1064 /* initialize info structure */
1065 GetSystemTime (&infoPtr
->date
);
1066 infoPtr
->dateValid
= TRUE
;
1067 infoPtr
->hFont
= GetStockObject(DEFAULT_GUI_FONT
);
1073 DATETIME_Destroy (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1075 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
1077 COMCTL32_Free (infoPtr
);
1082 static LRESULT WINAPI
1083 DATETIME_WindowProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1088 case DTM_GETSYSTEMTIME
:
1089 DATETIME_GetSystemTime (hwnd
, wParam
, lParam
);
1091 case DTM_SETSYSTEMTIME
:
1092 DATETIME_SetSystemTime (hwnd
, wParam
, lParam
);
1095 FIXME("Unimplemented msg DTM_GETRANGE\n");
1099 FIXME("Unimplemented msg DTM_SETRANGE\n");
1102 case DTM_SETFORMATA
:
1103 return DATETIME_SetFormat (hwnd
, wParam
, lParam
);
1105 case DTM_SETFORMATW
:
1106 return DATETIME_SetFormatW (hwnd
, wParam
, lParam
);
1108 case DTM_SETMCCOLOR
:
1109 return DATETIME_SetMonthCalColor (hwnd
, wParam
, lParam
);
1111 case DTM_GETMCCOLOR
:
1112 return DATETIME_GetMonthCalColor (hwnd
, wParam
);
1114 case DTM_GETMONTHCAL
:
1115 return DATETIME_GetMonthCal (hwnd
);
1118 return DATETIME_SetMonthCalFont (hwnd
, wParam
, lParam
);
1121 return DATETIME_GetMonthCalFont (hwnd
);
1123 case WM_PARENTNOTIFY
:
1124 return DATETIME_ParentNotify (hwnd
, wParam
, lParam
);
1127 return DATETIME_Notify (hwnd
, wParam
, lParam
);
1130 return DLGC_WANTARROWS
| DLGC_WANTCHARS
;
1133 return DATETIME_Paint (hwnd
, wParam
);
1136 return DATETIME_KeyDown (hwnd
, wParam
, lParam
);
1139 return DATETIME_KillFocus (hwnd
, wParam
, lParam
);
1142 return DATETIME_SetFocus (hwnd
, wParam
, lParam
);
1145 return DATETIME_Size (hwnd
, wParam
, lParam
);
1147 case WM_LBUTTONDOWN
:
1148 return DATETIME_LButtonDown (hwnd
, wParam
, lParam
);
1151 return DATETIME_LButtonUp (hwnd
, wParam
, lParam
);
1154 return DATETIME_Create (hwnd
, wParam
, lParam
);
1157 return DATETIME_Destroy (hwnd
, wParam
, lParam
);
1160 if (uMsg
>= WM_USER
)
1161 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
1162 uMsg
, wParam
, lParam
);
1163 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
1170 DATETIME_Register (void)
1174 ZeroMemory (&wndClass
, sizeof(WNDCLASSA
));
1175 wndClass
.style
= CS_GLOBALCLASS
;
1176 wndClass
.lpfnWndProc
= (WNDPROC
)DATETIME_WindowProc
;
1177 wndClass
.cbClsExtra
= 0;
1178 wndClass
.cbWndExtra
= sizeof(DATETIME_INFO
*);
1179 wndClass
.hCursor
= LoadCursorA (0, IDC_ARROWA
);
1180 wndClass
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
1181 wndClass
.lpszClassName
= DATETIMEPICK_CLASSA
;
1183 RegisterClassA (&wndClass
);
1188 DATETIME_Unregister (void)
1190 UnregisterClassA (DATETIMEPICK_CLASSA
, (HINSTANCE
)NULL
);