Так случилось, что пришлось сесть за комп, открыть Delphi и писать программу, не коммерческого, но, можно сказать, массового использования. Сие творение будет представлять из себя лабораторную работу для студентов изучающих процессы в оптоволокне.
В ходе работы потребуется вводить различные значения. Но студент не будет студентом если не введёт что-то другое, нежели указано в методическом указании. Вот собственно я и задался проблемой обломать студентов и перекрыть им возможность всяких буковок и прочей фигни...
Первый вариант был достаточно прост и удобен. Решил я все сделать по событию OnKeyPress. Все вроде бы просто, смотришь, что было уже написано, определяешь, где находится курсор, вставляешь туда символ который нажали. Полученный текст прогоняешь процедурой val(s,a,r), где s - наша получившаяся строка, а число которое процедура смогла выцепить и r - номер символа на котором процедура споткнулась. И если либо a не удовлетворяет условию, либо r больше нуля присваиваешь переменной Key #0.
Все работало удивительно, за исключением маленькой проблемки. Нельзя было стереть лишние символы. Но это просто решалось добавлением условия, что вести обработку только тех символов, которые больше равны пробела. Но счастье длилось не долго. Я забыл про такую комбинацию клавиш как ctrl+V, которая вставляла в поле все, что хотела, хоть войну и мир.
Делать нечего. Надо думать над вторым вариантом. И вторым вариантом стала обработка события OnChange. У этого события есть один недостаток. Оно ничего не возвращает, то есть не говорит что нового появилось и не помнит что было. Вот Вам мол что есть с этим и работайте, раньше точно было другое. Это проблема устраняется вводом новой переменной, которая бы запоминала предыдущее состояние поля. Я взял эту переменную типа real. Ну а дальше опять же val.
Но как оказалось и тут промашка. При попытке ввести отрицательные значения например и нажатии двух минусов подряд, значение в поле сбрасывает в предыдущее реальное значение, то есть 0, хотя вроде как предыдущим-то должно быть "-". Такая же бодяга и с точками. Выход из этой ситуации сделать переменную предыдущего статуса текстового типа, но мне данный вариант не понравился. Либо оставлять VAL еще и на событии OnKeyPress. Что мне тоже не понраву, так как если много полей и для каждого свои условия, то исходный код программы разрастается ужасно много.
В общем время потеряно. А проблема осталась. Но в принципе-то работать можно. Студенты со нормальной длиной носа лишнего ничего не введут, а вот длинноносым будет хуже при сдаче лабораторной ;)
P.S. Вот как-то так:
var s:string;
r:integer;
a:real;
begin
begin
s:=(Sender as Tedit).Text;
if (s<>'') then
begin
val(s,a,r);
if (r>0)or(a<0)or(a>=2000)or(length((Sender as tedit).Text)>5) then
begin
(Sender as Tedit).Text:=floattostr(L);
(Sender as Tedit).SelStart:=length((Sender as Tedit).Text);
end else l:=a;
end
else L:=0;
end;