Мансуров. Основы программирования в среде Lazarus. 2010
.pdfГлава 6 Программирование приложений с графическим интерфейсом
____________________________________________________________________
AutoSelect = true
EditMask = #9999;0;
TabOrder = 1
свойство Text оставьте пустым.
Установите символ заполнитель такой же, что и для MaskEdit1.
В LabeledEdit3 и BitBtn1 свойству TabStop присвойте значение
false.
Обработчики событий запишите в виде:
procedure TForm1.FormShow(Sender: TObject); begin
MaskEdit1.SetFocus;
end;
procedure TForm1.SpeedButton1Click(Sender: TObject); begin
LabeledEdit3.Text:= IntToStr(StrToInt(MaskEdit1.Text)
+ StrToInt(MaskEdit2.Text));
StatusBar1.SimpleText:= 'Сложение';
MaskEdit1.SetFocus;
MaskEdit1.SelectAll;
end;
procedure TForm1.SpeedButton2Click(Sender: TObject); begin
LabeledEdit3.Text:= IntToStr(StrToInt(MaskEdit1.Text)
- StrToInt(MaskEdit2.Text));
StatusBar1.SimpleText:= 'Вычитание';
MaskEdit1.SetFocus;
MaskEdit1.SelectAll;
end;
531
6.3 Визуальное программирование в среде Lazarus
____________________________________________________________________
procedure TForm1.SpeedButton3Click(Sender: TObject); begin
LabeledEdit3.Text:= IntToStr(StrToInt(MaskEdit1.Text)
* StrToInt(MaskEdit2.Text));
StatusBar1.SimpleText:= 'Умножение';
MaskEdit1.SetFocus;
MaskEdit1.SelectAll;
end;
procedure TForm1.SpeedButton4Click(Sender: TObject); begin
try
LabeledEdit3.Text:= IntToStr(StrToInt(MaskEdit1.Text)
div StrToInt(MaskEdit2.Text));
except
on EDivByZero do
ShowMessage('Ошибка! Произошло деление на ноль.' + ' Вероятно Вы ошиблись при вводе второго числа');
end;
StatusBar1.SimpleText:= 'Деление нацело';
MaskEdit1.SetFocus;
MaskEdit1.SelectAll;
end;
Как видите, обработку исключений на возможные ошибки преобразования типов мы убрали, поскольку MaskEdit не позволит пользователю ввести не-
допустимые символы. Но в обработчике операции деления исключение, возни-
кающее при попытке деления на ноль мы, естественно, оставили.
Переход от MaskEdit1 к MaskEdit2 и обратно осуществляйте кла-
вишей Tab.
532
Глава 6 Программирование приложений с графическим интерфейсом
____________________________________________________________________
Впрочем, можете добавить обработчик OnKeyPress для MaskEdit1:
procedure TForm1.MaskEdit1KeyPress(Sender: TObject; var Key: char);
begin
if Key = #13 then begin
MaskEdit2.SetFocus; SpeedButton1.Down:= false; SpeedButton2.Down:= false; SpeedButton3.Down:= false; SpeedButton4.Down:= false; exit;
end;
end;
Давайте теперь попробуем сами реализовать контроль ввода для компо-
нента TLabeledEdit. Реализуем полный контроль ввода целых чисел с уче-
том знака. Для этого создадим простое приложение. Поместите на форму два компонента TLabeledEdit и одну кнопку TButton, рис. 6.34.
Рис. 6.34. Форма приложения
Установите свойство TabOrder=0 и TabStop=true |
для |
533
6.3 Визуальное программирование в среде Lazarus
____________________________________________________________________
LabeledEdit1, и TabOrder=1, TabStop=true для TButton1, а для
LabeledEdit2 свойство TabStop=false. Это для того, чтобы при нажатии клавиши Tab фокус автоматически перемещался с LabeledEdit1 на кнопку
иобратно. Кроме того, установите свойство AutoSelect для
LabeledEdit1 равным true.
Будем вводить числа в окне LabeledEdit1, затем введенное число про-
сто выведем в LabeledEdit2, но не "сразу"! Сначала преобразуем его во внутреннее представление целого числа для того, чтобы "выловить" ошибки.
Если будут ошибки при вводе, то естественно, преобразования не произойдет и возникнет исключение EConvertError. Для отладки и тестирования нашего приложения нам хватит и стандартной реакции системы, поэтому обработку исключения мы делать не будем. Добавьте лишь исключение
EConvertError в список игнора через меню
Окружение->Параметры>Отладчик->Исключения языка, чтобы удоб-
нее было запускать наше приложение из среды Lazarus.
Итак, с чего начнем? Задача вполне ясная. Необходимо обеспечить ввод пользователем только цифр от 0 до 9 и знака минус (-) (знак плюс (+) перед числом обычно не ставится). Для этого проще всего воспользоваться опреде-
ленным в Паскаль типом – множество и оператором in для определения при-
надлежности символа к допустимым.
В LabeledEdit1 для события OnKeyPress напишите следующий об-
работчик:
procedure TForm1.LabeledEdit1KeyPress(Sender: TObject; var Key: char);
begin
{разрешаем только цифры, знак минус и кл. BackSpace } if not (Key in ['0' .. '9', '-' , #8])
534
Глава 6 Программирование приложений с графическим интерфейсом
____________________________________________________________________
then Key:= #0;
end;
В операторе if если пользователь нажимает на клавиши отличные от цифр, клавиши BackSpace и знака (-) параметру Key присваивается нулевой символ.
Для события OnClick кнопки напишите следующий обработчик:
procedure TForm1.Button1Click(Sender: TObject);
begin
LabeledEdit1.SetFocus;
n:= StrToInt(LabeledEdit1.Text);
LabeledEdit2.Text:= IntToStr(n);
end;
Не забудьте объявить переменную n целого типа:
var
Form1: TForm1;
n: integer;
Запустите приложение. Попробуйте ввести символы, отличные от цифр и знака минус. Вы видите, что недопустимые символы просто не появляются в окне ввода. И что? Задача решена? К сожалению, нет!
Введите несколько цифр, а затем знак минус. Например, "2010-". Если нажать на кнопку, получите сообщение об ошибке. Потому что знак числа ста-
вится перед первой значащей цифрой. Или введите сначала два или более знака
(-), затем цифры, например, "--2010". Опять получите ошибку.
Вы скажете, ну не может быть, чтобы пользователь допускал такие ошиб-
ки! Не настолько же пользователь глуп и туп! И вы правы! Речь может идти о случайных ошибках. Мы на протяжении этой книги не раз говорили об этом.
Программа должна быть защищена от любых случайных и непреднамеренных
535
6.3 Визуальное программирование в среде Lazarus
____________________________________________________________________
ошибок пользователя!
Значит после ввода цифр, знак (-) тоже должен быть запрещен. Кроме того,
необходимо разрешить ввод знака числа только один раз, причем вначале чис-
ла! Для этого введем логическую переменную, назовем ее sign. Первоначаль-
но ее значение будет равно false. Как только пользователь нажал на хотя бы один допустимый символ, включая знак числа, переменной sign присваиваем значение true.
Обработчик для LabeledEdit1 переписываем в следующем виде, заод-
но разрешим пользователю заканчивать ввод нажатием клавиши Enter:
procedure TForm1.LabeledEdit1KeyPress(Sender: TObject;
var Key: char);
begin
if Key = #13 then
begin
sign:= false;
n:= StrToInt(LabeledEdit1.Text);
LabeledEdit2.Text:= IntToStr(n);
end;
{разрешаем только цифры, знак минус и кл. BackSpace } if not (Key in ['0' .. '9', '-' , #8]) then
begin Key:= #0; exit;
end;
if (Key = '-') and (sign) then Key:= #0;
sign:= true;
536
Глава 6 Программирование приложений с графическим интерфейсом
____________________________________________________________________
end;
Оператор
if (Key = '-') and (sign)
then Key:= #0;
не позволит пользователю ввести знак числа после значащих цифр и, кроме то-
го, дважды ввести знак (-).
Теперь, кажется все. Но нет, еще не все! Представьте ситуацию – пользо-
ватель хотел ввести отрицательное число, но забыл ввести знак минус, а цифры уже ввел. Попробуйте ввести несколько цифр, затем вернуть курсор на начало строки и попытайтесь ввести (-). У вас не получится! Даже если вы удалите введенные цифры клавишей Delete или BackSpace. Потому что sign имеет значение true. Ситуация не столь проста, как кажется. Чтобы ввести отрица-
тельное число нужно сначала нажать на кнопку "Ввод" или на клавишу Enter,
т.е. пользователь будет вынужден ввести число, которое не хотел вводить!
Придется контролировать положение курсора. У компонента есть свойство
SelStart, которое указывает на текущее положение курсора. Используя это свойство и функцию Pos, перепишем обработчик следующим образом:
procedure TForm1.LabeledEdit1KeyPress(Sender: TObject;
var Key: char);
begin
if Key = #13 then
begin
sign:= false;
n:= StrToInt(LabeledEdit1.Text);
LabeledEdit2.Text:= IntToStr(n);
exit;
537
6.3 Визуальное программирование в среде Lazarus
____________________________________________________________________
end;
{разрешаем только цифры, знак минус и кл. BackSpace } if not (Key in ['0' .. '9', '-' , #8]) then
begin Key:= #0; exit;
end;
if (Key = '-') and (sign) then
begin
if (LabeledEdit1.SelStart <> 0) then
begin Key:= #0; exit;
end else
if (Pos('-', LabeledEdit1.Text) <> 0) then Key:= #0;
end;
sign:= true; end;
Обработчик работает следующим образом – если текущий символ знак (-)
и цифры введены, то проверяем позицию курсора. Если курсор установлен на начало и минуса нет, то разрешаем ввод знака.
Уф! Наконец-то должно все заработать как надо. Но есть нюанс!
Попробуйте ввести только один знак (-) и больше ничего. Опять получите
538
Глава 6 Программирование приложений с графическим интерфейсом
____________________________________________________________________
ошибку. Но это уже слишком, воскликнете вы! Кому придет в голову вводить один только минус. Ну, а вдруг, чисто случайно? И еще. А что если, пользова-
тель ничего не введя, опять же случайно, нажмет кнопку или Enter, т.е. будет введена пустая строка?
У вас не возникает ощущения, что мы пишем программу для американцев? (Как говорил М. Задорнов – "Ну, тупые…!).
Сделаем так, если длина строки равна единице и это знак (-), то запрещаем ввод.
procedure TForm1.LabeledEdit1KeyPress(Sender: TObject; var Key: char);
begin
if Key = #13 then begin
sign:= false;
if Length(LabeledEdit1.Text) = 0 // если пустая строка then exit;
if (Length(LabeledEdit1.Text) = 1) and (LabeledEdit1.Text = '-')
then exit;
n:= StrToInt(LabeledEdit1.Text); LabeledEdit2.Text:= IntToStr(n); exit;
end;
{разрешаем только цифры, знак минус и кл. BackSpace } if not (Key in ['0' .. '9', '-' , #8]) then
begin Key:= #0;
539
6.3 Визуальное программирование в среде Lazarus
____________________________________________________________________
exit;
end;
if (Key = '-') and (sign) then
begin
if (LabeledEdit1.SelStart <> 0) then
begin Key:= #0; exit;
end else
if (Pos('-', LabeledEdit1.Text) <> 0) then Key:= #0;
end;
sign:= true; end;
procedure TForm1.Button1Click(Sender: TObject); begin
LabeledEdit1.SetFocus; sign:= false;
if Length(LabeledEdit1.Text) = 0 // если пустая строка then exit;
if (Length(LabeledEdit1.Text) = 1)and (LabeledEdit1.Text = '-')
then exit else
n:= StrToInt(LabeledEdit1.Text);
540