Проверка входных данных TStringGrid для разрешения только чисел, десятичных знаков и запятых в C++ Builder XE8
Этот вопрос является продолжением другого вопроса:
Проверка ввода TEdit в C++ Builder XE8
У меня есть редактируемый TStringGrid
, Я только хочу, чтобы пользователь набирал числа и максимум одну десятичную точку или запятую для каждой ячейки в сетке.
Из приведенной выше ссылки я понимаю, как разрешить только определенные ключи, но не как отслеживать, сколько раз определенное значение ключа уже существует в данной ячейке.
Из приведенной выше ссылки, у меня есть это:
void __fastcall TSetDataForm::ProbabilityGridKeyPress(TObject *Sender, System::WideChar &Key)
{
if( Key == VK_BACK )
return;
if( (Key < L'0') || (Key > L'9') )
{
ShowMessage("Please enter numerals only");
Key = 0;
}
}
Как я могу позволить '.'
или же ','
но только один раз?
2 ответа
Я бы предложил использовать TryStrToFloat()
чтобы проверить ввод, тогда не возникает вопроса, вводит ли пользователь правильную десятичную строку или нет. Вам просто нужно разобраться с дополнительными случаями, когда:
пользователь печатает символ где-то, кроме конца поля редактирования, с выделенным текстом или без него.
пользователь копирует / вставляет текст в редактор.
Например:
class TStringGridAccess : public TStringGrid
{
public:
__property InplaceEditor;
};
void __fastcall TSetDataForm::ProbabilityGridKeyPress(TObject *Sender, System::WideChar &Key)
{
switch (Key)
{
case 3: // Ctrl-C
case 8: // Backspace
return;
case 22: // Ctrl-V
{
Key = 0;
TInplaceEdit *Editor = ((TStringGridAccess*)ProbabilityGrid)->InplaceEditor;
String SaveCellText = ProbabilityGrid->Cells[ProbabilityGrid->Col][ProbabilityGrid->Row];
String SaveEditText = Editor->Text;
int SaveSelStart = Editor->SelStart;
int SaveSelLen = Editor->SelLength;
Editor->Perform(WM_PASTE, 0, 0);
TFormatSettings fmt = TFormatSettings::Create();
fmt.DecimalSeparator = _D('.');
double value;
if (TryStrToFloat(Editor->Text, value, fmt))
return;
ProbabilityGrid->Cells[ProbabilityGrid->Col][ProbabilityGrid->Row] = SaveCellText;
Editor->Text = SaveEditText;
Editor->SelStart = SaveSelStart;
Editor->SelLength = SaveSelLen;
break;
}
case _D('0'):
case _D('1'):
case _D('2'):
case _D('3'):
case _D('4'):
case _D('5'):
case _D('6'):
case _D('7'):
case _D('8'):
case _D('9'):
case _D('.'):
{
TInplaceEdit *Editor = ((TStringGridAccess*)ProbabilityGrid)->InplaceEditor;
String str = Editor->Text;
int idx = Editor->SelStart;
int len = Editor->SelLength;
String str2 = str.SubString(1, idx) + Key + str.SubString(1+idx+len, MaxInt);
TFormatSettings fmt = TFormatSettings::Create();
fmt.DecimalSeparator = _D('.');
double value;
if (TryStrToFloat(str2, value, fmt))
return;
break;
}
}
ShowMessage(_D("Please enter decimals only"));
Key = 0;
}
Моя проблема была связана с тем, что я не знал, как читать текст ячейки, в которую пишет пользователь.
Вот мое решение для всех, кто заинтересован:
void __fastcall TSetDataForm::ProbabilityGridKeyPress(TObject *Sender, System::WideChar &Key)
{
if( Key == VK_BACK )
return;
if( !((Key >= L'0') && (Key <= L'9') || (Key == L'.')))
{
ShowMessage("Please enter numerals only");
Key = 0;
}
else if ((Key == L'.') &&
(Pos(Key, ProbabilityGrid->Cells[ProbabilityGrid->Col][ProbabilityGrid->Row]) > 0))
{
ShowMessage("Two dots!");
Key = 0;
}
}