Проверка входных данных 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;
    }
}
Другие вопросы по тегам