Компонент маски в FMX Delphi

Компонент маски в FMX Delphi

Как известно, во фреймворке FMX для Delphi отсутствует компонент маски. И это очень не удобно, поскольку мы все знаем, что маска ввода является достаточно часто используемым компонентом для ввода информации. Обычно это даты, телефонные номера, номера автомобилей и прочие...

В одной из предыдущих статей я рассказывал способ работы с компонентом маски ввода TEditMask библиотеки VCL: «Собственное сообщение для маски ввода (Maskedit Delphi)». В этой статье описываются основные маски ввода и описывается механизм создания собственного сообщения для ошибочно или не полного введенного значения в маску.

Обычно на просторах Интернета я видел достаточно часто, как пользователи программисты пишут о несостоятельности и не совершенности данного компонента. Обычно такие недвусмысленные негативные отзывы относятся к тому, что у многих не получается создать именно собственное сообщение, которое должно появляться, если пользователь ввел некорректные данные. В основном пользователи получают системное сообщение, что их отталкивает от этого компонента. Поэтому приведенная статья описывает как сделать свое собственное сообщение вместо системного.

Но вот в FMX (FireMonkey) компонент маски ввода отсутствует полностью, не смотря на то, что надобность в нем никуда не подевалась. И вот совсем недавно мне понадобился такой компонент. Мне не удобно использовать TDateEdit. Мне больше нравится иметь поле ввода, такое как TEdit и вводить в него данные с клавиатуры. На мой взгляд, это удобнее, чем мышью выбирать даты из списка компоненты TDateEdit.

Ну на самом деле неудобно ведь. Ну представьте, что вам нужно вводить даты рождения людей. При этом вам каждый раз придется выбирать мышью год, меся, а затем дату из этого самого компонента. Крайне не удобно. Гораздо эффективнее в этом случае TMaskEdit, которого нет в FMX. А жаль. Полазив по форумам и блогам довольно долго в надежде найти такой компонент или, по крайней мере, как его сделать. Но увы.

Возможно такой компонент есть в платном варианте от какой-нибудь фирмы, по аналогии с VCL, но мне хотелось чтобы он присутствовал уже, так сказать, из коробки...

Писать собственный компонент маски ввода я не хотел, потому что это неимоверно сложная задача. Его же нужно создать во всех его интерпретациях, чтобы он мог отображать разнообразное число масок ввода, как TMaskEdit в VCL. Поэтому я решил обойтись написание процедуры, способной проверять каждый вводимый символ в TEdit.

Я написал такую процедуру для ввода даты. И я постарался максимально приблизиться к тому, как работает компонент TMaskEdit. И в результате моей работы у меня появилось три версии. Давайте их рассмотрим по порядку. Сразу отмечу, что эти способы создания маски подходят не только для FMX, но и для VCL. Хотя для последней библиотеки все это не нужно, поскольку там есть достаточно развитый TMaskEdit, но, если уж сильно хочется...

Как создать маску ввода в FMX

Конечно в FMX можно поступить хитрее. Можно взять компонент TRectangle как контейнер, поместить в него три компонента TEdit, а меду ними два TText, в котором можно отобразить разделительные точки. У все у этих компонентов убрать обрамление, а для TRectangle просто создать стиль, похожий на стиль компонента TEdit. И будет очень похоже. Тогда просто придется работать отдельно с днем, месяцем и датой. Будет очень похоже на TMaskEdit. Можно даже добавить немного кода для автоматического перехода к месяцу после заполнения даты, а от месяца к году, после заполнения месяца. Но все это больше относится к рисованию, чем к программированию, а мы ведь хотим сделать полноценный ввод, подобный TMaskEdit. Если так, тогда смотрим далее.

Вариант 1

Давайте мы наверное начнем с самого простого варианта такой маски. На одном из сайтов я видел, что дата вводится именно по такому способу. И в принципе, если сильно не заморачиваться, то его достаточно. Итак, разместим на форме самый обычный компонент TEdit.

В FMX у TEdit есть такое событие как OnTyping. Это событие возникает при вводе символов в поле TEdit. Можно использовать его. Но я не хочу этого делать, потому что моя задача обойтись стандартными событиями. OnTyping, например, нет в библиотеке VCL. Но может быть это и не нужно, потому что VCL работает только с Windows.

Но поскольку я хотел сделать универсальную процедуру, работающую как в FMX, так и в VCL, я решил использовать стандартное событие OnKeyDown. Это событие возникает, когда нажимается клавиша клавиатуры.

procedure TfrmActions.txtFilterDate2KeyDown(Sender: TObject; var Key: Word;
  var KeyChar: WideChar; Shift: TShiftState);
var
    sDate: string;//Значение поля ввода
    iLen :integer;//Общая длина
    iSelStart: integer;
