Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.145.201.55] |
|
Сообщ.
#1
,
|
|
|
На форме содержиться несколько Edit и в каждом надо проверять вводимые символы (только цифры и минус).
Проблема в том, что я не знаю как оптимизировать код (громоздким не делать). Т.е. для каждого edit нужно писать вот этот кусочег кода case key of '0'..'9': ; '-' : if length(Edit1.Text)<>0 then key:=#0; else key:=#0; end; Можно, конечно, и сделать отдельную процедуру, в которую будем передавать вводимый символ и сам editN. вот так это будет: type TForm1 = class(TForm) Edit1: TEdit; Edit2: TEdit; Edit3: TEdit; procedure k1(Sender: TObject; var Key: Char); procedure k2(Sender: TObject; var Key: Char); procedure k3(Sender: TObject; var Key: Char); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} Procedure control(var ch: char; var edt: TEdit); begin case ch of '0'..'9': ; '-' : if length(edt.Text)<>0 then ch:=#0; else ch:=#0; end; end; procedure TForm1.k1(Sender: TObject; var Key: Char); begin control(key, Edit1); end; procedure TForm1.k2(Sender: TObject; var Key: Char); begin control(key, Edit2); end; procedure TForm1.k3(Sender: TObject; var Key: Char); begin control(key, Edit3); end; end. Нельзя ли как нибудь это упростить? хм, только щас заметил, а почему все заголовки процедур состоят только из TForm1.k*? а где же ещё название edit'a? разьве не должно быть так TForm1.Edit1k1(.....var key:char);? Событие onKeyPress обрабатывается. |
Сообщ.
#2
,
|
|
|
сдедай для одного Edit а всем остальным укажи тот же метод.
Цитата Continental @ хм, только щас заметил, а почему все заголовки процедур состоят только из TForm1.k*? а где же ещё название edit'a? разьве не должно быть так TForm1.Edit1k1(.....var key:char);? методы называются TForm1.CompanentNameMethode(Sender: TObject...........) |
Сообщ.
#3
,
|
|
|
Спасибо, что помогли. Я понял, впринципе, любому обекту можно один и тот же метод назначить.
Добавлено а как же тогда проверять длинну строки в edit'e? чтобы минус написать только первым и не "пять" раз есть вот такая проверка: procedure TForm1.contr(Sender: TObject; var Key: Char); begin case key of '0'..'9', #8: ; '-' : if length(Edit1.Text)<>0 then key:=#0; <------- length else key:=#0; end; end; И если несколько edit'oв пользуются одним методом, то что надо написать в Length(?) |
Сообщ.
#4
,
|
|
|
length(TEdit(Sender).Text)
|
Сообщ.
#5
,
|
|
|
[quote=Continental,1221139547,2066876]'-' : if length(Edit1.Text)<>0 then key:=#0; <------- length[/quote]
Параметр Sender это и есть Edit, в который вводится символ '-' : if length((Sender as TEdit).Text)<>0 then key:=#0; <------- length[/quote] PS: опоздал .. |
Сообщ.
#6
,
|
|
|
Если такая задача становится достаточно часто, то можно написать свой компонент - потомок от TEdit
|
Сообщ.
#7
,
|
|
|
А почему можно написать в скобках
Цитата Shaggy @ и с помощью asTEdit(Sender).Text Цитата leo @ Т.е. это где-то играет роль в каких-либо определённых случаях, или это просто такая обширность у языка?(Sender as TEdit).Text Цитата and85 @ Если такая задача становится достаточно часто, то можно написать свой компонент - потомок от TEdit Пока что мне до этого далеко. А вот можете пожалуйста помочь ещё с одним вопросом. В моём случае есть три edit'a и кнопка вычислить (сложить всё что во всех полях), причём если хоть один edit не заполнен - кнопка Button1.Enabled:=false; Я проверял поля при помощи onChange: procedure TFm_Tover.Pr(Sender: TObject); begin if Edt_name.Text<>'' then begin if Edt_price.Text<>''then begin if Edt_count.Text<>''then Btn_Calc.Enabled:=true else Btn_Calc.Enabled:=false; end else Btn_Calc.Enabled:=false; end else Btn_Calc.Enabled:=false; end; т.е. я с помошью if .. else проверял каждое поле и устанавливал кнопке значение Enabled. Вот только при трёх полях, алгоритм уже плохо читается. Есть какой-нибудь способ, чтобы сократить данный код? Тему новую не стал создавать, так как посчитал, что речь идёт почти про одно и то же, так что не сочтите мусором. |
Сообщ.
#8
,
|
|
|
для определённости:
1) TEdit(Sender) и 2) (Sender as TEdit) 1) a) стоит исползовать только если Sender - это именно TEdit(в данном случае) т.е. фактически это инструкция компилятору - "заткнись и делай, что велено..." б) никаких проверок не производится, и если на самом деле Sender это не TEdit, то в результате получищь кучу глуков - от: странное поведение программы, до AV 2) так называемое "безопасное приведение типов", т.е. производится проверка: Sender - это на самом деле TEdit? и если нет, возбуждается исключение EInvalidCast |
Сообщ.
#9
,
|
|
|
Цитата Shaggy @ никаких проверок не производится, и если на самом деле Sender это не TEdit, то в результате получищь кучу глуков - от: странное поведение программы, до AV А я видел как Sender использовался с Button. .... procedure TForm1.DigitBtnClick(Sender: TObject); var Btn: TButton; ch: Char; begin Btn := Sender as TButton; ch := Chr(48+Btn.Tag); ..... ...... это значит относится ко второму пункту ----> Цитата Shaggy @ 2) так называемое "безопасное приведение типов", т.е. производится проверка: Sender - это на самом деле TEdit? и если нет, возбуждается исключение EInvalidCast |
Сообщ.
#10
,
|
|
|
Continental думаю помочь решить проблему может написание собственого компонента с рассшренными возможностями по контролю ввода ...
з.ы.: в архиве прилагается мое видение решения данной проблемы ... Прикреплённый файлXPEdit.rar (8.88 Кбайт, скачиваний: 394) |
Сообщ.
#11
,
|
|
|
Цитата Continental @ Есть какой-нибудь способ, чтобы сократить данный код? Btn_Calc.Enabled:=(Edt_name.Text<>'') and (Edt_price.Text<>'') and (Edt_count.Text<>''); Хотя думается в данном случае лучше не дизэйблить кнопку, а вынести проверки в обработчик нажатия Btn_CalcClick и если один из эдитов не заполнен то выдавать сообщение или бип и переводить фокус на пустой эдит procedure TForm1.Btn_CalcClick(Sender: TObject); function IsEmpty(e:TEdit;const what:string):boolean; begin Result:=e.Text = ''; if Result then begin beep; MessageDlg('Введите значение: '+what,mtWarning,[mbOk],0); FocusControl(e); end; end; begin if IsEmpty(Edt_name,'Наименование') or IsEmpty(Edt_price,'Цена') or IsEmpty(Edt_count,'Количество') then Exit; ... end; |
Сообщ.
#12
,
|
|
|
Если начать сначала.
я так и не понял, как сделать чтоб в edit`ы можно было вводить только цифры??? в каком событии писать case ch of '0'..'9': ; '-' : if length(edt.Text)<>0 then ch:=#0; else ch:=#0; ???? и сразу же второе, как сделать это сразу для нескольких edit`ов? как работать с методами TForm1.CompanentNameMethode(Sender: TObject...........) ???? заранее спасибо ........пис |
Сообщ.
#13
,
|
|
|
Нужно создать один обработчик Edit1KeyPress и назначить его нескольким эдитам. Причем если в обработчике используется обращение к св-вам эдита (например Text), то для того, чтобы этот обработчик был универсальным, нужно вместо прямых ссылок типа edt.Text использовать (Sender as TEdit).Text
procedure TForm1.Edit1KeyPress(Sender:TObject;var Key:Char); begin if not (Key in ['-','0'..'9']) or (Key = '-') and (Length((Sender as TEdit).Text) <> 0) then Key:=#0; end; |
Сообщ.
#14
,
|
|
|
Есть маленькое замечание. Нигде не обрабатывается вставка из буфера винды. Тоесть, если у меня в буфере белиберда 'алдывраывлоарыдлаорывдлаорыва', то нажав Shift+Insert, я смогу эту бяку к себе в эдит вставить:)
P.S. У andrew.virus это похоже учитывается:) |
Сообщ.
#15
,
|
|
|
Минутку, а backspace? почему не работает? можно удалять только кнопкой "delete".??
Объясните пожалуйста, как сделать, чтоб в определенное количество едитов. можно было вводить только цифры, и стирать кнопкой backspace??? |
Сообщ.
#16
,
|
|
|
Цитата and85 @ Есть маленькое замечание. Нигде не обрабатывается вставка из буфера винды. Тоесть, если у меня в буфере белиберда 'алдывраывлоарыдлаорывдлаорыва', то нажав Shift+Insert, я смогу эту бяку к себе в эдит вставить:) Не сможешь. Цитата subsonic @ как сделать, чтоб в определенное количество едитов. можно было вводить только цифры, и стирать кнопкой backspace??? procedure TForm1.Edit1KeyPress(Sender:TObject;var Key:Char); begin if not (Key in [#8, '-','0'..'9']) or (Key = '-') and (Length((Sender as TEdit).Text) <> 0) then Key:=#0; end; |
Сообщ.
#17
,
|
|
|
Цитата subsonic @ можно было вводить только цифры, и стирать кнопкой backspace??? Просто добавить символ бэкспейса (#8) в число разрешенных if not (Key in [#8,'-','0'..'9']) Добавлено Цитата and85 @ Есть маленькое замечание. Нигде не обрабатывается вставка из буфера винды. Тоесть, если у меня в буфере белиберда 'алдывраывлоарыдлаорывдлаорыва', то нажав Shift+Insert, я смогу эту бяку к себе в эдит вставить:) P.S. У andrew.virus это похоже учитывается:) Проще добавить обработчик OnChange, чем городить спец.контрол, да еще и "с нуля" PS: Кстати виндовый стиль эдита ES_NUMBER также не отслеживает вставку "белиберды" из буфера обмена |
Сообщ.
#18
,
|
|
|
Backspace - символ #8. Просто допусти и его
|
Сообщ.
#19
,
|
|
|
Цитата Просто добавить символ бэкспейса (#8) а как узнать символы каждой кнопки на клаве? |
Сообщ.
#20
,
|
|
|
Цитата subsonic @ а как узнать символы каждой кнопки на клаве? Поставь брейкпойнт в обработчике, запусти прогу, и смотри, чему равен Key |
Сообщ.
#21
,
|
|
|
Символы - то, что написано. Плюс #7 - табуляция.
Остальные по кодам идут, это OnKeyUp обычно контролирует. VK_F1 и остальные |
Сообщ.
#22
,
|
|
|
Цитата Continental @ Есть какой-нибудь способ, чтобы сократить данный код? цикл сделать по коллекции ParControl.Controls, где ParControl - контрол на котором лежат Едиты (форма или панель, что там у вас) ParControl.ControlCount - кол-во дочерних контролов |
Сообщ.
#23
,
|
|
|
Цитата Romkin @ Плюс #7 - табуляция Вообще-то табуляция VK_TAB = #9 |
Сообщ.
#24
,
|
|
|
Цитата leo @ Вообще-то табуляция VK_TAB = #9 Ой. Точно. А 7 - это бип |
Сообщ.
#25
,
|
|
|
вообще то проще посмотреть в ASCII таблице
|
Сообщ.
#26
,
|
|
|
Вот, как раз только что делал такую штуку. Подумал-подумал, и решил, что для цифрового поля должны вводиться
1)Цифры 2)Backspase 3)Ну и стрелки назад-вперед, видимо - иначе представляю, как юзверь будет материться, вогнав длинную строку, и поняв, что сделал ошибку. И тогда то, что здесь описывалось, будет выглядеть так. unit klavishi; interface procedure klavishi1(var key:char); implementation procedure klavishi1 (var key:char); begin case key of '0'..'9':; chr(8),chr(37),chr(39):; else key:=Chr(0); end; end; end. До того, чтобы компонент писать, я вот пока не дошел. Но модуль отдельный как раз сделал - подключаешь его, и пишешь в событие поля ввода на OnKeyPress klavishi; |
Сообщ.
#27
,
|
|
|
Цитата inmast @ chr(8),chr(37),chr(39):; А при чем тут chr(37) - знак процента %, и chr(39) - одиночный апостроф ' Цитата inmast @ 3)Ну и стрелки назад-вперед, Стрелки назад-вперед это не символы, а управляющие клавиши. Поэтому в OnKeyPress они не попадают, только в OnKeyDown\OnKeyUp |
Сообщ.
#28
,
|
|
|
Еще вариант до кучи по мотивам темы
procedure TForm1.FormCreate(Sender: TObject); var J: Integer; begin for J := 0 to ComponentCount-1 do if Components[J] is TEdit then TEdit(Components[J]).OnKeyPress := klavishi1; end; procedure TForm1.klavishi1(Sender: TObject; var Key: Char); begin if not (Key in [#8 ,'-', '0'..'9', Chr(VK_DELETE), Chr(VK_LEFT), Chr(VK_UP), Chr(VK_RIGHT), Chr(VK_DOWN)]) then Key := #0; end; |
Сообщ.
#29
,
|
|
|
А не проще ли глобально для всех контролов что лежат на форме обрабатывать.
У формы на которой лежат контролы делаем KeyPreview := True и вешаем обработчик на OnKeyPress procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char); begin if not (Key in [#8 ,'-', '0'..'9', Chr(VK_DELETE), Chr(VK_LEFT), Chr(VK_UP), Chr(VK_RIGHT), Chr(VK_DOWN)]) then Key := #0; end; и не заморачеваемся с перебором класов и т.д. Хотя это от ситуации зависит. |
Сообщ.
#30
,
|
|
|
Цитата SourceUser @ if not (Key in [#8 ,'-', '0'..'9', Chr(VK_DELETE), Chr(VK_LEFT), Chr(VK_UP), Chr(VK_RIGHT), Chr(VK_DOWN)]) Угу, прежде чем ерунду писать сначала попробовал бы вывести все эти символы VK_.. в едит Etit1.Text:=Chr(VK_DELETE)+Chr(VK_LEFT)+Chr(VK_UP)+Chr(VK_RIGHT)+Chr(VK_DOWN); тогда бы сразу увидел что они означают: .%&'( Повторяю для непонятливых: Цитата leo @ Стрелки назад-вперед это не символы, а управляющие клавиши. Поэтому в OnKeyPress они не попадают, только в OnKeyDown\OnKeyUp а VK_... это не коды символов, а виртуальные коды клавиш клавиатуры |
Сообщ.
#31
,
|
|
|
Ну да, leo прав
Ну значит точно, делаем у формы KeyPreview := True и в OnKeyPress ловим тру символы, а в OnKeyDown управляющие клавиши. Вуаля |
Сообщ.
#32
,
|
|
|
Цитата SourceUser @ а в OnKeyDown управляющие клавиши. Вуаля А ты опять не прав Зачем вообще ловить управляющие клавиши, если нам не нужно их запрещать ?! По умолчанию они и так разрешены, и ограничение на ввод символов в OnKeyPress на них никак не влияет - зачем тогда вообще что-то ловить в OnKeyDown ?! |