| /* | |
| * Date and time picker control | |
| * | |
| * Copyright 1998, 1999 Eric Kohl | |
| * Copyright 1999 Alex Priem <alexp@sci.kun.nl> | |
| * | |
| * | |
| * TODO: | |
| * - All messages. | |
| * - All notifications. | |
| * | |
| */ | |
| #include "winbase.h" | |
| #include "commctrl.h" | |
| #include "datetime.h" | |
| #include "monthcal.h" | |
| #include "debugtools.h" | |
| DEFAULT_DEBUG_CHANNEL(datetime) | |
| #define DATETIME_GetInfoPtr(hwnd) ((DATETIME_INFO *)GetWindowLongA (hwnd, 0)) | |
| static BOOL | |
| DATETIME_SendSimpleNotify (HWND hwnd, UINT code); | |
| extern char *days[]; /* from ole/parsedt.c */ | |
| static LRESULT | |
| DATETIME_GetSystemTime (HWND hwnd, WPARAM wParam, LPARAM lParam ) | |
| { | |
| DATETIME_INFO *infoPtr = DATETIME_GetInfoPtr (hwnd); | |
| DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE); | |
| SYSTEMTIME *lprgSysTimeArray=(SYSTEMTIME *) lParam; | |
| if (!lParam) return GDT_NONE; | |
| if ((dwStyle & DTS_SHOWNONE) && | |
| (SendMessageA (infoPtr->hwndCheckbut, BM_GETCHECK, 0, 0))) | |
| return GDT_NONE; | |
| MONTHCAL_CopyTime (&infoPtr->date, lprgSysTimeArray); | |
| return GDT_VALID; | |
| } | |
| static LRESULT | |
| DATETIME_SetSystemTime (HWND hwnd, WPARAM wParam, LPARAM lParam ) | |
| { | |
| DATETIME_INFO *infoPtr = DATETIME_GetInfoPtr (hwnd); | |
| SYSTEMTIME *lprgSysTimeArray=(SYSTEMTIME *) lParam; | |
| if (!lParam) return 0; | |
| if (lParam==GDT_VALID) | |
| MONTHCAL_CopyTime (lprgSysTimeArray, &infoPtr->date); | |
| if (lParam==GDT_NONE) { | |
| infoPtr->dateValid=FALSE; | |
| SendMessageA (infoPtr->hwndCheckbut, BM_SETCHECK, 0, 0); | |
| } | |
| return 1; | |
| } | |
| static LRESULT | |
| DATETIME_GetMonthCalColor (HWND hwnd, WPARAM wParam) | |
| { | |
| DATETIME_INFO *infoPtr = DATETIME_GetInfoPtr (hwnd); | |
| return SendMessageA (infoPtr->hMonthCal, MCM_GETCOLOR, wParam, 0); | |
| } | |
| static LRESULT | |
| DATETIME_SetMonthCalColor (HWND hwnd, WPARAM wParam, LPARAM lParam) | |
| { | |
| DATETIME_INFO *infoPtr = DATETIME_GetInfoPtr (hwnd); | |
| return SendMessageA (infoPtr->hMonthCal, MCM_SETCOLOR, wParam, lParam); | |
| } | |
| /* FIXME: need to get way to force font into monthcal structure */ | |
| static LRESULT | |
| DATETIME_GetMonthCal (HWND hwnd) | |
| { | |
| DATETIME_INFO *infoPtr = DATETIME_GetInfoPtr (hwnd); | |
| return infoPtr->hMonthCal; | |
| } | |
| /* FIXME: need to get way to force font into monthcal structure */ | |
| static LRESULT | |
| DATETIME_GetMonthCalFont (HWND hwnd) | |
| { | |
| return 0; | |
| } | |
| static LRESULT | |
| DATETIME_SetMonthCalFont (HWND hwnd, WPARAM wParam, LPARAM lParam) | |
| { | |
| return 0; | |
| } | |
| static void DATETIME_Refresh (HWND hwnd, HDC hdc) | |
| { | |
| DATETIME_INFO *infoPtr = DATETIME_GetInfoPtr (hwnd); | |
| RECT *daytxt = &infoPtr->daytxt; | |
| RECT *daynumtxt= &infoPtr->daynumtxt; | |
| RECT *rmonthtxt= &infoPtr->rmonthtxt; | |
| RECT *yeartxt = &infoPtr->yeartxt; | |
| RECT *calbutton= &infoPtr->calbutton; | |
| RECT *checkbox = &infoPtr->checkbox; | |
| RECT *rect = &infoPtr->rect; | |
| DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE); | |
| SYSTEMTIME date = infoPtr->date; | |
| SIZE size; | |
| BOOL prssed=FALSE; | |
| COLORREF oldBk = 0; | |
| if (infoPtr->dateValid) { | |
| char txt[80]; | |
| HFONT oldFont; | |
| oldFont = SelectObject (hdc, infoPtr->hFont); | |
| GetClientRect (hwnd, rect); | |
| sprintf (txt,"%s,",days[date.wDayOfWeek]); | |
| GetTextExtentPoint32A (hdc, txt, strlen (txt), &size); | |
| rect->bottom=size.cy+2; | |
| checkbox->left = 0; | |
| checkbox->right = 0; | |
| checkbox->top = rect->top; | |
| checkbox->bottom= rect->bottom; | |
| if (dwStyle & DTS_SHOWNONE) { /* FIXME: draw checkbox */ | |
| checkbox->right=18; | |
| } | |
| if (infoPtr->select==(DTHT_DAY|DTHT_GOTFOCUS)) | |
| oldBk=SetBkColor (hdc, COLOR_GRAYTEXT); | |
| daytxt->left = checkbox->right; | |
| daytxt->right = checkbox->right+size.cx; | |
| daytxt->top = rect->top; | |
| daytxt->bottom= rect->bottom; | |
| DrawTextA ( hdc, txt, strlen(txt), daytxt, | |
| DT_LEFT | DT_VCENTER | DT_SINGLELINE ); | |
| if (infoPtr->select==(DTHT_DAY|DTHT_GOTFOCUS)) | |
| SetBkColor (hdc, oldBk); | |
| if (infoPtr->select==(DTHT_MONTH|DTHT_GOTFOCUS)) | |
| oldBk=SetBkColor (hdc, COLOR_GRAYTEXT); | |
| strcpy (txt, monthtxt[date.wMonth]); | |
| GetTextExtentPoint32A (hdc, "September", 9, &size); | |
| rmonthtxt->left = daytxt->right; | |
| rmonthtxt->right = daytxt->right+size.cx; | |
| rmonthtxt->top = rect->top; | |
| rmonthtxt->bottom= rect->bottom; | |
| DrawTextA ( hdc, txt, strlen(txt), rmonthtxt, | |
| DT_CENTER | DT_VCENTER | DT_SINGLELINE ); | |
| if (infoPtr->select==(DTHT_MONTH|DTHT_GOTFOCUS)) | |
| SetBkColor (hdc, oldBk); | |
| if (infoPtr->select==(DTHT_DAYNUM|DTHT_GOTFOCUS)) | |
| oldBk=SetBkColor (hdc, COLOR_GRAYTEXT); | |
| sprintf (txt,"%d,",date.wDay); | |
| GetTextExtentPoint32A (hdc, "31,", 3, &size); | |
| daynumtxt->left = rmonthtxt->right; | |
| daynumtxt->right = rmonthtxt->right+size.cx; | |
| daynumtxt->top = rect->top; | |
| daynumtxt->bottom= rect->bottom; | |
| DrawTextA ( hdc, txt, strlen(txt), daynumtxt, | |
| DT_RIGHT | DT_VCENTER | DT_SINGLELINE ); | |
| if (infoPtr->select==(DTHT_DAYNUM|DTHT_GOTFOCUS)) | |
| SetBkColor (hdc, oldBk); | |
| if (infoPtr->select==(DTHT_YEAR|DTHT_GOTFOCUS)) | |
| oldBk=SetBkColor (hdc, COLOR_GRAYTEXT); | |
| sprintf (txt,"%d",date.wYear); | |
| GetTextExtentPoint32A (hdc, "2000", 5, &size); | |
| yeartxt->left = daynumtxt->right; | |
| yeartxt->right = daynumtxt->right+size.cx; | |
| yeartxt->top = rect->top; | |
| yeartxt->bottom= rect->bottom; | |
| DrawTextA ( hdc, txt, strlen(txt), yeartxt, | |
| DT_RIGHT | DT_VCENTER | DT_SINGLELINE ); | |
| if (infoPtr->select==(DTHT_YEAR|DTHT_GOTFOCUS)) | |
| SetBkColor (hdc, oldBk); | |
| SelectObject (hdc, oldFont); | |
| } | |
| if (!(dwStyle & DTS_UPDOWN)) { | |
| calbutton->right = rect->right; | |
| calbutton->left = rect->right-15; | |
| calbutton->top = rect->top; | |
| calbutton->bottom= rect->bottom; | |
| DrawFrameControl(hdc, calbutton, DFC_SCROLL, | |
| DFCS_SCROLLDOWN | (prssed ? DFCS_PUSHED : 0) | | |
| (dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) ); | |
| } | |
| } | |
| static LRESULT | |
| DATETIME_HitTest (HWND hwnd, DATETIME_INFO *infoPtr, POINT pt) | |
| { | |
| TRACE ("%ld, %ld\n",pt.x,pt.y); | |
| if (PtInRect (&infoPtr->calbutton, pt)) return DTHT_MCPOPUP; | |
| if (PtInRect (&infoPtr->yeartxt, pt)) return DTHT_YEAR; | |
| if (PtInRect (&infoPtr->daynumtxt, pt)) return DTHT_DAYNUM; | |
| if (PtInRect (&infoPtr->rmonthtxt, pt)) return DTHT_MONTH; | |
| if (PtInRect (&infoPtr->daytxt, pt)) return DTHT_DAY; | |
| if (PtInRect (&infoPtr->checkbox, pt)) return DTHT_CHECKBOX; | |
| return 0; | |
| } | |
| static LRESULT | |
| DATETIME_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam) | |
| { | |
| DATETIME_INFO *infoPtr = DATETIME_GetInfoPtr (hwnd); | |
| POINT pt; | |
| int old; | |
| TRACE ("\n"); | |
| old=infoPtr->select; | |
| pt.x=(INT)LOWORD(lParam); | |
| pt.y=(INT)HIWORD(lParam); | |
| infoPtr->select=DATETIME_HitTest (hwnd, infoPtr, pt); | |
| if (infoPtr->select!=old) { | |
| HDC hdc; | |
| SetFocus (hwnd); | |
| hdc=GetDC (hwnd); | |
| DATETIME_Refresh (hwnd,hdc); | |
| ReleaseDC (hwnd, hdc); | |
| } | |
| if (infoPtr->select==DTHT_MCPOPUP) { | |
| POINT pt; | |
| pt.x=8; | |
| pt.y=infoPtr->rect.bottom+5; | |
| ClientToScreen (hwnd, &pt); | |
| infoPtr->hMonthCal=CreateWindowExA (0,"SysMonthCal32", 0, | |
| WS_POPUP | WS_BORDER, | |
| pt.x,pt.y,145,150, | |
| GetParent (hwnd), | |
| 0,0,0); | |
| TRACE ("dt:%x mc:%x mc parent:%x, desktop:%x, mcpp:%x\n", | |
| hwnd,infoPtr->hMonthCal, | |
| GetParent (infoPtr->hMonthCal), | |
| GetDesktopWindow (), | |
| GetParent (GetParent (infoPtr->hMonthCal))); | |
| SetFocus (hwnd); | |
| DATETIME_SendSimpleNotify (hwnd, DTN_DROPDOWN); | |
| } | |
| return 0; | |
| } | |
| static LRESULT | |
| DATETIME_Paint (HWND hwnd, WPARAM wParam) | |
| { | |
| HDC hdc; | |
| PAINTSTRUCT ps; | |
| hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam; | |
| DATETIME_Refresh (hwnd, hdc); | |
| if(!wParam) | |
| EndPaint (hwnd, &ps); | |
| return 0; | |
| } | |
| static LRESULT | |
| DATETIME_ParentNotify (HWND hwnd, WPARAM wParam, LPARAM lParam) | |
| { | |
| DATETIME_INFO *infoPtr = DATETIME_GetInfoPtr (hwnd); | |
| LPNMHDR lpnmh=(LPNMHDR) lParam; | |
| TRACE ("%x,%lx\n",wParam, lParam); | |
| TRACE ("Got notification %x from %x\n", lpnmh->code, lpnmh->hwndFrom); | |
| TRACE ("info: %x %x %x\n",hwnd,infoPtr->hMonthCal,infoPtr->hUpdown); | |
| return 0; | |
| } | |
| static LRESULT | |
| DATETIME_Notify (HWND hwnd, WPARAM wParam, LPARAM lParam) | |
| { | |
| DATETIME_INFO *infoPtr = DATETIME_GetInfoPtr (hwnd); | |
| LPNMHDR lpnmh=(LPNMHDR) lParam; | |
| TRACE ("%x,%lx\n",wParam, lParam); | |
| TRACE ("Got notification %x from %x\n", lpnmh->code, lpnmh->hwndFrom); | |
| TRACE ("info: %x %x %x\n",hwnd,infoPtr->hMonthCal,infoPtr->hUpdown); | |
| return 0; | |
| } | |
| static LRESULT | |
| DATETIME_KillFocus (HWND hwnd, WPARAM wParam, LPARAM lParam) | |
| { | |
| DATETIME_INFO *infoPtr = DATETIME_GetInfoPtr (hwnd); | |
| HDC hdc; | |
| TRACE ("\n"); | |
| if (infoPtr->select) { | |
| DATETIME_SendSimpleNotify (hwnd, NM_KILLFOCUS); | |
| infoPtr->select&= ~DTHT_GOTFOCUS; | |
| } | |
| hdc = GetDC (hwnd); | |
| DATETIME_Refresh (hwnd, hdc); | |
| ReleaseDC (hwnd, hdc); | |
| InvalidateRect (hwnd, NULL, TRUE); | |
| return 0; | |
| } | |
| static LRESULT | |
| DATETIME_SetFocus (HWND hwnd, WPARAM wParam, LPARAM lParam) | |
| { | |
| HDC hdc; | |
| DATETIME_INFO *infoPtr = DATETIME_GetInfoPtr (hwnd); | |
| TRACE ("\n"); | |
| if (infoPtr->select) { | |
| DATETIME_SendSimpleNotify (hwnd, NM_SETFOCUS); | |
| infoPtr->select|=DTHT_GOTFOCUS; | |
| } | |
| hdc = GetDC (hwnd); | |
| DATETIME_Refresh (hwnd, hdc); | |
| ReleaseDC (hwnd, hdc); | |
| return 0; | |
| } | |
| static BOOL | |
| DATETIME_SendSimpleNotify (HWND hwnd, UINT code) | |
| { | |
| NMHDR nmhdr; | |
| TRACE("%x\n",code); | |
| nmhdr.hwndFrom = hwnd; | |
| nmhdr.idFrom = GetWindowLongA( hwnd, GWL_ID); | |
| nmhdr.code = code; | |
| return (BOOL) SendMessageA (GetParent (hwnd), WM_NOTIFY, | |
| (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr); | |
| } | |
| static LRESULT | |
| DATETIME_Create (HWND hwnd, WPARAM wParam, LPARAM lParam) | |
| { | |
| DATETIME_INFO *infoPtr; | |
| DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE); | |
| /* allocate memory for info structure */ | |
| infoPtr = (DATETIME_INFO *)COMCTL32_Alloc (sizeof(DATETIME_INFO)); | |
| if (infoPtr == NULL) { | |
| ERR("could not allocate info memory!\n"); | |
| return 0; | |
| } | |
| SetWindowLongA (hwnd, 0, (DWORD)infoPtr); | |
| if (dwStyle & DTS_SHOWNONE) { | |
| infoPtr->hwndCheckbut=CreateWindowExA (0,"button", 0, | |
| WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, | |
| 2,2,13,13, | |
| hwnd, | |
| 0, GetWindowLongA (hwnd, GWL_HINSTANCE), 0); | |
| SendMessageA (infoPtr->hwndCheckbut, BM_SETCHECK, 1, 0); | |
| } | |
| if (dwStyle & DTS_UPDOWN) { | |
| infoPtr->hUpdown=CreateUpDownControl ( | |
| WS_CHILD | WS_BORDER | WS_VISIBLE, | |
| 120,1,20,20, | |
| hwnd,1,0,0, | |
| UD_MAXVAL, UD_MINVAL, 0); | |
| } | |
| /* initialize info structure */ | |
| infoPtr->hMonthCal=0; | |
| GetSystemTime (&infoPtr->date); | |
| infoPtr->dateValid = TRUE; | |
| infoPtr->hFont = GetStockObject(DEFAULT_GUI_FONT); | |
| return 0; | |
| } | |
| static LRESULT | |
| DATETIME_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam) | |
| { | |
| DATETIME_INFO *infoPtr = DATETIME_GetInfoPtr (hwnd); | |
| COMCTL32_Free (infoPtr); | |
| return 0; | |
| } | |
| static LRESULT WINAPI | |
| DATETIME_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) | |
| { | |
| switch (uMsg) | |
| { | |
| case DTM_GETSYSTEMTIME: | |
| DATETIME_GetSystemTime (hwnd, wParam, lParam); | |
| case DTM_SETSYSTEMTIME: | |
| DATETIME_SetSystemTime (hwnd, wParam, lParam); | |
| case DTM_GETRANGE: | |
| FIXME("Unimplemented msg DTM_GETRANGE\n"); | |
| return 0; | |
| case DTM_SETRANGE: | |
| FIXME("Unimplemented msg DTM_SETRANGE\n"); | |
| return 1; | |
| case DTM_SETFORMATA: | |
| FIXME("Unimplemented msg DTM_SETFORMAT32A\n"); | |
| return 1; | |
| case DTM_SETFORMATW: | |
| FIXME("Unimplemented msg DTM_SETFORMAT32W\n"); | |
| return 1; | |
| case DTM_SETMCCOLOR: | |
| return DATETIME_SetMonthCalColor (hwnd, wParam, lParam); | |
| case DTM_GETMCCOLOR: | |
| return DATETIME_GetMonthCalColor (hwnd, wParam); | |
| case DTM_GETMONTHCAL: | |
| return DATETIME_GetMonthCal (hwnd); | |
| case DTM_SETMCFONT: | |
| return DATETIME_SetMonthCalFont (hwnd, wParam, lParam); | |
| case DTM_GETMCFONT: | |
| return DATETIME_GetMonthCalFont (hwnd); | |
| case WM_PARENTNOTIFY: | |
| return DATETIME_ParentNotify (hwnd, wParam, lParam); | |
| case WM_NOTIFY: | |
| return DATETIME_Notify (hwnd, wParam, lParam); | |
| case WM_PAINT: | |
| return DATETIME_Paint (hwnd, wParam); | |
| case WM_KILLFOCUS: | |
| return DATETIME_KillFocus (hwnd, wParam, lParam); | |
| case WM_SETFOCUS: | |
| return DATETIME_SetFocus (hwnd, wParam, lParam); | |
| case WM_LBUTTONDOWN: | |
| return DATETIME_LButtonDown (hwnd, wParam, lParam); | |
| case WM_CREATE: | |
| return DATETIME_Create (hwnd, wParam, lParam); | |
| case WM_DESTROY: | |
| return DATETIME_Destroy (hwnd, wParam, lParam); | |
| default: | |
| if (uMsg >= WM_USER) | |
| ERR("unknown msg %04x wp=%08x lp=%08lx\n", | |
| uMsg, wParam, lParam); | |
| return DefWindowProcA (hwnd, uMsg, wParam, lParam); | |
| } | |
| return 0; | |
| } | |
| VOID | |
| DATETIME_Register (void) | |
| { | |
| WNDCLASSA wndClass; | |
| if (GlobalFindAtomA (DATETIMEPICK_CLASSA)) return; | |
| ZeroMemory (&wndClass, sizeof(WNDCLASSA)); | |
| wndClass.style = CS_GLOBALCLASS; | |
| wndClass.lpfnWndProc = (WNDPROC)DATETIME_WindowProc; | |
| wndClass.cbClsExtra = 0; | |
| wndClass.cbWndExtra = sizeof(DATETIME_INFO *); | |
| wndClass.hCursor = LoadCursorA (0, IDC_ARROWA); | |
| wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); | |
| wndClass.lpszClassName = DATETIMEPICK_CLASSA; | |
| RegisterClassA (&wndClass); | |
| } | |
| VOID | |
| DATETIME_Unregister (void) | |
| { | |
| if (GlobalFindAtomA (DATETIMEPICK_CLASSA)) | |
| UnregisterClassA (DATETIMEPICK_CLASSA, (HINSTANCE)NULL); | |
| } | |