begin
    if not (KeyChar in ['0'..'9', #8]) then KeyChar:= #0 else //Если введен любой символ, кроме цифр и BackSpace, то прерываем ввод.
    begin                                                     //иначе следующий код
        sDate:=TEdit(Sender).Text; //Присваиваем переменной полное значение всего поля
        iLen:=sDate.Length; //Выясняем длину этого значения
        if iLen<10 then //Если эта длина меньше 10 (10 - это длина всей даты вместе с точками)
        begin // то выполняем следующий код
            if iLen=2 then //Если количество символов два, то следующий символ должен быть точкой
            begin
               TEdit(Sender).Text:=TEdit(Sender).Text+'.'; //и поэтому мы добавляем точку к существующему тексту
               TEdit(Sender).SelStart := Length(TEdit(Sender).Text); //И далее ставим курсор в конец текста
               TEdit(Sender).SelLength := 0;
            end;
            if iLen=5 then //Если количество символов пять, то следующий символ должен быть также точкой
            begin //Далее по аналогии с предыдущим блоком
               TEdit(Sender).Text:=TEdit(Sender).Text+'.';
               TEdit(Sender).SelStart := Length(TEdit(Sender).Text);
               TEdit(Sender).SelLength := 0;
            end;
        end else KeyChar:= #0; //Если количество символов в TEdit все-таки равно 10, то прерываем ввод.
    end;
end;

Описывать данный код не стану, поскольку я его постарался описать практически построчно в самом листинге кода. Результат работы этого кода следующий... Перед вводом даты в TEdit оно будет абсолютно пустым. То есть, в нем не будет видно символов заполнителей и разделителей, как это принято в TMaskEdit. Затем вы начинаете набирать дату, впечатываете день, затем нажимаете следующую цифру, чтобы ввести месяц, при этом разделительная точка устанавливается автоматически, печатаете далее. В результате у вас получается самая обычная дата:

Дата в TEdit
Результат ввода

Вполне удобно. Процедура довольно короткая. Вполне себе можно реализовать такой компонент на базе TEdit, не создавая при этом нового компонента.

Давайте поговорим теперь о недостатках такого подхода. Но их не много и ими вполне можно пренебречь.

Во-первых, если введены все символы, то вы не сможете поменять символ внутри строки. Например, вы ошиблись месяцем и ввели «21.04.1959» вместо «21.05.1959». Исправить «4» на «5» вы не сможете. Нужно будет удалить полностью маску или хотя бы удалить все символы справа до нуля с помощью Backspace или выделить символы мышью и нажать Delete. А затем ввести месяц и снова год. Ну это не сильный недостаток.

Во-вторых, еще один недостаток заключается в том, что при вводе вы не контролируете значение в том плане, что вы в качестве даты можете ввести «74», а в качестве месяца вы можете ввести хоть «28». Но это тоже не сильный недостаток, потому что так вводятся значения и в компоненте TMaskEdit в VCL. Правильность даты вы можете проверить уже после ввода. О том, как это сделать мы поговорим в следующей статье.

В третьих, как уже было написано выше, при данном способе организации маски ввода в поле TEdit, будут отсутствовать заполняющие символы и символы разделители. Ну может быть так даже элегантнее выглядит. Это, как говорится, на вкус и цвет...

Это, пожалуй, все недостатки. Просто этот подход не похож на стандартное поведение компонента TMaskEdit. А чтобы поведение компонента TEdit было максимально похоже на поведение TMaskEdit рассмотрим два других варианта. Они дают абсолютно одинаковый результат, но реализовываются немного по-разному.

Вариант 2

Размещаем также компонент TEdit на форме. На этот раз мы добавляем в компонент символы заполнители и разделители, поэтому в режиме разработки в диспетчере свойств в свойстве Text указываем значение «__.__.____». Получается как на картинке:

Символы заполнения для маски в FMX
Символы заполнения и разделители для маски в FMX

Далее будем использовать все тоже событие OnKeyDown нашего компонента TEdit. Напишем в нем следующий код:

procedure TfrmActions.txtFilterDate1KeyDown(Sender: TObject; var Key: Word;
  var KeyChar: WideChar; Shift: TShiftState);
var
   s: string;//Значение текстового поля
   sSelect: string;//Текст выделенного фрагмента
   d: integer;//Длина выделенного текста
   i: integer;//Счетчик
   iStart: integer;//Начальная позиция
   iLen: integer;//Длина выделенного текста
begin
     //Сначала осуществляем действия, если выделено сразу несколько любых
     //символов и нажат Delete или Backspace. При этом выделенные символы
     //обязаны удалиться, а вместо них должны остаться символы заполнители
     //и разделительные символы.
     //Итак, если нажата Backspace или Delete и при этом выделенных символов больше 0, то
     if ((Key=8) or (Key=46)) and (TEdit(Sender).SelLength>0) then
     begin
         s:=TEdit(Sender).Text; //Присваиваем текст компоненте TEdit
         sSelect:=TEdit(Sender).SelText; //Присваиваем выделенный текст из TEdit
         iStart:=TEdit(Sender).SelStart+1;//Двигаем курсов на единицу вперед
         d:=Length(sSelect);//Запоминаем длину выделенного текста
         i:=1; //Присваиваем счетчику единицу
         while i<=d do //Если счетчик меньше, либо равен длине выделенного текста
         begin //то проверяем выделенный текст посимвольно
            if sSelect[i]<>'.' then sSelect[i]:='_'; //Если символ не точка, то заменяем его на подчеркивание
            i:=i+1; //Передвигаемся к следующему символу для проверки
         end;
         Delete(s, iStart, d); //Удаляем выделенный кусок текста из переменной
         Insert(sSelect, s, iStart); //Вставляем измененный кусок в переменную s на место удаленного текста
         TEdit(Sender).Text:=s; //Присваиваем TEdit новое значение переменной s
         TEdit(Sender).SelStart:=iStart-1; //Ставим курсор в прежнее положение
         abort; //Останавливаем выполнение программы
     end else //Иначе (если нет выделенных символов) выполняем код ниже.
     begin
         if not ((Key=37) or (Key=39)) then //Если не нажаты клавиши "Назад" или "Вперед" клавиатуры, то
         begin  //проверяем посимвольно
            case TEdit(Sender).SelStart of
                0: //Перед первым символом дня месяца
                begin
                     if not ((Key=8) or (Key=46)) then //Если не нажаты Backspace или Delete
                     begin //то
                       //Контролируем тип вводимых данных в первый символ
                       //Если нажат любой символ, кроме цифр или Backspace, то прерываем ввод
                       if not (KeyChar in ['0'..'9']) then KeyChar:= #0 else
                       begin //иначе (если нажата цифра)
                          s:=TEdit(Sender).Text;//Присваиваем переменной s значение всего текста
                          Delete(s, 1, 1); //Удаляем из переменной s первый символ
                          TEdit(Sender).Text:=s; //Присваиваем TEdit переменную s с удаленным первым символом
                          TEdit(Sender).SelStart:=0; //Устанавливаем указатель перед первым символом
                       end; //Теперь на это место будет добавлен введенный символ
                     end;
                     //Если нажата Backspace, то ничего не делаем, так как это первый символ
                     if Key=8 then
                     begin
                        abort; //то ничего не делаем, так как слева нет символов
                     end;
                     //Если нажата Delete, то меняем символ на "_" справа
                     if Key=46 then
                     begin
                        s:=TEdit(Sender).Text;
                        Delete(s, 1, 1);
                        Insert('_', s, 1);
                        TEdit(Sender).Text:=s;
                        TEdit(Sender).SelStart:=0;
                        abort;
                     end;
                end;
                1: //Перед вторым символом дня месяца
                begin
                     if not ((Key=8) or (Key=46)) then
                     begin
                       //Контролируем тип вводимых данных во второй символ
                       if not (KeyChar in ['0'..'9']) then KeyChar:= #0 else
                       begin
                          s:=TEdit(Sender).Text;
                          Delete(s, 2, 1);
                          TEdit(Sender).Text:=s;
                          TEdit(Sender).SelStart:=1;
                       end;
                     end;
                     //Если нажата Backspace
                     if Key=8 then
                     begin
                        s:=TEdit(Sender).Text;
                        Delete(s, 1, 1);
                        Insert('_', s, 1);
                        TEdit(Sender).Text:=s;
                        TEdit(Sender).SelStart:=0;
                     end;
                     //Если нажата Delete
                     if Key=46 then
                     begin
                        s:=TEdit(Sender).Text;
                        Delete(s, 2, 1);
                        Insert('_', s, 2);
                        TEdit(Sender).Text:=s;
                        TEdit(Sender).SelStart:=1;
                        abort;
                     end;
                end;
                2: //Перед точкой
                begin
                     if not ((Key=8) or (Key=46)) then
                     begin
                        //Контролируем тип вводимых данных
                        if not (KeyChar in ['0'..'9']) then KeyChar:= #0 else
                        begin
                           //И, если это была цифра, то сдвигаемся на один символ
                           //вправо, так как перед нами точка
                           TEdit(Sender).SelStart:=3;
                           //Далее удаляем прежний символ, чтобы вместо него
                           //разместился тот, который нажали
                           s:=TEdit(Sender).Text;
                           Delete(s, 4, 1);
                           TEdit(Sender).Text:=s;
                           TEdit(Sender).SelStart:=3;
                        end;
                     end;
                     //Если нажата Backspace
                     if Key=8 then
                     begin
                        s:=TEdit(Sender).Text;
                        Delete(s, 2, 1);
                        Insert('_', s, 2);
                        TEdit(Sender).Text:=s;
                        TEdit(Sender).SelStart:=1;
                        abort;
                     end;
                     //Если нажата Backspace,
                     if Key=46 then
                     begin
                        //Ничего не делаем, потому что сразу справа находится точка
                        abort;
                     end;
                end;
                3: //Перед первым символом месяца
                begin
                     if not ((Key=8) or (Key=46)) then
                     begin
                       //Контролируем тип вводимых данных в четвертую позицию
                       //Третью позицию перескочили, так как там точка
                       if not (KeyChar in ['0'..'9']) then KeyChar:= #0 else
                       begin
                          s:=TEdit(Sender).Text;
                          Delete(s, 4, 1);
                          TEdit(Sender).Text:=s;
                          TEdit(Sender).SelStart:=3;
                       end;
                     end;
                     //Если нажата Backspace
                     if Key=8 then
                     begin
                        TEdit(Sender).SelStart:=2;
                        s:=TEdit(Sender).Text;
                        Delete(s, 2, 1);
                        Insert('_', s, 2);
                        TEdit(Sender).Text:=s;
                        TEdit(Sender).SelStart:=1;
                        abort;
                     end;
                     //Если нажата Delete
                     if Key=46 then
                     begin
                        s:=TEdit(Sender).Text;
                        Delete(s, 4, 1);
                        Insert('_', s, 4);
                        TEdit(Sender).Text:=s;
                        TEdit(Sender).SelStart:=3;
                        abort;
                     end;
                end;
                4: //Перед вторым символом месяца
                begin
                     if not ((Key=8) or (Key=46)) then
                     begin
                       //Контролируем тип вводимых данных в пятую позицию
                       if not (KeyChar in ['0'..'9']) then KeyChar:= #0 else
                       begin
                          s:=TEdit(Sender).Text;
                          Delete(s, 5, 1);
                          TEdit(Sender).Text:=s;
                          TEdit(Sender).SelStart:=4;
                       end;
                     end;
                     //Если нажата Backspace
                     if Key=8 then
                     begin
                        s:=TEdit(Sender).Text;
                        Delete(s, 4, 1);
                        Insert('_', s, 4);
                        TEdit(Sender).Text:=s;
                        TEdit(Sender).SelStart:=3;
                        abort;
                     end;
                     //Если нажата Delete
                     if Key=46 then
                     begin
                        s:=TEdit(Sender).Text;
                        Delete(s, 5, 1);
                        Insert('_', s, 5);
                        TEdit(Sender).Text:=s;
                        TEdit(Sender).SelStart:=4;
                        abort;
                     end;
                end;
                5: //Перед точкой
                begin
                     if not ((Key=8) or (Key=46)) then
                     begin
                        //Контролируем тип вводимых данных
                        if not (KeyChar in ['0'..'9']) then KeyChar:= #0 else
                        begin
                           //И, если это была цифра, то сдвигаемся на один символ
                           //вправо, так как перед нами точка
                           TEdit(Sender).SelStart:=6;
                           //Далее удаляем прежний символ, чтобы вместо него
                           //разместился тот, который нажали
                           s:=TEdit(Sender).Text;
                           Delete(s, 7, 1);
                           TEdit(Sender).Text:=s;
                           TEdit(Sender).SelStart:=6;
                        end;
                     end;
                     //Если нажата Backspace
                     if Key=8 then
                     begin
                        s:=TEdit(Sender).Text;
                        Delete(s, 5, 1);
                        Insert('_', s, 5);
                        TEdit(Sender).Text:=s;
                        TEdit(Sender).SelStart:=4;
                        abort;
                     end;
                     //Если нажата Delete
                     if Key=46 then
                     begin
                        //Ничего не делаем, потому что сразу справа находится точка
                        abort;
                     end;
                end;
                6: //Перед первым символом года
                begin
                     if not ((Key=8) or (Key=46)) then
                     begin
                        //Контролируем тип вводимых данных
                        if not (KeyChar in ['0'..'9']) then KeyChar:= #0 else
                        begin
                           s:=TEdit(Sender).Text;
                           Delete(s, 7, 1);
                           TEdit(Sender).Text:=s;
                           TEdit(Sender).SelStart:=6;
                        end;
                     end;
                     //Если нажата Backspace
                     if Key=8 then
                     begin
                        TEdit(Sender).SelStart:=5;
                        s:=TEdit(Sender).Text;
                        Delete(s, 5, 1);
                        Insert('_', s, 5);
                        TEdit(Sender).Text:=s;
                        TEdit(Sender).SelStart:=4;
                        abort;
                     end;
                     //Если нажата Delete
                     if Key=46 then
                     begin
                        s:=TEdit(Sender).Text;
                        Delete(s, 7, 1);
                        Insert('_', s, 7);
                        TEdit(Sender).Text:=s;
                        TEdit(Sender).SelStart:=6;
                        abort;
                     end;
                end;
                7: //Перед вторым символом года
                begin
                     if not ((Key=8) or (Key=46)) then
                     begin
                       //Контролируем тип вводимых данных
                       if not (KeyChar in ['0'..'9']) then KeyChar:= #0 else
                       begin
                          s:=TEdit(Sender).Text;
                          Delete(s, 8, 1);
                          TEdit(Sender).Text:=s;
                          TEdit(Sender).SelStart:=7;
                       end;
                     end;
                     //Если нажата Backspace
                     if Key=8 then
                     begin
                        s:=TEdit(Sender).Text;
                        Delete(s, 7, 1);
                        Insert('_', s, 7);
                        TEdit(Sender).Text:=s;
                        TEdit(Sender).SelStart:=6;
                        abort;
                     end;
                     //Если нажата Delete
                     if Key=46 then
                     begin
                        s:=TEdit(Sender).Text;
                        Delete(s, 8, 1);
                        Insert('_', s, 8);
                        TEdit(Sender).Text:=s;
                        TEdit(Sender).SelStart:=7;
                        abort;
                     end;
                end;
                8: //Перед третьим символом года
                begin
                     if not ((Key=8) or (Key=46)) then
                     begin
                       //Контролируем тип вводимых данных
                       if not (KeyChar in ['0'..'9']) then KeyChar:= #0 else
                       begin
                          s:=TEdit(Sender).Text;
                          Delete(s, 9, 1);
                          TEdit(Sender).Text:=s;
                          TEdit(Sender).SelStart:=8;
                       end;
                     end;
                     //Если нажата Backspace
                     if Key=8 then
                     begin
                        s:=TEdit(Sender).Text;
                        Delete(s, 8, 1);
                        Insert('_', s, 8);
                        TEdit(Sender).Text:=s;
                        TEdit(Sender).SelStart:=7;
                        abort;
                     end;
                     //Если нажата Delete
                     if Key=46 then
                     begin
                        s:=TEdit(Sender).Text;
                        Delete(s, 9, 1);
                        Insert('_', s, 9);
                        TEdit(Sender).Text:=s;
                        TEdit(Sender).SelStart:=8;
                        abort;
                     end;
                end;
                9: //Перед четвертым символом года
                begin
                     if not ((Key=8) or (Key=46)) then
                     begin
                       //Контролируем тип вводимых данных
                       if not (KeyChar in ['0'..'9']) then KeyChar:= #0 else
                       begin
                          s:=TEdit(Sender).Text;
                          Delete(s, 10, 1);
                          TEdit(Sender).Text:=s;
                          TEdit(Sender).SelStart:=9;
                       end;
                     end;
                     //Если нажата Backspace
                     if Key=8 then
                     begin
                        s:=TEdit(Sender).Text;
                        Delete(s, 9, 1);
                        Insert('_', s, 9);
                        TEdit(Sender).Text:=s;
                        TEdit(Sender).SelStart:=8;
                        abort;
                     end;
                     //Если нажата Delete
                     if Key=46 then
                     begin
                        s:=TEdit(Sender).Text;
                        Delete(s, 10, 1);
                        Insert('_', s, 10);
                        TEdit(Sender).Text:=s;
                        TEdit(Sender).SelStart:=9;
                        abort;
                     end;
                end;
                10: //После четвертого символа года
                begin
                     if not ((Key=8) or (Key=46)) then
                     begin
                        abort;//Так как год закончился
                     end;
                     //Если нажата Backspace
                     if Key=8 then
                     begin
                        s:=TEdit(Sender).Text;
                        Delete(s, 10, 1);
                        Insert('_', s, 10);
                        TEdit(Sender).Text:=s;
                        TEdit(Sender).SelStart:=9;
                        abort;
                     end;
                     //Если нажата Delete, то
                     if Key=46 then
                     begin
                        abort;
                     end;
                end;
            end;
         end;
     end;
end;

Особенно комментировать приведенный код не стану, так как я его прокомментировал в самом листинге кода практически построчно. Единственное что, не до конца, потому что потом все идет по аналогии.

В двух словах опишу его так: сначала проверяется выделены ли символы массово (более одного) и нажата ли при этом Delete или Backspace. Если да, то выделенные символы удаляются и вместо них ставятся символы заполнители и разделительные точки.

Если это условие не выполняется, то считается, что курсор установлен в каком то любом месте. Тогда при нажатии на любую клавишу мы проверяем позицию, в которой стоим и в каждой такой позиции мы проверяем тип нажатой клавиши. В нашем случае нажатой должна быть цифра. Если нет, то ничего не происходит, а если нажатой оказалась цифра, то опять же, удаляется символ после курсора (символ заполнитель или любой другой) и вместо него ставится нажатый пользователем символ. Если же это была точка, то позиция курсора смещается на один символ вперед.

Сложного вроде бы в нем ничего нет, поэтому думаю, что разберетесь без особого напряжения.

Вариант 3

Третий вариант, в принципе, практически копия второго. Разница только в том, что я использовал вместо связок типа Delete/Insert комбинации методов объекта TEdit таких как SelStart, SelLength и SelText. Преимущество такого подхода заключается в несколько более лаконичном и сокращенном коде. Но не на много. Просто в связке Delete/Insert нужно было присваивать содержимое TEdit переменной, потом с ней работать, а затем значение переменной уже обратно записывать в TEdit, то при методах SelStart, SelLength и SelText этого делать не нужно, потому что можно напрямую работать с TEdit.

  • SelStart — определяет позицию курсора в TEdit;
  • SelLength — определяет количество выделенных символов в TEdit;
  • SelText — содержит выделенный текст.

Ниже представлен этот код:

procedure TfrmActions.txtFilterDate3KeyDown(Sender: TObject; var Key: Word;
  var KeyChar: WideChar; Shift: TShiftState);
var
   s: string;//Значение текстового поля
   sSelect: string;//Текст выделенного фрагмента
   d: integer;//Длина выделенного текста
   i: integer;//Счетчик
   iStart: integer;//Начальная позиция
   iLen: integer;//Длина выделенного текста
begin
   if ((Key=8) or (Key=46)) and (TEdit(Sender).SelLength>0) then
   begin
       iStart:=TEdit(Sender).SelStart;
       iLen:=TEdit(Sender).SelLength;
       i:=1;
       while i<=iLen do
       begin
         TEdit(Sender).SelLength:=1;
         if TEdit(Sender).SelText<>'.' then TEdit(Sender).SelText:='_';
         TEdit(Sender).SelStart:=TEdit(Sender).SelStart+1;
         i:=i+1;
       end;
       TEdit(Sender).SelStart:=iStart;
       abort;
   end else
   begin
       if not ((Key=37) or (Key=39)) then
       begin
          case TEdit(Sender).SelStart of
              0: //Перед первым символом дня месяца
              begin
                   if not ((Key=8) or (Key=46)) then
                   begin
                     //Контролируем тип вводимых данных
                      if not (KeyChar in ['0'..'9']) then KeyChar:= #0 else
                      begin
                        TEdit(Sender).SelLength:=1;
                      end;
                   end;
                   //Если нажата Backspace
                   if Key=8 then
                   begin
                      abort;
                   end;
                   //Если нажата Delete
                   if Key=46 then
                   begin
                      TEdit(Sender).SelLength:=1;
                      TEdit(Sender).SelText:='_';
                      TEdit(Sender).SelStart:=0;
                      abort;
                   end;
              end;
              1: //Перед вторым символом дня месяца
              begin
                   if not ((Key=8) or (Key=46)) then
                   begin
                     //Контролируем тип вводимых данных
                     if not (KeyChar in ['0'..'9']) then KeyChar:= #0 else
                     begin
                        TEdit(Sender).SelLength:=1;
                     end;
                   end;
                   //Если нажата Backspace
                   if Key=8 then
                   begin
                      TEdit(Sender).SelLength:=-1;
                      TEdit(Sender).SelText:='_';
                      TEdit(Sender).SelStart:=0;
                      abort;
                   end;
                   //Если нажата Delete
                   if Key=46 then
                   begin
                      TEdit(Sender).SelLength:=1;
                      TEdit(Sender).SelText:='_';
                      TEdit(Sender).SelStart:=1;
                      abort;
                   end;
              end;
              2: //Перед точкой
              begin
                   if not ((Key=8) or (Key=46)) then
                   begin
                      //Контролируем тип вводимых данных
                      if not (KeyChar in ['0'..'9']) then KeyChar:= #0 else
                      begin
                         //И, если это была цифра, то сдвигаемся на один символ
                         //вправо, так как перед нами точка
                         TEdit(Sender).SelStart:=3;
                         //Далее выделяем символ, чтобы вместо него
                         //проставился тот, который нажали
                         TEdit(Sender).SelLength:=1;
                      end;
                   end;
                   //Если нажата Backspace
                   if Key=8 then
                   begin
                      TEdit(Sender).SelLength:=-1;
                      TEdit(Sender).SelText:='_';
                      TEdit(Sender).SelStart:=1;
                      abort;
                   end;
                   //Если нажата Delete, то
                   if Key=46 then
                   begin
                      abort;
                   end;
              end;
              3: //Перед первым символом месяца
              begin
                   if not ((Key=8) or (Key=46)) then
                   begin
                     //Контролируем тип вводимых данных
                     if not (KeyChar in ['0'..'9']) then KeyChar:= #0 else
                     begin
                        TEdit(Sender).SelLength:=1;
                     end;
                   end;
                   //Если нажата Backspace, то
                   if Key=8 then
                   begin
                      TEdit(Sender).SelStart:=2;
                      TEdit(Sender).SelLength:=-1;
                      TEdit(Sender).SelText:='_';
                      TEdit(Sender).SelStart:=1;
                      abort;
                   end;
                   //Если нажата Delete, то меняем символ на "_"
                   if Key=46 then
                   begin
                      TEdit(Sender).SelLength:=1;
                      TEdit(Sender).SelText:='_';
                      TEdit(Sender).SelStart:=3;
                      abort;
                   end;
              end;
              4: //Перед вторым символом месяца
              begin
                   if not ((Key=8) or (Key=46)) then
                   begin
                     //Контролируем тип вводимых данных
                     if not (KeyChar in ['0'..'9']) then KeyChar:= #0 else
                     begin
                        TEdit(Sender).SelLength:=1;
                     end;
                   end;
                   //Если нажата Backspace, то
                   if Key=8 then
                   begin
                      TEdit(Sender).SelStart:=4;
                      TEdit(Sender).SelLength:=-1;
                      TEdit(Sender).SelText:='_';
                      TEdit(Sender).SelStart:=3;
                      abort;
                   end;
                   //Если нажата Delete, то меняем символ на "_"
                   if Key=46 then
                   begin
                      TEdit(Sender).SelLength:=1;
                      TEdit(Sender).SelText:='_';
                      TEdit(Sender).SelStart:=4;
                      abort;
                   end;
              end;
              5: //Перед точкой
              begin
                   if not ((Key=8) or (Key=46)) then
                   begin
                      //Контролируем тип вводимых данных
                      if not (KeyChar in ['0'..'9']) then KeyChar:= #0 else
                      begin
                         //И, если это была цифра, то сдвигаемся на один символ
                         //вправо, так как перед нами точка
                         TEdit(Sender).SelStart:=6;
                         //Далее выделяем символ, чтобы вместо него
                         //проставился тот, который нажали
                         TEdit(Sender).SelLength:=1;
                      end;
                   end;
                   //Если нажата Backspace
                   if Key=8 then
                   begin
                      TEdit(Sender).SelStart:=5;
                      TEdit(Sender).SelLength:=-1;
                      TEdit(Sender).SelText:='_';
                      TEdit(Sender).SelStart:=4;
                      abort;
                   end;
                   //Если нажата Delete, то меняем символ на "_"
                   if Key=46 then
                   begin
                      abort;
                   end;
              end;
              6: //Перед первым символом года
              begin
                   if not ((Key=8) or (Key=46)) then
                   begin
                      //Контролируем тип вводимых данных
                      if not (KeyChar in ['0'..'9']) then KeyChar:= #0 else
                      begin
                         TEdit(Sender).SelLength:=1;
                      end;
                   end;
                   //Если нажата Backspace
                   if Key=8 then
                   begin
                      TEdit(Sender).SelStart:=5;
                      TEdit(Sender).SelLength:=-1;
                      TEdit(Sender).SelText:='_';
                      TEdit(Sender).SelStart:=4;
                      abort;
                   end;
                   //Если нажата Delete, то меняем символ на "_"
                   if Key=46 then
                   begin
                      TEdit(Sender).SelLength:=1;
                      TEdit(Sender).SelText:='_';
                      TEdit(Sender).SelStart:=6;
                      abort;
                   end;
              end;
              7: //Перед вторым символом года
              begin
                   if not ((Key=8) or (Key=46)) then
                   begin
                      //Контролируем тип вводимых данных
                      if not (KeyChar in ['0'..'9']) then KeyChar:= #0 else
                      begin
                         TEdit(Sender).SelLength:=1;
                      end;
                   end;
                   //Если нажата Backspace
                   if Key=8 then
                   begin
                      TEdit(Sender).SelLength:=-1;
                      TEdit(Sender).SelText:='_';
                      TEdit(Sender).SelStart:=6;
                      abort;
                   end;
                   //Если нажата Delete, то меняем символ на "_"
                   if Key=46 then
                   begin
                      TEdit(Sender).SelLength:=1;
                      TEdit(Sender).SelText:='_';
                      TEdit(Sender).SelStart:=7;
                      abort;
                   end;
              end;
              8: //Перед третьим символом года
              begin
                   if not ((Key=8) or (Key=46)) then
                   begin
                     //Контролируем тип вводимых данных
                     if not (KeyChar in ['0'..'9']) then KeyChar:= #0 else
                     begin
                         TEdit(Sender).SelLength:=1;
                     end;
                   end;
                   //Если нажата Backspace, то
                   if Key=8 then
                   begin
                      TEdit(Sender).SelLength:=-1;
                      TEdit(Sender).SelText:='_';
                      TEdit(Sender).SelStart:=7;
                      abort;
                   end;
                   //Если нажата Delete, то меняем символ на "_"
                   if Key=46 then
                   begin
                      TEdit(Sender).SelLength:=1;
                      TEdit(Sender).SelText:='_';
                      TEdit(Sender).SelStart:=8;
                      abort;
                   end;
              end;
              9: //Перед четвертым символом года
              begin
                   if not ((Key=8) or (Key=46)) then
                   begin
                     //Контролируем тип вводимых данных
                     if not (KeyChar in ['0'..'9']) then KeyChar:= #0 else
                     begin
                         TEdit(Sender).SelLength:=1;
                     end;
                   end;
                   //Если нажата Backspace, то
                   if Key=8 then
                   begin
                      TEdit(Sender).SelLength:=-1;
                      TEdit(Sender).SelText:='_';
                      TEdit(Sender).SelStart:=8;
                      abort;
                   end;
                   //Если нажата Delete, то меняем символ на "_"
                   if Key=46 then
                   begin
                      TEdit(Sender).SelLength:=1;
                      TEdit(Sender).SelText:='_';
                      TEdit(Sender).SelStart:=9;
                      abort;
                   end;
              end;
              10: //После четвертого символа
              begin
                   if not ((Key=8) or (Key=46)) then
                   begin
                     //Контролируем тип вводимых данных
                     if not (KeyChar in ['0'..'9']) then KeyChar:= #0 else
                     begin
                         abort;//Так как год закончился
                     end;
                   end;
                   //Если нажата Backspace, то
                   if Key=8 then
                   begin
                      TEdit(Sender).SelLength:=-1;
                      TEdit(Sender).SelText:='_';
                      TEdit(Sender).SelStart:=9;
                      abort;
                   end;
                   //Если нажата Delete, то
                   if Key=46 then
                   begin
                      abort;
                   end;
              end;
          end;
       end;
   end;
end;

Усовершенствование подхода к построению маски

Рассмотренные выше две последние процедуры отлично работают. Но как всегда их можно оптимизировать. Например, укоротить, вынести общую часть кода в отдельную процедуру, а еще лучше в отдельный модуль, потому что ввод и правильность введенных дат может понадобиться в разных формах.

Объединение общих частей задачи довольно запутанная, поскольку казалось бы определенные общие и одинаковые участки кода при внимательном рассмотрении отличаются, поэтому здесь можно ограничиться тем, чтобы просто вынести всю процедуру в отдельный модуль, а из данного просто вызывать ее. Это необходимо для того, чтобы уменьшить количество кода. Например, если на форме не один компонент маски, а два или три, то такую процедур придется писать целых три раза для каждого компонента и меняться будет только название компонента.

Тогда проще всего вынести весь блок в отельную процедуру и в качестве параметров передавать в нее имя объекта и вводимые символы. Давайте сделаем это. Создадим модуль, сохраним его, назвав my_proc, ну или как вам вздумается.

Из нашей формы (пусть ее модуль будет называться Actions) сразу подключим данный модуль в разделе uses. А в модуле my_proc в uses сразу подключим модуль формы, из которой будем вызывать наш модуль my_proc.

Давайте для примера возьмем код из варианта 2. Разместим код в нашем модуле. Нам понадобиться добавить в uses модуль FMX.Edit. Нашу процедуру мы назовем MaskDate. И будем передавать ей три параметра (объект типа TEdit, Код нажатой клавиши Key с типом Word и нажатый символ KeyChar типа WideChar). Единственный момент, который нам еще потребуется сделать — это поменять в каждой строке «if not (KeyChar in ['0'..'9']) then KeyChar:= #0 else» параметр KeyChar:= #0 на Abort.

unit my_proc;
interface
uses
  SysUtils, FMX.Edit;

  procedure MaskDate(oEdit: TEdit; Key: Word; KeyChar: WideChar);

implementation

uses actions;
procedure MaskDate(oEdit: TEdit; Key: Word; KeyChar: WideChar);
var
   s: string;//Значение текстового поля
   sSelect: string;//Текст выделенного фрагмента
   d: integer;//Длина выделенного текста
   i: integer;//Счетчик
   iStart: integer;//Начальная позиция
   iLen: integer;//Длина выделенного текста
begin
     //Сначала осуществляем действия, если выделено сразу несколько любых
     //символов и нажат Delete или Backspace. При этом выделенные символы
     //обязаны удалиться, а вместо них должны остаться символы заполнители
     //и разделительные символы.
     //Итак, если нажата Backspace или Delete и при этом выделенных символов больше 0, то
     if ((Key=8) or (Key=46)) and (oEdit.SelLength>0) then
     begin
         s:=oEdit.Text; //Присваиваем текст компоненте TEdit
         sSelect:=oEdit.SelText; //Присваиваем выделенный текст из TEdit
         iStart:=oEdit.SelStart+1;//Двигаем курсов на единицу вперед
         d:=Length(sSelect);//Запоминаем длину выделенного текста
         i:=1; //Присваиваем счетчику единицу
         while i<=d do //Если счетчик меньше, либо равен длине выделенного текста
         begin //то проверяем выделенный текст посимвольно
            if sSelect[i]<>'.' then sSelect[i]:='_'; //Если символ не точка, то заменяем его на подчеркивание
            i:=i+1; //Передвигаемся к следующему символу для проверки
         end;
         Delete(s, iStart, d); //Удаляем выделенный кусок текста из переменной
         Insert(sSelect, s, iStart); //Вставляем измененный кусок в переменную s на место удаленного текста
         oEdit.Text:=s; //Присваиваем TEdit новое значение переменной s
         oEdit.SelStart:=iStart-1; //Ставим курсор в прежнее положение
         abort; //Останавливаем выполнение программы
     end else //Иначе (если нет выделенных символов) выполняем код ниже.
     begin
         if not ((Key=37) or (Key=39)) then //Если не нажаты клавиши "Назад" или "Вперед" клавиатуры, то
         begin  //проверяем посимвольно
            case oEdit.SelStart of
                0: //Перед первым символом дня месяца
                begin
                     if not ((Key=8) or (Key=46)) then //Если не нажаты Backspace или Delete
                     begin //то
                       //Контролируем тип вводимых данных в первый символ
                       //Если нажат любой символ, кроме цифр или Backspace, то прерываем ввод
                       if not (KeyChar in ['0'..'9']) then Abort else
                       begin //иначе (если нажата цифра)
                          s:=oEdit.Text;//Присваиваем переменной s значение всего текста
                          Delete(s, 1, 1); //Удаляем из переменной s первый символ
                          oEdit.Text:=s; //Присваиваем TEdit переменную s с удаленным первым символом
                          oEdit.SelStart:=0; //Устанавливаем указатель перед первым символом
                       end; //Теперь на это место будет добавлен введенный символ
                     end;
                     //Если нажата Backspace, то ничего не делаем, так как это первый символ
                     if Key=8 then
                     begin
                        abort; //то ничего не делаем, так как слева нет символов
                     end;
                     //Если нажата Delete, то меняем символ на "_" справа
                     if Key=46 then
                     begin
                        s:=oEdit.Text;
                        Delete(s, 1, 1);
                        Insert('_', s, 1);
                        oEdit.Text:=s;
                        oEdit.SelStart:=0;
                        abort;
                     end;
                end;
                1: //Перед вторым символом дня месяца
                begin
                     if not ((Key=8) or (Key=46)) then
                     begin
                       //Контролируем тип вводимых данных во второй символ
                       if not (KeyChar in ['0'..'9']) then Abort else
                       begin
                          s:=oEdit.Text;
                          Delete(s, 2, 1);
                          oEdit.Text:=s;
                          oEdit.SelStart:=1;
                       end;
                     end;
                     //Если нажата Backspace
                     if Key=8 then
                     begin
                        s:=oEdit.Text;
                        Delete(s, 1, 1);
                        Insert('_', s, 1);
                        oEdit.Text:=s;
                        oEdit.SelStart:=0;
                     end;
                     //Если нажата Delete
                     if Key=46 then
                     begin
                        s:=oEdit.Text;
                        Delete(s, 2, 1);
                        Insert('_', s, 2);
                        oEdit.Text:=s;
                        oEdit.SelStart:=1;
                        abort;
                     end;
                end;
                2: //Перед точкой
                begin
                     if not ((Key=8) or (Key=46)) then
                     begin
                        //Контролируем тип вводимых данных
                        if not (KeyChar in ['0'..'9']) then Abort else
                        begin
                           //И, если это была цифра, то сдвигаемся на один символ
                           //вправо, так как перед нами точка
                           oEdit.SelStart:=3;
                           //Далее удаляем прежний символ, чтобы вместо него
                           //разместился тот, который нажали
                           s:=oEdit.Text;
                           Delete(s, 4, 1);
                           oEdit.Text:=s;
                           oEdit.SelStart:=3;
                        end;
                     end;
                     //Если нажата Backspace
                     if Key=8 then
                     begin
                        s:=oEdit.Text;
                        Delete(s, 2, 1);
                        Insert('_', s, 2);
                        oEdit.Text:=s;
                        oEdit.SelStart:=1;
                        abort;
                     end;
                     //Если нажата Backspace,
                     if Key=46 then
                     begin
                        //Ничего не делаем, потому что сразу справа находится точка
                        abort;
                     end;
                end;
                3: //Перед первым символом месяца
                begin
                     if not ((Key=8) or (Key=46)) then
                     begin
                       //Контролируем тип вводимых данных в четвертую позицию
                       //Третью позицию перескочили, так как там точка
                       if not (KeyChar in ['0'..'9']) then Abort else
                       begin
                          s:=oEdit.Text;
                          Delete(s, 4, 1);
                          oEdit.Text:=s;
                          oEdit.SelStart:=3;
                       end;
                     end;
                     //Если нажата Backspace
                     if Key=8 then
                     begin
                        oEdit.SelStart:=2;
                        s:=oEdit.Text;
                        Delete(s, 2, 1);
                        Insert('_', s, 2);
                        oEdit.Text:=s;
                        oEdit.SelStart:=1;
                        abort;
                     end;
                     //Если нажата Delete
                     if Key=46 then
                     begin
                        s:=oEdit.Text;
                        Delete(s, 4, 1);
                        Insert('_', s, 4);
                        oEdit.Text:=s;
                        oEdit.SelStart:=3;
                        abort;
                     end;
                end;
                4: //Перед вторым символом месяца
                begin
                     if not ((Key=8) or (Key=46)) then
                     begin
                       //Контролируем тип вводимых данных в пятую позицию
                       if not (KeyChar in ['0'..'9']) then Abort else
                       begin
                          s:=oEdit.Text;
                          Delete(s, 5, 1);
                          oEdit.Text:=s;
                          oEdit.SelStart:=4;
                       end;
                     end;
                     //Если нажата Backspace
                     if Key=8 then
                     begin
                        s:=oEdit.Text;
                        Delete(s, 4, 1);
                        Insert('_', s, 4);
                        oEdit.Text:=s;
                        oEdit.SelStart:=3;
                        abort;
                     end;
                     //Если нажата Delete
                     if Key=46 then
                     begin
                        s:=oEdit.Text;
                        Delete(s, 5, 1);
                        Insert('_', s, 5);
                        oEdit.Text:=s;
                        oEdit.SelStart:=4;
                        abort;
                     end;
                end;
                5: //Перед точкой
                begin
                     if not ((Key=8) or (Key=46)) then
                     begin
                        //Контролируем тип вводимых данных
                        if not (KeyChar in ['0'..'9']) then Abort else
                        begin
                           //И, если это была цифра, то сдвигаемся на один символ
                           //вправо, так как перед нами точка
                           oEdit.SelStart:=6;
                           //Далее удаляем прежний символ, чтобы вместо него
                           //разместился тот, который нажали
                           s:=oEdit.Text;
                           Delete(s, 7, 1);
                           oEdit.Text:=s;
                           oEdit.SelStart:=6;
                        end;
                     end;
                     //Если нажата Backspace
                     if Key=8 then
                     begin
                        s:=oEdit.Text;
                        Delete(s, 5, 1);
                        Insert('_', s, 5);
                        oEdit.Text:=s;
                        oEdit.SelStart:=4;
                        abort;
                     end;
                     //Если нажата Delete
                     if Key=46 then
                     begin
                        //Ничего не делаем, потому что сразу справа находится точка
                        abort;
                     end;
                end;
                6: //Перед первым символом года
                begin
                     if not ((Key=8) or (Key=46)) then
                     begin
                        //Контролируем тип вводимых данных
                        if not (KeyChar in ['0'..'9']) then Abort else
                        begin
                           s:=oEdit.Text;
                           Delete(s, 7, 1);
                           oEdit.Text:=s;
                           oEdit.SelStart:=6;
                        end;
                     end;
                     //Если нажата Backspace
                     if Key=8 then
                     begin
                        oEdit.SelStart:=5;
                        s:=oEdit.Text;
                        Delete(s, 5, 1);
                        Insert('_', s, 5);
                        oEdit.Text:=s;
                        oEdit.SelStart:=4;
                        abort;
                     end;
                     //Если нажата Delete
                     if Key=46 then
                     begin
                        s:=oEdit.Text;
                        Delete(s, 7, 1);
                        Insert('_', s, 7);
                        oEdit.Text:=s;
                        oEdit.SelStart:=6;
                        abort;
                     end;
                end;
                7: //Перед вторым символом года
                begin
                     if not ((Key=8) or (Key=46)) then
                     begin
                       //Контролируем тип вводимых данных
                       if not (KeyChar in ['0'..'9']) then Abort else
                       begin
                          s:=oEdit.Text;
                          Delete(s, 8, 1);
                          oEdit.Text:=s;
                          oEdit.SelStart:=7;
                       end;
                     end;
                     //Если нажата Backspace
                     if Key=8 then
                     begin
                        s:=oEdit.Text;
                        Delete(s, 7, 1);
                        Insert('_', s, 7);
                        oEdit.Text:=s;
                        oEdit.SelStart:=6;
                        abort;
                     end;
                     //Если нажата Delete
                     if Key=46 then
                     begin
                        s:=oEdit.Text;
                        Delete(s, 8, 1);
                        Insert('_', s, 8);
                        oEdit.Text:=s;
                        oEdit.SelStart:=7;
                        abort;
                     end;
                end;
                8: //Перед третьим символом года
                begin
                     if not ((Key=8) or (Key=46)) then
                     begin
                       //Контролируем тип вводимых данных
                       if not (KeyChar in ['0'..'9']) then Abort else
                       begin
                          s:=oEdit.Text;
                          Delete(s, 9, 1);
                          oEdit.Text:=s;
                          oEdit.SelStart:=8;
                       end;
                     end;
                     //Если нажата Backspace
                     if Key=8 then
                     begin
                        s:=oEdit.Text;
                        Delete(s, 8, 1);
                        Insert('_', s, 8);
                        oEdit.Text:=s;
                        oEdit.SelStart:=7;
                        abort;
                     end;
                     //Если нажата Delete
                     if Key=46 then
                     begin
                        s:=oEdit.Text;
                        Delete(s, 9, 1);
                        Insert('_', s, 9);
                        oEdit.Text:=s;
                        oEdit.SelStart:=8;
                        abort;
                     end;
                end;
                9: //Перед четвертым символом года
                begin
                     if not ((Key=8) or (Key=46)) then
                     begin
                       //Контролируем тип вводимых данных
                       if not (KeyChar in ['0'..'9']) then Abort else
                       begin
                          s:=oEdit.Text;
                          Delete(s, 10, 1);
                          oEdit.Text:=s;
                          oEdit.SelStart:=9;
                       end;
                     end;
                     //Если нажата Backspace
                     if Key=8 then
                     begin
                        s:=oEdit.Text;
                        Delete(s, 9, 1);
                        Insert('_', s, 9);
                        oEdit.Text:=s;
                        oEdit.SelStart:=8;
                        abort;
                     end;
                     //Если нажата Delete
                     if Key=46 then
                     begin
                        s:=oEdit.Text;
                        Delete(s, 10, 1);
                        Insert('_', s, 10);
                        oEdit.Text:=s;
                        oEdit.SelStart:=9;
                        abort;
                     end;
                end;
                10: //После четвертого символа года
                begin
                     if not ((Key=8) or (Key=46)) then
                     begin
                        abort;//Так как год закончился
                     end;
                     //Если нажата Backspace
                     if Key=8 then
                     begin
                        s:=oEdit.Text;
                        Delete(s, 10, 1);
                        Insert('_', s, 10);
                        oEdit.Text:=s;
                        oEdit.SelStart:=9;
                        abort;
                     end;
                     //Если нажата Delete, то
                     if Key=46 then
                     begin
                        abort;
                     end;
                end;
            end;
         end;
     end;
end;
end;

Теперь в самой форме в onKeyDown у нас останется всего одна строка:

procedure TfrmActions.txtFilterDate1KeyDown(Sender: TObject; var Key: Word;
  var KeyChar: WideChar; Shift: TShiftState);
begin
   MaskDate(TEdit(Sender), Key, KeyChar);
end;

Вот и все!

Заключение

Итак, мы рассмотрели несколько вариантов создания маски на базе компонента TEdit. Маска была рассмотрена на примере ввода даты. Она максимально соответствует компоненту TEditMask из библиотеки VCL. Но такая маска легко создается и для других типов масок, например, для ввода СНИЛС, ввода паспортных данных, ввода государственных номеров автомобилей, телефонных номеров и прочих других масок.

Но не достаточно будет просто ввести данные. Их еще нужно будет и проверить. Например, пользователь может ввести не полную дату или вообще забыть что-либо ввести. О том, как корректно проверить ввод я расскажу в следующей статье.

Понравилась статья? Поделиться с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: