Monday is day number '1'.
Set day of week when a day is selected in the calender. Use fixed width fields in datetime. DTS_TIMEFORMAT is a two bit field, so test accordingly. Reposition and resize the updown control when the datetime control is resized. Respond to updown inputs.
This commit is contained in:
parent
44d2da9f5d
commit
a6659d26d2
|
@ -82,6 +82,7 @@ typedef struct
|
|||
int *buflen;
|
||||
WCHAR textbuf[256];
|
||||
POINT monthcal_pos;
|
||||
int pendingUpdown;
|
||||
} DATETIME_INFO, *LPDATETIME_INFO;
|
||||
|
||||
/* in monthcal.c */
|
||||
|
@ -256,7 +257,7 @@ DATETIME_SetFormatW (DATETIME_INFO *infoPtr, LPCWSTR lpszFormat)
|
|||
|
||||
if (infoPtr->dwStyle & DTS_LONGDATEFORMAT)
|
||||
format_item = LOCALE_SLONGDATE;
|
||||
else if (infoPtr->dwStyle & DTS_TIMEFORMAT)
|
||||
else if ((infoPtr->dwStyle & DTS_TIMEFORMAT) == DTS_TIMEFORMAT)
|
||||
format_item = LOCALE_STIMEFORMAT;
|
||||
else /* DTS_SHORTDATEFORMAT */
|
||||
format_item = LOCALE_SSHORTDATE;
|
||||
|
@ -405,6 +406,19 @@ DATETIME_ReturnTxt (DATETIME_INFO *infoPtr, int count, LPWSTR result, int result
|
|||
TRACE ("arg%d=%x->[%s]\n", count, infoPtr->fieldspec[count], debugstr_w(result));
|
||||
}
|
||||
|
||||
/* Offsets of days in the week to the weekday of january 1 in a leap year. */
|
||||
static const int DayOfWeekTable[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
|
||||
|
||||
/* returns the day in the week(0 == sunday, 6 == saturday) */
|
||||
/* day(1 == 1st, 2 == 2nd... etc), year is the year value */
|
||||
static int DATETIME_CalculateDayOfWeek(DWORD day, DWORD month, DWORD year)
|
||||
{
|
||||
year-=(month < 3);
|
||||
|
||||
return((year + year/4 - year/100 + year/400 +
|
||||
DayOfWeekTable[month-1] + day ) % 7);
|
||||
}
|
||||
|
||||
static int wrap(int val, int delta, int minVal, int maxVal)
|
||||
{
|
||||
val += delta;
|
||||
|
@ -428,12 +442,14 @@ DATETIME_IncreaseField (DATETIME_INFO *infoPtr, int number, int delta)
|
|||
case TWODIGITYEAR:
|
||||
case FULLYEAR:
|
||||
date->wYear = wrap(date->wYear, delta, 1752, 9999);
|
||||
date->wDayOfWeek = DATETIME_CalculateDayOfWeek(date->wDay,date->wMonth,date->wYear);
|
||||
break;
|
||||
case ONEDIGITMONTH:
|
||||
case TWODIGITMONTH:
|
||||
case THREECHARMONTH:
|
||||
case FULLMONTH:
|
||||
date->wMonth = wrap(date->wMonth, delta, 1, 12);
|
||||
date->wDayOfWeek = DATETIME_CalculateDayOfWeek(date->wDay,date->wMonth,date->wYear);
|
||||
delta = 0;
|
||||
/* fall through */
|
||||
case ONEDIGITDAY:
|
||||
|
@ -441,6 +457,7 @@ DATETIME_IncreaseField (DATETIME_INFO *infoPtr, int number, int delta)
|
|||
case THREECHARDAY:
|
||||
case FULLDAY:
|
||||
date->wDay = wrap(date->wDay, delta, 1, MONTHCAL_MonthLength(date->wMonth, date->wYear));
|
||||
date->wDayOfWeek = DATETIME_CalculateDayOfWeek(date->wDay,date->wMonth,date->wYear);
|
||||
break;
|
||||
case ONELETTERAMPM:
|
||||
case TWOLETTERAMPM:
|
||||
|
@ -481,6 +498,92 @@ DATETIME_IncreaseField (DATETIME_INFO *infoPtr, int number, int delta)
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
DATETIME_ReturnFieldWidth (DATETIME_INFO *infoPtr, HDC hdc, int count, SHORT *fieldWidthPtr)
|
||||
{
|
||||
/* fields are a fixed width, determined by the largest possible string */
|
||||
/* presumably, these widths should be language dependent */
|
||||
static const WCHAR fld_d1W[] = { '2', 0 };
|
||||
static const WCHAR fld_d2W[] = { '2', '2', 0 };
|
||||
static const WCHAR fld_d4W[] = { '2', '2', '2', '2', 0 };
|
||||
static const WCHAR fld_am1[] = { 'A', 0 };
|
||||
static const WCHAR fld_am2[] = { 'A', 'M', 0 };
|
||||
static const WCHAR fld_day[] = { 'W', 'e', 'd', 'n', 'e', 's', 'd', 'a', 'y', 0 };
|
||||
static const WCHAR fld_day3[] = { 'W', 'e', 'd', 0 };
|
||||
static const WCHAR fld_mon[] = { 'S', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 };
|
||||
static const WCHAR fld_mon3[] = { 'D', 'e', 'c', 0 };
|
||||
int spec;
|
||||
WCHAR buffer[80], *bufptr;
|
||||
SIZE size;
|
||||
|
||||
TRACE ("%d,%d\n", infoPtr->nrFields, count);
|
||||
if (count>infoPtr->nrFields || count < 0) {
|
||||
WARN ("buffer overrun, have %d want %d\n", infoPtr->nrFields, count);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!infoPtr->fieldspec) return;
|
||||
|
||||
spec = infoPtr->fieldspec[count];
|
||||
if (spec & DT_STRING) {
|
||||
int txtlen = infoPtr->buflen[count];
|
||||
|
||||
if (txtlen > 79)
|
||||
txtlen = 79;
|
||||
memcpy (buffer, infoPtr->textbuf + (spec &~ DT_STRING), txtlen * sizeof(WCHAR));
|
||||
buffer[txtlen] = 0;
|
||||
bufptr = buffer;
|
||||
}
|
||||
else {
|
||||
switch (spec) {
|
||||
case ONEDIGITDAY:
|
||||
case ONEDIGIT12HOUR:
|
||||
case ONEDIGIT24HOUR:
|
||||
case ONEDIGITSECOND:
|
||||
case ONEDIGITMINUTE:
|
||||
case ONEDIGITMONTH:
|
||||
case ONEDIGITYEAR:
|
||||
/* these seem to use a two byte field */
|
||||
case TWODIGITDAY:
|
||||
case TWODIGIT12HOUR:
|
||||
case TWODIGIT24HOUR:
|
||||
case TWODIGITSECOND:
|
||||
case TWODIGITMINUTE:
|
||||
case TWODIGITMONTH:
|
||||
case TWODIGITYEAR:
|
||||
bufptr = (WCHAR *)fld_d2W;
|
||||
break;
|
||||
case INVALIDFULLYEAR:
|
||||
case FULLYEAR:
|
||||
bufptr = (WCHAR *)fld_d4W;
|
||||
break;
|
||||
case THREECHARDAY:
|
||||
bufptr = (WCHAR *)fld_day3;
|
||||
break;
|
||||
case FULLDAY:
|
||||
bufptr = (WCHAR *)fld_day;
|
||||
break;
|
||||
case THREECHARMONTH:
|
||||
bufptr = (WCHAR *)fld_mon3;
|
||||
break;
|
||||
case FULLMONTH:
|
||||
bufptr = (WCHAR *)fld_mon;
|
||||
break;
|
||||
case ONELETTERAMPM:
|
||||
bufptr = (WCHAR *)fld_am1;
|
||||
break;
|
||||
case TWOLETTERAMPM:
|
||||
bufptr = (WCHAR *)fld_am2;
|
||||
break;
|
||||
default:
|
||||
bufptr = (WCHAR *)fld_d1W;
|
||||
break;
|
||||
}
|
||||
}
|
||||
GetTextExtentPoint32W (hdc, bufptr, strlenW(bufptr), &size);
|
||||
*fieldWidthPtr = size.cx;
|
||||
}
|
||||
|
||||
static void
|
||||
DATETIME_Refresh (DATETIME_INFO *infoPtr, HDC hdc)
|
||||
{
|
||||
|
@ -491,6 +594,7 @@ DATETIME_Refresh (DATETIME_INFO *infoPtr, HDC hdc)
|
|||
RECT *checkbox = &infoPtr->checkbox;
|
||||
SIZE size;
|
||||
COLORREF oldTextColor;
|
||||
SHORT fieldWidth;
|
||||
|
||||
/* draw control edge */
|
||||
TRACE("\n");
|
||||
|
@ -509,9 +613,10 @@ DATETIME_Refresh (DATETIME_INFO *infoPtr, HDC hdc)
|
|||
for (i = 0; i < infoPtr->nrFields; i++) {
|
||||
DATETIME_ReturnTxt (infoPtr, i, txt, sizeof(txt)/sizeof(txt[0]));
|
||||
GetTextExtentPoint32W (hdc, txt, strlenW(txt), &size);
|
||||
DATETIME_ReturnFieldWidth (infoPtr, hdc, i, &fieldWidth);
|
||||
field = &infoPtr->fieldRect[i];
|
||||
field->left = prevright;
|
||||
field->right = prevright+size.cx;
|
||||
field->right = prevright + fieldWidth;
|
||||
field->top = rcDraw->top;
|
||||
field->bottom = rcDraw->bottom;
|
||||
prevright = field->right;
|
||||
|
@ -720,12 +825,17 @@ DATETIME_Notify (DATETIME_INFO *infoPtr, int idCtrl, LPNMHDR lpnmh)
|
|||
ShowWindow(infoPtr->hMonthCal, SW_HIDE);
|
||||
infoPtr->dateValid = TRUE;
|
||||
SendMessageW (infoPtr->hMonthCal, MCM_GETCURSEL, 0, (LPARAM)&infoPtr->date);
|
||||
TRACE("got from calendar %04d/%02d/%02d\n",
|
||||
infoPtr->date.wYear, infoPtr->date.wMonth, infoPtr->date.wDay);
|
||||
TRACE("got from calendar %04d/%02d/%02d day of week %d\n",
|
||||
infoPtr->date.wYear, infoPtr->date.wMonth, infoPtr->date.wDay, infoPtr->date.wDayOfWeek);
|
||||
SendMessageW (infoPtr->hwndCheckbut, BM_SETCHECK, BST_CHECKED, 0);
|
||||
InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
|
||||
DATETIME_SendDateTimeChangeNotify (infoPtr);
|
||||
}
|
||||
if ((lpnmh->hwndFrom == infoPtr->hUpdown) && (lpnmh->code == UDN_DELTAPOS)) {
|
||||
LPNMUPDOWN lpnmud = (LPNMUPDOWN)lpnmh;
|
||||
TRACE("Delta pos %d\n", lpnmud->iDelta);
|
||||
infoPtr->pendingUpdown = lpnmud->iDelta;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -789,6 +899,30 @@ DATETIME_KeyDown (DATETIME_INFO *infoPtr, DWORD vkCode, LPARAM flags)
|
|||
}
|
||||
|
||||
|
||||
static LRESULT
|
||||
DATETIME_VScroll (DATETIME_INFO *infoPtr, WORD wScroll)
|
||||
{
|
||||
int fieldNum = infoPtr->select & DTHT_DATEFIELD;
|
||||
|
||||
if ((SHORT)LOWORD(wScroll) != SB_THUMBPOSITION) return 0;
|
||||
if (!(infoPtr->haveFocus)) return 0;
|
||||
if ((fieldNum==0) && (infoPtr->select)) return 0;
|
||||
|
||||
if (infoPtr->pendingUpdown >= 0) {
|
||||
DATETIME_IncreaseField (infoPtr, fieldNum, 1);
|
||||
DATETIME_SendDateTimeChangeNotify (infoPtr);
|
||||
}
|
||||
else {
|
||||
DATETIME_IncreaseField (infoPtr, fieldNum, -1);
|
||||
DATETIME_SendDateTimeChangeNotify (infoPtr);
|
||||
}
|
||||
|
||||
InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static LRESULT
|
||||
DATETIME_KillFocus (DATETIME_INFO *infoPtr, HWND lostFocus)
|
||||
{
|
||||
|
@ -875,12 +1009,22 @@ DATETIME_Size (DATETIME_INFO *infoPtr, WORD flags, INT width, INT height)
|
|||
|
||||
infoPtr->rcDraw = infoPtr->rcClient;
|
||||
|
||||
if (infoPtr->dwStyle & DTS_UPDOWN) {
|
||||
/* the updown control seems to ignore SetWindowPos messages */
|
||||
DestroyWindow(infoPtr->hUpdown);
|
||||
/* hmmm... the updown control seems to ignore the width parameter */
|
||||
infoPtr->hUpdown = CreateUpDownControl (WS_CHILD | WS_BORDER | WS_VISIBLE,
|
||||
infoPtr->rcClient.right-14, 0, 20, infoPtr->rcClient.bottom,
|
||||
infoPtr->hwndSelf, 1, 0, 0, UD_MAXVAL, UD_MINVAL, 0);
|
||||
}
|
||||
else {
|
||||
/* set the size of the button that drops the calendar down */
|
||||
/* FIXME: account for style that allows button on left side */
|
||||
infoPtr->calbutton.top = infoPtr->rcDraw.top;
|
||||
infoPtr->calbutton.bottom= infoPtr->rcDraw.bottom;
|
||||
infoPtr->calbutton.left = infoPtr->rcDraw.right-15;
|
||||
infoPtr->calbutton.right = infoPtr->rcDraw.right;
|
||||
}
|
||||
|
||||
/* set enable/disable button size for show none style being enabled */
|
||||
/* FIXME: these dimensions are completely incorrect */
|
||||
|
@ -1067,6 +1211,9 @@ DATETIME_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||
case WM_LBUTTONUP:
|
||||
return DATETIME_LButtonUp (infoPtr, (WORD)wParam);
|
||||
|
||||
case WM_VSCROLL:
|
||||
return DATETIME_VScroll (infoPtr, (WORD)wParam);
|
||||
|
||||
case WM_CREATE:
|
||||
return DATETIME_Create (hwnd, (LPCREATESTRUCTW)lParam);
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@ typedef struct
|
|||
} MONTHCAL_INFO, *LPMONTHCAL_INFO;
|
||||
|
||||
|
||||
/* Offsets of days in the week to the weekday of january 1. */
|
||||
/* Offsets of days in the week to the weekday of january 1 in a leap year */
|
||||
static const int DayOfWeekTable[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
|
||||
|
||||
|
||||
|
@ -187,17 +187,17 @@ void MONTHCAL_CopyTime(const SYSTEMTIME *from, SYSTEMTIME *to)
|
|||
Need to find out if we're on a DST place & adjust the clock accordingly.
|
||||
Above function assumes we have a valid data.
|
||||
Valid for year>1752; 1 <= d <= 31, 1 <= m <= 12.
|
||||
0 = Monday.
|
||||
0 = Sunday.
|
||||
*/
|
||||
|
||||
/* returns the day in the week(0 == monday, 6 == sunday) */
|
||||
/* returns the day in the week(0 == sunday, 6 == saturday) */
|
||||
/* day(1 == 1st, 2 == 2nd... etc), year is the year value */
|
||||
static int MONTHCAL_CalculateDayOfWeek(DWORD day, DWORD month, DWORD year)
|
||||
{
|
||||
year-=(month < 3);
|
||||
|
||||
return((year + year/4 - year/100 + year/400 +
|
||||
DayOfWeekTable[month-1] + day - 1 ) % 7);
|
||||
DayOfWeekTable[month-1] + day ) % 7);
|
||||
}
|
||||
|
||||
/* From a given point, calculate the row (weekpos), column(daypos)
|
||||
|
@ -537,7 +537,7 @@ static void MONTHCAL_Refresh(MONTHCAL_INFO *infoPtr, HDC hdc, PAINTSTRUCT* ps)
|
|||
i = infoPtr->firstDay;
|
||||
|
||||
for(j=0; j<7; j++) {
|
||||
GetLocaleInfoW( LOCALE_USER_DEFAULT,LOCALE_SABBREVDAYNAME1 + (i +j)%7, buf, countof(buf));
|
||||
GetLocaleInfoW( LOCALE_USER_DEFAULT,LOCALE_SABBREVDAYNAME1 + (i+j+6)%7, buf, countof(buf));
|
||||
DrawTextW(hdc, buf, strlenW(buf), days, DT_CENTER | DT_VCENTER | DT_SINGLELINE );
|
||||
days->left+=infoPtr->width_increment;
|
||||
days->right+=infoPtr->width_increment;
|
||||
|
@ -886,7 +886,7 @@ MONTHCAL_GetFirstDayOfWeek(MONTHCAL_INFO *infoPtr)
|
|||
|
||||
|
||||
/* sets the first day of the week that will appear in the control */
|
||||
/* 0 == Monday, 6 == Sunday */
|
||||
/* 0 == Sunday, 6 == Saturday */
|
||||
/* FIXME: this needs to be implemented properly in MONTHCAL_Refresh() */
|
||||
/* FIXME: we need more error checking here */
|
||||
static LRESULT
|
||||
|
@ -904,7 +904,7 @@ MONTHCAL_SetFirstDayOfWeek(MONTHCAL_INFO *infoPtr, LPARAM lParam)
|
|||
{
|
||||
GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IFIRSTDAYOFWEEK, buf, countof(buf));
|
||||
TRACE("%s %d\n", debugstr_w(buf), strlenW(buf));
|
||||
infoPtr->firstDay = atoiW(buf);
|
||||
infoPtr->firstDay = (atoiW(buf)+1)%7;
|
||||
}
|
||||
return prev;
|
||||
}
|
||||
|
@ -1238,6 +1238,7 @@ MONTHCAL_HitTest(MONTHCAL_INFO *infoPtr, LPARAM lParam)
|
|||
retval = MCHT_CALENDARDATE;
|
||||
lpht->st.wMonth = infoPtr->currentMonth;
|
||||
lpht->st.wDay = day;
|
||||
lpht->st.wDayOfWeek = MONTHCAL_CalculateDayOfWeek(day,lpht->st.wMonth,lpht->st.wYear);
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue