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);