Fixed compiler warnings.
[wine.git] / dlls / comctl32 / datetime.c
blob2904d41f5f14a444a11d9fc957260cb46dce1570
1 /*
2 * Date and time picker control
4 * Copyright 1998, 1999 Eric Kohl
5 * Copyright 1999 Alex Priem <alexp@sci.kun.nl>
8 * TODO:
9 * - All messages.
10 * - All notifications.
14 #include "winbase.h"
15 #include "commctrl.h"
16 #include "datetime.h"
17 #include "monthcal.h"
18 #include "debugtools.h"
20 DEFAULT_DEBUG_CHANNEL(datetime)
24 #define DATETIME_GetInfoPtr(hwnd) ((DATETIME_INFO *)GetWindowLongA (hwnd, 0))
25 static BOOL
27 DATETIME_SendSimpleNotify (HWND hwnd, UINT code);
29 extern char *days[]; /* from ole/parsedt.c */
32 static LRESULT
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)))
43 return GDT_NONE;
45 MONTHCAL_CopyTime (&infoPtr->date, lprgSysTimeArray);
47 return GDT_VALID;
51 static LRESULT
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);
65 return 1;
69 static LRESULT
70 DATETIME_GetMonthCalColor (HWND hwnd, WPARAM wParam)
72 DATETIME_INFO *infoPtr = DATETIME_GetInfoPtr (hwnd);
74 return SendMessageA (infoPtr->hMonthCal, MCM_GETCOLOR, wParam, 0);
77 static LRESULT
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 */
88 static LRESULT
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 */
100 static LRESULT
101 DATETIME_GetMonthCalFont (HWND hwnd)
104 return 0;
107 static LRESULT
108 DATETIME_SetMonthCalFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
111 return 0;
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;
128 SIZE size;
129 BOOL prssed=FALSE;
130 COLORREF oldBk = 0;
134 if (infoPtr->dateValid) {
135 char txt[80];
136 HFONT oldFont;
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;
145 checkbox->left = 0;
146 checkbox->right = 0;
147 checkbox->top = rect->top;
148 checkbox->bottom= rect->bottom;
149 if (dwStyle & DTS_SHOWNONE) { /* FIXME: draw checkbox */
150 checkbox->right=18;
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) );
221 static LRESULT
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;
233 return 0;
236 static LRESULT
237 DATETIME_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
239 DATETIME_INFO *infoPtr = DATETIME_GetInfoPtr (hwnd);
240 POINT pt;
241 int old;
243 TRACE ("\n");
245 old=infoPtr->select;
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) {
251 HDC hdc;
253 SetFocus (hwnd);
254 hdc=GetDC (hwnd);
255 DATETIME_Refresh (hwnd,hdc);
256 ReleaseDC (hwnd, hdc);
258 if (infoPtr->select==DTHT_MCPOPUP) {
259 POINT pt;
261 pt.x=8;
262 pt.y=infoPtr->rect.bottom+5;
263 ClientToScreen (hwnd, &pt);
264 infoPtr->hMonthCal=CreateWindowExA (0,"SysMonthCal32", 0,
265 WS_POPUP | WS_BORDER,
266 pt.x,pt.y,145,150,
267 GetParent (hwnd),
268 0,0,0);
270 TRACE ("dt:%x mc:%x mc parent:%x, desktop:%x, mcpp:%x\n",
271 hwnd,infoPtr->hMonthCal,
272 GetParent (infoPtr->hMonthCal),
273 GetDesktopWindow (),
274 GetParent (GetParent (infoPtr->hMonthCal)));
276 SetFocus (hwnd);
277 DATETIME_SendSimpleNotify (hwnd, DTN_DROPDOWN);
279 return 0;
283 static LRESULT
284 DATETIME_Paint (HWND hwnd, WPARAM wParam)
286 HDC hdc;
287 PAINTSTRUCT ps;
289 hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
290 DATETIME_Refresh (hwnd, hdc);
291 if(!wParam)
292 EndPaint (hwnd, &ps);
293 return 0;
296 static LRESULT
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);
305 return 0;
308 static LRESULT
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);
318 return 0;
321 static LRESULT
322 DATETIME_KillFocus (HWND hwnd, WPARAM wParam, LPARAM lParam)
324 DATETIME_INFO *infoPtr = DATETIME_GetInfoPtr (hwnd);
325 HDC hdc;
327 TRACE ("\n");
329 if (infoPtr->select) {
330 DATETIME_SendSimpleNotify (hwnd, NM_KILLFOCUS);
331 infoPtr->select&= ~DTHT_GOTFOCUS;
333 hdc = GetDC (hwnd);
334 DATETIME_Refresh (hwnd, hdc);
335 ReleaseDC (hwnd, hdc);
336 InvalidateRect (hwnd, NULL, TRUE);
338 return 0;
342 static LRESULT
343 DATETIME_SetFocus (HWND hwnd, WPARAM wParam, LPARAM lParam)
345 HDC hdc;
346 DATETIME_INFO *infoPtr = DATETIME_GetInfoPtr (hwnd);
348 TRACE ("\n");
350 if (infoPtr->select) {
351 DATETIME_SendSimpleNotify (hwnd, NM_SETFOCUS);
352 infoPtr->select|=DTHT_GOTFOCUS;
354 hdc = GetDC (hwnd);
355 DATETIME_Refresh (hwnd, hdc);
356 ReleaseDC (hwnd, hdc);
358 return 0;
362 static BOOL
363 DATETIME_SendSimpleNotify (HWND hwnd, UINT code)
365 NMHDR nmhdr;
367 TRACE("%x\n",code);
368 nmhdr.hwndFrom = hwnd;
369 nmhdr.idFrom = GetWindowLongA( hwnd, GWL_ID);
370 nmhdr.code = code;
372 return (BOOL) SendMessageA (GetParent (hwnd), WM_NOTIFY,
373 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
381 static LRESULT
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");
391 return 0;
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,
399 2,2,13,13,
400 hwnd,
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,
409 120,1,20,20,
410 hwnd,1,0,0,
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);
419 return 0;
423 static LRESULT
424 DATETIME_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
426 DATETIME_INFO *infoPtr = DATETIME_GetInfoPtr (hwnd);
428 COMCTL32_Free (infoPtr);
429 return 0;
436 static LRESULT WINAPI
437 DATETIME_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
440 switch (uMsg)
443 case DTM_GETSYSTEMTIME:
444 DATETIME_GetSystemTime (hwnd, wParam, lParam);
446 case DTM_SETSYSTEMTIME:
447 DATETIME_SetSystemTime (hwnd, wParam, lParam);
449 case DTM_GETRANGE:
450 FIXME("Unimplemented msg DTM_GETRANGE\n");
451 return 0;
453 case DTM_SETRANGE:
454 FIXME("Unimplemented msg DTM_SETRANGE\n");
455 return 1;
457 case DTM_SETFORMATA:
458 FIXME("Unimplemented msg DTM_SETFORMAT32A\n");
459 return 1;
461 case DTM_SETFORMATW:
462 FIXME("Unimplemented msg DTM_SETFORMAT32W\n");
463 return 1;
465 case DTM_SETMCCOLOR:
466 return DATETIME_SetMonthCalColor (hwnd, wParam, lParam);
468 case DTM_GETMCCOLOR:
469 return DATETIME_GetMonthCalColor (hwnd, wParam);
471 case DTM_GETMONTHCAL:
472 return DATETIME_GetMonthCal (hwnd);
474 case DTM_SETMCFONT:
475 return DATETIME_SetMonthCalFont (hwnd, wParam, lParam);
477 case DTM_GETMCFONT:
478 return DATETIME_GetMonthCalFont (hwnd);
480 case WM_PARENTNOTIFY:
481 return DATETIME_ParentNotify (hwnd, wParam, lParam);
483 case WM_NOTIFY:
484 return DATETIME_Notify (hwnd, wParam, lParam);
486 case WM_PAINT:
487 return DATETIME_Paint (hwnd, wParam);
489 case WM_KILLFOCUS:
490 return DATETIME_KillFocus (hwnd, wParam, lParam);
492 case WM_SETFOCUS:
493 return DATETIME_SetFocus (hwnd, wParam, lParam);
495 case WM_LBUTTONDOWN:
496 return DATETIME_LButtonDown (hwnd, wParam, lParam);
498 case WM_CREATE:
499 return DATETIME_Create (hwnd, wParam, lParam);
501 case WM_DESTROY:
502 return DATETIME_Destroy (hwnd, wParam, lParam);
504 default:
505 if (uMsg >= WM_USER)
506 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
507 uMsg, wParam, lParam);
508 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
510 return 0;
514 VOID
515 DATETIME_Register (void)
517 WNDCLASSA wndClass;
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);
534 VOID
535 DATETIME_Unregister (void)
537 if (GlobalFindAtomA (DATETIMEPICK_CLASSA))
538 UnregisterClassA (DATETIMEPICK_CLASSA, (HINSTANCE)NULL);