2 * Date and time picker control
4 * Copyright 1998, 1999 Eric Kohl
5 * Copyright 1999 Alex Priem <alexp@sci.kun.nl>
10 * - All notifications.
18 #include "debugtools.h"
20 DEFAULT_DEBUG_CHANNEL(datetime
)
24 #define DATETIME_GetInfoPtr(hwnd) ((DATETIME_INFO *)GetWindowLongA (hwnd, 0))
27 DATETIME_SendSimpleNotify (HWND hwnd
, UINT code
);
29 extern char *days
[]; /* from ole/parsedt.c */
33 DATETIME_GetSystemTime (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
35 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
36 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
37 SYSTEMTIME
*lprgSysTimeArray
=(SYSTEMTIME
*) lParam
;
39 if (!lParam
) return GDT_NONE
;
41 if ((dwStyle
& DTS_SHOWNONE
) &&
42 (SendMessageA (infoPtr
->hwndCheckbut
, BM_GETCHECK
, 0, 0)))
45 MONTHCAL_CopyTime (&infoPtr
->date
, lprgSysTimeArray
);
52 DATETIME_SetSystemTime (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
54 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
55 SYSTEMTIME
*lprgSysTimeArray
=(SYSTEMTIME
*) lParam
;
57 if (!lParam
) return 0;
59 if (lParam
==GDT_VALID
)
60 MONTHCAL_CopyTime (lprgSysTimeArray
, &infoPtr
->date
);
61 if (lParam
==GDT_NONE
) {
62 infoPtr
->dateValid
=FALSE
;
63 SendMessageA (infoPtr
->hwndCheckbut
, BM_SETCHECK
, 0, 0);
70 DATETIME_GetMonthCalColor (HWND hwnd
, WPARAM wParam
)
72 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
74 return SendMessageA (infoPtr
->hMonthCal
, MCM_GETCOLOR
, wParam
, 0);
78 DATETIME_SetMonthCalColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
80 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
82 return SendMessageA (infoPtr
->hMonthCal
, MCM_SETCOLOR
, wParam
, lParam
);
86 /* FIXME: need to get way to force font into monthcal structure */
89 DATETIME_GetMonthCal (HWND hwnd
)
91 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
93 return infoPtr
->hMonthCal
;
98 /* FIXME: need to get way to force font into monthcal structure */
101 DATETIME_GetMonthCalFont (HWND hwnd
)
108 DATETIME_SetMonthCalFont (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
115 static void DATETIME_Refresh (HWND hwnd
, HDC hdc
)
118 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
119 RECT
*daytxt
= &infoPtr
->daytxt
;
120 RECT
*daynumtxt
= &infoPtr
->daynumtxt
;
121 RECT
*rmonthtxt
= &infoPtr
->rmonthtxt
;
122 RECT
*yeartxt
= &infoPtr
->yeartxt
;
123 RECT
*calbutton
= &infoPtr
->calbutton
;
124 RECT
*checkbox
= &infoPtr
->checkbox
;
125 RECT
*rect
= &infoPtr
->rect
;
126 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
127 SYSTEMTIME date
= infoPtr
->date
;
134 if (infoPtr
->dateValid
) {
137 oldFont
= SelectObject (hdc
, infoPtr
->hFont
);
139 GetClientRect (hwnd
, rect
);
141 sprintf (txt
,"%s,",days
[date
.wDayOfWeek
]);
142 GetTextExtentPoint32A (hdc
, txt
, strlen (txt
), &size
);
143 rect
->bottom
=size
.cy
+2;
147 checkbox
->top
= rect
->top
;
148 checkbox
->bottom
= rect
->bottom
;
149 if (dwStyle
& DTS_SHOWNONE
) { /* FIXME: draw checkbox */
154 if (infoPtr
->select
==(DTHT_DAY
|DTHT_GOTFOCUS
))
155 oldBk
=SetBkColor (hdc
, COLOR_GRAYTEXT
);
156 daytxt
->left
= checkbox
->right
;
157 daytxt
->right
= checkbox
->right
+size
.cx
;
158 daytxt
->top
= rect
->top
;
159 daytxt
->bottom
= rect
->bottom
;
160 DrawTextA ( hdc
, txt
, strlen(txt
), daytxt
,
161 DT_LEFT
| DT_VCENTER
| DT_SINGLELINE
);
162 if (infoPtr
->select
==(DTHT_DAY
|DTHT_GOTFOCUS
))
163 SetBkColor (hdc
, oldBk
);
165 if (infoPtr
->select
==(DTHT_MONTH
|DTHT_GOTFOCUS
))
166 oldBk
=SetBkColor (hdc
, COLOR_GRAYTEXT
);
167 strcpy (txt
, monthtxt
[date
.wMonth
]);
168 GetTextExtentPoint32A (hdc
, "September", 9, &size
);
169 rmonthtxt
->left
= daytxt
->right
;
170 rmonthtxt
->right
= daytxt
->right
+size
.cx
;
171 rmonthtxt
->top
= rect
->top
;
172 rmonthtxt
->bottom
= rect
->bottom
;
173 DrawTextA ( hdc
, txt
, strlen(txt
), rmonthtxt
,
174 DT_CENTER
| DT_VCENTER
| DT_SINGLELINE
);
175 if (infoPtr
->select
==(DTHT_MONTH
|DTHT_GOTFOCUS
))
176 SetBkColor (hdc
, oldBk
);
178 if (infoPtr
->select
==(DTHT_DAYNUM
|DTHT_GOTFOCUS
))
179 oldBk
=SetBkColor (hdc
, COLOR_GRAYTEXT
);
180 sprintf (txt
,"%d,",date
.wDay
);
181 GetTextExtentPoint32A (hdc
, "31,", 3, &size
);
182 daynumtxt
->left
= rmonthtxt
->right
;
183 daynumtxt
->right
= rmonthtxt
->right
+size
.cx
;
184 daynumtxt
->top
= rect
->top
;
185 daynumtxt
->bottom
= rect
->bottom
;
186 DrawTextA ( hdc
, txt
, strlen(txt
), daynumtxt
,
187 DT_RIGHT
| DT_VCENTER
| DT_SINGLELINE
);
188 if (infoPtr
->select
==(DTHT_DAYNUM
|DTHT_GOTFOCUS
))
189 SetBkColor (hdc
, oldBk
);
191 if (infoPtr
->select
==(DTHT_YEAR
|DTHT_GOTFOCUS
))
192 oldBk
=SetBkColor (hdc
, COLOR_GRAYTEXT
);
193 sprintf (txt
,"%d",date
.wYear
);
194 GetTextExtentPoint32A (hdc
, "2000", 5, &size
);
195 yeartxt
->left
= daynumtxt
->right
;
196 yeartxt
->right
= daynumtxt
->right
+size
.cx
;
197 yeartxt
->top
= rect
->top
;
198 yeartxt
->bottom
= rect
->bottom
;
199 DrawTextA ( hdc
, txt
, strlen(txt
), yeartxt
,
200 DT_RIGHT
| DT_VCENTER
| DT_SINGLELINE
);
201 if (infoPtr
->select
==(DTHT_YEAR
|DTHT_GOTFOCUS
))
202 SetBkColor (hdc
, oldBk
);
204 SelectObject (hdc
, oldFont
);
207 if (!(dwStyle
& DTS_UPDOWN
)) {
209 calbutton
->right
= rect
->right
;
210 calbutton
->left
= rect
->right
-15;
211 calbutton
->top
= rect
->top
;
212 calbutton
->bottom
= rect
->bottom
;
214 DrawFrameControl(hdc
, calbutton
, DFC_SCROLL
,
215 DFCS_SCROLLDOWN
| (prssed
? DFCS_PUSHED
: 0) |
216 (dwStyle
& WS_DISABLED
? DFCS_INACTIVE
: 0) );
222 DATETIME_HitTest (HWND hwnd
, DATETIME_INFO
*infoPtr
, POINT pt
)
224 TRACE ("%ld, %ld\n",pt
.x
,pt
.y
);
226 if (PtInRect (&infoPtr
->calbutton
, pt
)) return DTHT_MCPOPUP
;
227 if (PtInRect (&infoPtr
->yeartxt
, pt
)) return DTHT_YEAR
;
228 if (PtInRect (&infoPtr
->daynumtxt
, pt
)) return DTHT_DAYNUM
;
229 if (PtInRect (&infoPtr
->rmonthtxt
, pt
)) return DTHT_MONTH
;
230 if (PtInRect (&infoPtr
->daytxt
, pt
)) return DTHT_DAY
;
231 if (PtInRect (&infoPtr
->checkbox
, pt
)) return DTHT_CHECKBOX
;
237 DATETIME_LButtonDown (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
239 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
246 pt
.x
=(INT
)LOWORD(lParam
);
247 pt
.y
=(INT
)HIWORD(lParam
);
248 infoPtr
->select
=DATETIME_HitTest (hwnd
, infoPtr
, pt
);
250 if (infoPtr
->select
!=old
) {
255 DATETIME_Refresh (hwnd
,hdc
);
256 ReleaseDC (hwnd
, hdc
);
258 if (infoPtr
->select
==DTHT_MCPOPUP
) {
262 pt
.y
=infoPtr
->rect
.bottom
+5;
263 ClientToScreen (hwnd
, &pt
);
264 infoPtr
->hMonthCal
=CreateWindowExA (0,"SysMonthCal32", 0,
265 WS_POPUP
| WS_BORDER
,
270 TRACE ("dt:%x mc:%x mc parent:%x, desktop:%x, mcpp:%x\n",
271 hwnd
,infoPtr
->hMonthCal
,
272 GetParent (infoPtr
->hMonthCal
),
274 GetParent (GetParent (infoPtr
->hMonthCal
)));
277 DATETIME_SendSimpleNotify (hwnd
, DTN_DROPDOWN
);
284 DATETIME_Paint (HWND hwnd
, WPARAM wParam
)
289 hdc
= wParam
==0 ? BeginPaint (hwnd
, &ps
) : (HDC
)wParam
;
290 DATETIME_Refresh (hwnd
, hdc
);
292 EndPaint (hwnd
, &ps
);
297 DATETIME_ParentNotify (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
299 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
300 LPNMHDR lpnmh
=(LPNMHDR
) lParam
;
302 TRACE ("%x,%lx\n",wParam
, lParam
);
303 TRACE ("Got notification %x from %x\n", lpnmh
->code
, lpnmh
->hwndFrom
);
304 TRACE ("info: %x %x %x\n",hwnd
,infoPtr
->hMonthCal
,infoPtr
->hUpdown
);
309 DATETIME_Notify (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
312 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
313 LPNMHDR lpnmh
=(LPNMHDR
) lParam
;
315 TRACE ("%x,%lx\n",wParam
, lParam
);
316 TRACE ("Got notification %x from %x\n", lpnmh
->code
, lpnmh
->hwndFrom
);
317 TRACE ("info: %x %x %x\n",hwnd
,infoPtr
->hMonthCal
,infoPtr
->hUpdown
);
322 DATETIME_KillFocus (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
324 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
329 if (infoPtr
->select
) {
330 DATETIME_SendSimpleNotify (hwnd
, NM_KILLFOCUS
);
331 infoPtr
->select
&= ~DTHT_GOTFOCUS
;
334 DATETIME_Refresh (hwnd
, hdc
);
335 ReleaseDC (hwnd
, hdc
);
336 InvalidateRect (hwnd
, NULL
, TRUE
);
343 DATETIME_SetFocus (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
346 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
350 if (infoPtr
->select
) {
351 DATETIME_SendSimpleNotify (hwnd
, NM_SETFOCUS
);
352 infoPtr
->select
|=DTHT_GOTFOCUS
;
355 DATETIME_Refresh (hwnd
, hdc
);
356 ReleaseDC (hwnd
, hdc
);
363 DATETIME_SendSimpleNotify (HWND hwnd
, UINT code
)
368 nmhdr
.hwndFrom
= hwnd
;
369 nmhdr
.idFrom
= GetWindowLongA( hwnd
, GWL_ID
);
372 return (BOOL
) SendMessageA (GetParent (hwnd
), WM_NOTIFY
,
373 (WPARAM
)nmhdr
.idFrom
, (LPARAM
)&nmhdr
);
382 DATETIME_Create (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
384 DATETIME_INFO
*infoPtr
;
385 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
387 /* allocate memory for info structure */
388 infoPtr
= (DATETIME_INFO
*)COMCTL32_Alloc (sizeof(DATETIME_INFO
));
389 if (infoPtr
== NULL
) {
390 ERR("could not allocate info memory!\n");
394 SetWindowLongA (hwnd
, 0, (DWORD
)infoPtr
);
396 if (dwStyle
& DTS_SHOWNONE
) {
397 infoPtr
->hwndCheckbut
=CreateWindowExA (0,"button", 0,
398 WS_CHILD
| WS_VISIBLE
| BS_AUTOCHECKBOX
,
401 0, GetWindowLongA (hwnd
, GWL_HINSTANCE
), 0);
402 SendMessageA (infoPtr
->hwndCheckbut
, BM_SETCHECK
, 1, 0);
405 if (dwStyle
& DTS_UPDOWN
) {
407 infoPtr
->hUpdown
=CreateUpDownControl (
408 WS_CHILD
| WS_BORDER
| WS_VISIBLE
,
411 UD_MAXVAL
, UD_MINVAL
, 0);
414 /* initialize info structure */
415 infoPtr
->hMonthCal
=0;
416 GetSystemTime (&infoPtr
->date
);
417 infoPtr
->dateValid
= TRUE
;
418 infoPtr
->hFont
= GetStockObject(DEFAULT_GUI_FONT
);
424 DATETIME_Destroy (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
426 DATETIME_INFO
*infoPtr
= DATETIME_GetInfoPtr (hwnd
);
428 COMCTL32_Free (infoPtr
);
436 static LRESULT WINAPI
437 DATETIME_WindowProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
443 case DTM_GETSYSTEMTIME
:
444 DATETIME_GetSystemTime (hwnd
, wParam
, lParam
);
446 case DTM_SETSYSTEMTIME
:
447 DATETIME_SetSystemTime (hwnd
, wParam
, lParam
);
450 FIXME("Unimplemented msg DTM_GETRANGE\n");
454 FIXME("Unimplemented msg DTM_SETRANGE\n");
458 FIXME("Unimplemented msg DTM_SETFORMAT32A\n");
462 FIXME("Unimplemented msg DTM_SETFORMAT32W\n");
466 return DATETIME_SetMonthCalColor (hwnd
, wParam
, lParam
);
469 return DATETIME_GetMonthCalColor (hwnd
, wParam
);
471 case DTM_GETMONTHCAL
:
472 return DATETIME_GetMonthCal (hwnd
);
475 return DATETIME_SetMonthCalFont (hwnd
, wParam
, lParam
);
478 return DATETIME_GetMonthCalFont (hwnd
);
480 case WM_PARENTNOTIFY
:
481 return DATETIME_ParentNotify (hwnd
, wParam
, lParam
);
484 return DATETIME_Notify (hwnd
, wParam
, lParam
);
487 return DATETIME_Paint (hwnd
, wParam
);
490 return DATETIME_KillFocus (hwnd
, wParam
, lParam
);
493 return DATETIME_SetFocus (hwnd
, wParam
, lParam
);
496 return DATETIME_LButtonDown (hwnd
, wParam
, lParam
);
499 return DATETIME_Create (hwnd
, wParam
, lParam
);
502 return DATETIME_Destroy (hwnd
, wParam
, lParam
);
506 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
507 uMsg
, wParam
, lParam
);
508 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
515 DATETIME_Register (void)
519 if (GlobalFindAtomA (DATETIMEPICK_CLASSA
)) return;
521 ZeroMemory (&wndClass
, sizeof(WNDCLASSA
));
522 wndClass
.style
= CS_GLOBALCLASS
;
523 wndClass
.lpfnWndProc
= (WNDPROC
)DATETIME_WindowProc
;
524 wndClass
.cbClsExtra
= 0;
525 wndClass
.cbWndExtra
= sizeof(DATETIME_INFO
*);
526 wndClass
.hCursor
= LoadCursorA (0, IDC_ARROWA
);
527 wndClass
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
528 wndClass
.lpszClassName
= DATETIMEPICK_CLASSA
;
530 RegisterClassA (&wndClass
);
535 DATETIME_Unregister (void)
537 if (GlobalFindAtomA (DATETIMEPICK_CLASSA
))
538 UnregisterClassA (DATETIMEPICK_CLASSA
, (HINSTANCE
)NULL
);