comctl32: Validate text entered in a datetime by the user.
This commit is contained in:
parent
7b0a3128fb
commit
08a4c8611b
|
@ -73,6 +73,8 @@ typedef struct
|
|||
BOOL bCalDepressed; /* TRUE = cal button is depressed */
|
||||
int bDropdownEnabled;
|
||||
int select;
|
||||
WCHAR charsEntered[4];
|
||||
int nCharsEntered;
|
||||
HFONT hFont;
|
||||
int nrFieldsAllocated;
|
||||
int nrFields;
|
||||
|
@ -697,6 +699,13 @@ DATETIME_Refresh (DATETIME_INFO *infoPtr, HDC hdc)
|
|||
/* fill if focused */
|
||||
HBRUSH hbr = CreateSolidBrush (comctl32_color.clrActiveCaption);
|
||||
|
||||
if (infoPtr->nCharsEntered)
|
||||
{
|
||||
memcpy(txt, infoPtr->charsEntered, infoPtr->nCharsEntered * sizeof(WCHAR));
|
||||
txt[infoPtr->nCharsEntered] = 0;
|
||||
GetTextExtentPoint32W (hdc, txt, strlenW(txt), &size);
|
||||
}
|
||||
|
||||
selection.left = 0;
|
||||
selection.top = 0;
|
||||
selection.right = size.cx;
|
||||
|
@ -756,6 +765,68 @@ static int DATETIME_GetPrevDateField(const DATETIME_INFO *infoPtr, int i)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
DATETIME_ApplySelectedField (DATETIME_INFO *infoPtr)
|
||||
{
|
||||
int fieldNum = infoPtr->select & DTHT_DATEFIELD;
|
||||
int i, val=0;
|
||||
SYSTEMTIME date = infoPtr->date;
|
||||
|
||||
if (infoPtr->select == -1 || infoPtr->nCharsEntered == 0)
|
||||
return;
|
||||
|
||||
for (i=0; i<infoPtr->nCharsEntered; i++)
|
||||
val = val * 10 + infoPtr->charsEntered[i] - '0';
|
||||
|
||||
infoPtr->nCharsEntered = 0;
|
||||
|
||||
switch (infoPtr->fieldspec[fieldNum]) {
|
||||
case ONEDIGITYEAR:
|
||||
case TWODIGITYEAR:
|
||||
date.wYear = date.wYear - (date.wYear%100) + val;
|
||||
break;
|
||||
case INVALIDFULLYEAR:
|
||||
case FULLYEAR:
|
||||
date.wYear = val;
|
||||
break;
|
||||
case ONEDIGITMONTH:
|
||||
case TWODIGITMONTH:
|
||||
date.wMonth = val;
|
||||
break;
|
||||
case ONEDIGITDAY:
|
||||
case TWODIGITDAY:
|
||||
date.wDay = val;
|
||||
break;
|
||||
case ONEDIGIT12HOUR:
|
||||
case TWODIGIT12HOUR:
|
||||
case ONEDIGIT24HOUR:
|
||||
case TWODIGIT24HOUR:
|
||||
/* FIXME: Preserve AM/PM for 12HOUR? */
|
||||
date.wHour = val;
|
||||
break;
|
||||
case ONEDIGITMINUTE:
|
||||
case TWODIGITMINUTE:
|
||||
date.wMinute = val;
|
||||
break;
|
||||
case ONEDIGITSECOND:
|
||||
case TWODIGITSECOND:
|
||||
date.wSecond = val;
|
||||
break;
|
||||
}
|
||||
|
||||
if (DATETIME_SetSystemTime(infoPtr, GDT_VALID, &date))
|
||||
DATETIME_SendDateTimeChangeNotify (infoPtr);
|
||||
}
|
||||
|
||||
static void
|
||||
DATETIME_SetSelectedField (DATETIME_INFO *infoPtr, int select)
|
||||
{
|
||||
DATETIME_ApplySelectedField(infoPtr);
|
||||
|
||||
infoPtr->select = select;
|
||||
infoPtr->nCharsEntered = 0;
|
||||
}
|
||||
|
||||
static LRESULT
|
||||
DATETIME_LButtonDown (DATETIME_INFO *infoPtr, INT x, INT y)
|
||||
{
|
||||
|
@ -784,7 +855,8 @@ DATETIME_LButtonDown (DATETIME_INFO *infoPtr, INT x, INT y)
|
|||
if (infoPtr->fieldspec[new] == FULLDAY) return 0;
|
||||
}
|
||||
}
|
||||
infoPtr->select = new;
|
||||
|
||||
DATETIME_SetSelectedField(infoPtr, new);
|
||||
|
||||
if (infoPtr->select == DTHT_MCPOPUP) {
|
||||
RECT rcMonthCal;
|
||||
|
@ -962,6 +1034,7 @@ DATETIME_KeyDown (DATETIME_INFO *infoPtr, DWORD vkCode)
|
|||
{
|
||||
int fieldNum = infoPtr->select & DTHT_DATEFIELD;
|
||||
int wrap = 0;
|
||||
int new;
|
||||
|
||||
if (!(infoPtr->haveFocus)) return 0;
|
||||
if ((fieldNum==0) && (infoPtr->select)) return 0;
|
||||
|
@ -973,40 +1046,50 @@ DATETIME_KeyDown (DATETIME_INFO *infoPtr, DWORD vkCode)
|
|||
switch (vkCode) {
|
||||
case VK_ADD:
|
||||
case VK_UP:
|
||||
infoPtr->nCharsEntered = 0;
|
||||
DATETIME_IncreaseField (infoPtr, fieldNum, 1);
|
||||
DATETIME_SendDateTimeChangeNotify (infoPtr);
|
||||
break;
|
||||
case VK_SUBTRACT:
|
||||
case VK_DOWN:
|
||||
infoPtr->nCharsEntered = 0;
|
||||
DATETIME_IncreaseField (infoPtr, fieldNum, -1);
|
||||
DATETIME_SendDateTimeChangeNotify (infoPtr);
|
||||
break;
|
||||
case VK_HOME:
|
||||
infoPtr->nCharsEntered = 0;
|
||||
DATETIME_IncreaseField (infoPtr, fieldNum, INT_MIN);
|
||||
DATETIME_SendDateTimeChangeNotify (infoPtr);
|
||||
break;
|
||||
case VK_END:
|
||||
infoPtr->nCharsEntered = 0;
|
||||
DATETIME_IncreaseField (infoPtr, fieldNum, INT_MAX);
|
||||
DATETIME_SendDateTimeChangeNotify (infoPtr);
|
||||
break;
|
||||
case VK_LEFT:
|
||||
new = infoPtr->select;
|
||||
do {
|
||||
if (infoPtr->select == 0) {
|
||||
infoPtr->select = infoPtr->nrFields - 1;
|
||||
if (new == 0) {
|
||||
new = new - 1;
|
||||
wrap++;
|
||||
} else {
|
||||
infoPtr->select--;
|
||||
new--;
|
||||
}
|
||||
} while ((infoPtr->fieldspec[infoPtr->select] & DT_STRING) && (wrap<2));
|
||||
} while ((infoPtr->fieldspec[new] & DT_STRING) && (wrap<2));
|
||||
if (new != infoPtr->select)
|
||||
DATETIME_SetSelectedField(infoPtr, new);
|
||||
break;
|
||||
case VK_RIGHT:
|
||||
new = infoPtr->select;
|
||||
do {
|
||||
infoPtr->select++;
|
||||
if (infoPtr->select==infoPtr->nrFields) {
|
||||
infoPtr->select = 0;
|
||||
new++;
|
||||
if (new==infoPtr->nrFields) {
|
||||
new = 0;
|
||||
wrap++;
|
||||
}
|
||||
} while ((infoPtr->fieldspec[infoPtr->select] & DT_STRING) && (wrap<2));
|
||||
} while ((infoPtr->fieldspec[new] & DT_STRING) && (wrap<2));
|
||||
if (new != infoPtr->select)
|
||||
DATETIME_SetSelectedField(infoPtr, new);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1022,80 +1105,20 @@ DATETIME_Char (DATETIME_INFO *infoPtr, WPARAM vkCode)
|
|||
int fieldNum = infoPtr->select & DTHT_DATEFIELD;
|
||||
|
||||
if (vkCode >= '0' && vkCode <= '9') {
|
||||
int num = vkCode-'0';
|
||||
int newDays;
|
||||
int maxChars;
|
||||
int fieldSpec;
|
||||
|
||||
/* this is a somewhat simplified version of what Windows does */
|
||||
SYSTEMTIME *date = &infoPtr->date;
|
||||
switch (infoPtr->fieldspec[fieldNum]) {
|
||||
case ONEDIGITYEAR:
|
||||
case TWODIGITYEAR:
|
||||
date->wYear = date->wYear - (date->wYear%100) +
|
||||
(date->wYear%10)*10 + num;
|
||||
MONTHCAL_CalculateDayOfWeek(date, TRUE);
|
||||
DATETIME_SendDateTimeChangeNotify (infoPtr);
|
||||
break;
|
||||
case INVALIDFULLYEAR:
|
||||
case FULLYEAR:
|
||||
/* reset current year initialy */
|
||||
date->wYear = ((date->wYear/1000) ? 0 : 1)*(date->wYear%1000)*10 + num;
|
||||
MONTHCAL_CalculateDayOfWeek(date, TRUE);
|
||||
DATETIME_SendDateTimeChangeNotify (infoPtr);
|
||||
break;
|
||||
case ONEDIGITMONTH:
|
||||
case TWODIGITMONTH:
|
||||
if ((date->wMonth%10) > 1 || num > 2)
|
||||
date->wMonth = num;
|
||||
else
|
||||
date->wMonth = (date->wMonth%10)*10+num;
|
||||
MONTHCAL_CalculateDayOfWeek(date, TRUE);
|
||||
DATETIME_SendDateTimeChangeNotify (infoPtr);
|
||||
break;
|
||||
case ONEDIGITDAY:
|
||||
case TWODIGITDAY:
|
||||
newDays = (date->wDay%10)*10+num;
|
||||
if (newDays > MONTHCAL_MonthLength(date->wMonth, date->wYear))
|
||||
date->wDay = num;
|
||||
else
|
||||
date->wDay = newDays;
|
||||
MONTHCAL_CalculateDayOfWeek(date, TRUE);
|
||||
DATETIME_SendDateTimeChangeNotify (infoPtr);
|
||||
break;
|
||||
case ONEDIGIT12HOUR:
|
||||
case TWODIGIT12HOUR:
|
||||
if ((date->wHour%10) > 1 || num > 2)
|
||||
date->wHour = num;
|
||||
else
|
||||
date->wHour = (date->wHour%10)*10+num;
|
||||
DATETIME_SendDateTimeChangeNotify (infoPtr);
|
||||
break;
|
||||
case ONEDIGIT24HOUR:
|
||||
case TWODIGIT24HOUR:
|
||||
if ((date->wHour%10) > 2)
|
||||
date->wHour = num;
|
||||
else if ((date->wHour%10) == 2 && num > 3)
|
||||
date->wHour = num;
|
||||
else
|
||||
date->wHour = (date->wHour%10)*10+num;
|
||||
DATETIME_SendDateTimeChangeNotify (infoPtr);
|
||||
break;
|
||||
case ONEDIGITMINUTE:
|
||||
case TWODIGITMINUTE:
|
||||
if ((date->wMinute%10) > 5)
|
||||
date->wMinute = num;
|
||||
else
|
||||
date->wMinute = (date->wMinute%10)*10+num;
|
||||
DATETIME_SendDateTimeChangeNotify (infoPtr);
|
||||
break;
|
||||
case ONEDIGITSECOND:
|
||||
case TWODIGITSECOND:
|
||||
if ((date->wSecond%10) > 5)
|
||||
date->wSecond = num;
|
||||
else
|
||||
date->wSecond = (date->wSecond%10)*10+num;
|
||||
DATETIME_SendDateTimeChangeNotify (infoPtr);
|
||||
break;
|
||||
}
|
||||
infoPtr->charsEntered[infoPtr->nCharsEntered++] = vkCode;
|
||||
|
||||
fieldSpec = infoPtr->fieldspec[fieldNum];
|
||||
|
||||
if (fieldSpec == INVALIDFULLYEAR || fieldSpec == FULLYEAR)
|
||||
maxChars = 4;
|
||||
else
|
||||
maxChars = 2;
|
||||
|
||||
if (maxChars == infoPtr->nCharsEntered)
|
||||
DATETIME_ApplySelectedField(infoPtr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1133,6 +1156,7 @@ DATETIME_KillFocus (DATETIME_INFO *infoPtr, HWND lostFocus)
|
|||
if (infoPtr->haveFocus) {
|
||||
DATETIME_SendSimpleNotify (infoPtr, NM_KILLFOCUS);
|
||||
infoPtr->haveFocus = 0;
|
||||
DATETIME_SetSelectedField (infoPtr, -1);
|
||||
}
|
||||
|
||||
InvalidateRect (infoPtr->hwndSelf, NULL, TRUE);
|
||||
|
|
Loading…
Reference in New Issue