| /* |
| * 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; |
| |
| |
| |
| 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); |
| } |
| |