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 */
|
BOOL bCalDepressed; /* TRUE = cal button is depressed */
|
||||||
int bDropdownEnabled;
|
int bDropdownEnabled;
|
||||||
int select;
|
int select;
|
||||||
|
WCHAR charsEntered[4];
|
||||||
|
int nCharsEntered;
|
||||||
HFONT hFont;
|
HFONT hFont;
|
||||||
int nrFieldsAllocated;
|
int nrFieldsAllocated;
|
||||||
int nrFields;
|
int nrFields;
|
||||||
|
@ -697,6 +699,13 @@ DATETIME_Refresh (DATETIME_INFO *infoPtr, HDC hdc)
|
||||||
/* fill if focused */
|
/* fill if focused */
|
||||||
HBRUSH hbr = CreateSolidBrush (comctl32_color.clrActiveCaption);
|
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.left = 0;
|
||||||
selection.top = 0;
|
selection.top = 0;
|
||||||
selection.right = size.cx;
|
selection.right = size.cx;
|
||||||
|
@ -756,6 +765,68 @@ static int DATETIME_GetPrevDateField(const DATETIME_INFO *infoPtr, int i)
|
||||||
return -1;
|
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
|
static LRESULT
|
||||||
DATETIME_LButtonDown (DATETIME_INFO *infoPtr, INT x, INT y)
|
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;
|
if (infoPtr->fieldspec[new] == FULLDAY) return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
infoPtr->select = new;
|
|
||||||
|
DATETIME_SetSelectedField(infoPtr, new);
|
||||||
|
|
||||||
if (infoPtr->select == DTHT_MCPOPUP) {
|
if (infoPtr->select == DTHT_MCPOPUP) {
|
||||||
RECT rcMonthCal;
|
RECT rcMonthCal;
|
||||||
|
@ -962,6 +1034,7 @@ DATETIME_KeyDown (DATETIME_INFO *infoPtr, DWORD vkCode)
|
||||||
{
|
{
|
||||||
int fieldNum = infoPtr->select & DTHT_DATEFIELD;
|
int fieldNum = infoPtr->select & DTHT_DATEFIELD;
|
||||||
int wrap = 0;
|
int wrap = 0;
|
||||||
|
int new;
|
||||||
|
|
||||||
if (!(infoPtr->haveFocus)) return 0;
|
if (!(infoPtr->haveFocus)) return 0;
|
||||||
if ((fieldNum==0) && (infoPtr->select)) return 0;
|
if ((fieldNum==0) && (infoPtr->select)) return 0;
|
||||||
|
@ -973,40 +1046,50 @@ DATETIME_KeyDown (DATETIME_INFO *infoPtr, DWORD vkCode)
|
||||||
switch (vkCode) {
|
switch (vkCode) {
|
||||||
case VK_ADD:
|
case VK_ADD:
|
||||||
case VK_UP:
|
case VK_UP:
|
||||||
|
infoPtr->nCharsEntered = 0;
|
||||||
DATETIME_IncreaseField (infoPtr, fieldNum, 1);
|
DATETIME_IncreaseField (infoPtr, fieldNum, 1);
|
||||||
DATETIME_SendDateTimeChangeNotify (infoPtr);
|
DATETIME_SendDateTimeChangeNotify (infoPtr);
|
||||||
break;
|
break;
|
||||||
case VK_SUBTRACT:
|
case VK_SUBTRACT:
|
||||||
case VK_DOWN:
|
case VK_DOWN:
|
||||||
|
infoPtr->nCharsEntered = 0;
|
||||||
DATETIME_IncreaseField (infoPtr, fieldNum, -1);
|
DATETIME_IncreaseField (infoPtr, fieldNum, -1);
|
||||||
DATETIME_SendDateTimeChangeNotify (infoPtr);
|
DATETIME_SendDateTimeChangeNotify (infoPtr);
|
||||||
break;
|
break;
|
||||||
case VK_HOME:
|
case VK_HOME:
|
||||||
|
infoPtr->nCharsEntered = 0;
|
||||||
DATETIME_IncreaseField (infoPtr, fieldNum, INT_MIN);
|
DATETIME_IncreaseField (infoPtr, fieldNum, INT_MIN);
|
||||||
DATETIME_SendDateTimeChangeNotify (infoPtr);
|
DATETIME_SendDateTimeChangeNotify (infoPtr);
|
||||||
break;
|
break;
|
||||||
case VK_END:
|
case VK_END:
|
||||||
|
infoPtr->nCharsEntered = 0;
|
||||||
DATETIME_IncreaseField (infoPtr, fieldNum, INT_MAX);
|
DATETIME_IncreaseField (infoPtr, fieldNum, INT_MAX);
|
||||||
DATETIME_SendDateTimeChangeNotify (infoPtr);
|
DATETIME_SendDateTimeChangeNotify (infoPtr);
|
||||||
break;
|
break;
|
||||||
case VK_LEFT:
|
case VK_LEFT:
|
||||||
|
new = infoPtr->select;
|
||||||
do {
|
do {
|
||||||
if (infoPtr->select == 0) {
|
if (new == 0) {
|
||||||
infoPtr->select = infoPtr->nrFields - 1;
|
new = new - 1;
|
||||||
wrap++;
|
wrap++;
|
||||||
} else {
|
} 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;
|
break;
|
||||||
case VK_RIGHT:
|
case VK_RIGHT:
|
||||||
|
new = infoPtr->select;
|
||||||
do {
|
do {
|
||||||
infoPtr->select++;
|
new++;
|
||||||
if (infoPtr->select==infoPtr->nrFields) {
|
if (new==infoPtr->nrFields) {
|
||||||
infoPtr->select = 0;
|
new = 0;
|
||||||
wrap++;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1022,80 +1105,20 @@ DATETIME_Char (DATETIME_INFO *infoPtr, WPARAM vkCode)
|
||||||
int fieldNum = infoPtr->select & DTHT_DATEFIELD;
|
int fieldNum = infoPtr->select & DTHT_DATEFIELD;
|
||||||
|
|
||||||
if (vkCode >= '0' && vkCode <= '9') {
|
if (vkCode >= '0' && vkCode <= '9') {
|
||||||
int num = vkCode-'0';
|
int maxChars;
|
||||||
int newDays;
|
int fieldSpec;
|
||||||
|
|
||||||
/* this is a somewhat simplified version of what Windows does */
|
infoPtr->charsEntered[infoPtr->nCharsEntered++] = vkCode;
|
||||||
SYSTEMTIME *date = &infoPtr->date;
|
|
||||||
switch (infoPtr->fieldspec[fieldNum]) {
|
fieldSpec = infoPtr->fieldspec[fieldNum];
|
||||||
case ONEDIGITYEAR:
|
|
||||||
case TWODIGITYEAR:
|
if (fieldSpec == INVALIDFULLYEAR || fieldSpec == FULLYEAR)
|
||||||
date->wYear = date->wYear - (date->wYear%100) +
|
maxChars = 4;
|
||||||
(date->wYear%10)*10 + num;
|
else
|
||||||
MONTHCAL_CalculateDayOfWeek(date, TRUE);
|
maxChars = 2;
|
||||||
DATETIME_SendDateTimeChangeNotify (infoPtr);
|
|
||||||
break;
|
if (maxChars == infoPtr->nCharsEntered)
|
||||||
case INVALIDFULLYEAR:
|
DATETIME_ApplySelectedField(infoPtr);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1133,6 +1156,7 @@ DATETIME_KillFocus (DATETIME_INFO *infoPtr, HWND lostFocus)
|
||||||
if (infoPtr->haveFocus) {
|
if (infoPtr->haveFocus) {
|
||||||
DATETIME_SendSimpleNotify (infoPtr, NM_KILLFOCUS);
|
DATETIME_SendSimpleNotify (infoPtr, NM_KILLFOCUS);
|
||||||
infoPtr->haveFocus = 0;
|
infoPtr->haveFocus = 0;
|
||||||
|
DATETIME_SetSelectedField (infoPtr, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
InvalidateRect (infoPtr->hwndSelf, NULL, TRUE);
|
InvalidateRect (infoPtr->hwndSelf, NULL, TRUE);
|
||||||
|
|
Loading…
Reference in New Issue