Delphi function

  • Автор темы Streamdown
  • Обновлено
  • 17, Dec 2005
  • #1
Всем привет! У меня такой вопрос: есть обработка ввода в Edit:
procedure TToch.xKeyPress(Sender: TObject; var Key: Char);
begin
Case Key of
'0'..'9', #8:;
'.',',':
begin
Key := DecimalSeparator;
if pos (DecimalSeparator, x.Text) <> 0
then Key := Char(0);
end;
else Key := Char(0);
end;
end;
(Таких Edit-ов у меня штук 30) Можно ли вынести эту обработку как функцию, и потом просто везде ее вызывать? Или тогда как бороться с обращением (то что подчеркнуто) на конкретный Edit?

Streamdown


Рег
28 Feb, 2005

Тем
76

Постов
224

Баллов
634
  • 18, Dec 2005
  • #2
Можно, только это надо сделать процедурой, а не функцией (хотя в коде стоит именно процедура ). А вместо конкретного Edit-а используй Sender (только его надо к Edit-у привести). Т.е. замени везде конкретный Edit на TEdit(Sender). Ну а потом вызывай свою процедуру, передавая ей в Sender нужный Edit.

Удачи.
 

Ognev


Рег
20 Aug, 2004

Тем
76

Постов
294

Баллов
684
  • 29, Dec 2005
  • #3
Если создаешь Edit'ы динамически, то можно так: <Имя_Edit'a>.OnKeyPress:=<Твоя_Собственная_Процедура-Обработчик>
 

N3tM4n


Рег
10 Oct, 2005

Тем
93

Постов
195

Баллов
690
  • 20, Feb 2006
  • #4
Так процедура-то уже есть. Надо ее этим 30 Edit-ам назначить и все... Хоть в design-time, хоть в run-time
 

Hans_Cristian


Рег
09 Aug, 2004

Тем
85

Постов
193

Баллов
688
  • 21, Feb 2006
  • #5
Hans_Cristian:назначить и все
А как назначить? Если отдельно вынести - нужно как-то перечислить все Edit-ы.
 

Streamdown


Рег
28 Feb, 2005

Тем
76

Постов
224

Баллов
634
  • 21, Feb 2006
  • #6
Если совсем все, то можно в RunTime так:
 
var 
 i, h: integer;
 q: TEdit;
...
 with TToch do begin 
 for i:=0 to ComponentCount-1 do begin
 if Components[i] is TEdit then begin
 q:=Components[i] as TEdit;
 q.OnKeyPress:=TToch.xKeyPress;
 end;
 end;
 end;
...
Не забудь X в обработчике заменить на (Sender as TEdit)!
 

Ploki


Рег
16 May, 2005

Тем
73

Постов
194

Баллов
569
  • 21, Feb 2006
  • #7
так, еще раз...извините если че не так писал ранее:

Есть функция:

 function goblin(Sender: TObject; var Key: Char): Char;
var 
 vrPos, vrLength, vrSelStart: byte;
const
 I: byte = 1;
 begin

 with Sender as TEdit do
 begin
 vrLength := Length(Text);
 vrPos := Pos(',', Text); 
 vrSelStart := SelStart; 
 end;

 case Key of

 '0'..'9':
 begin
 if (vrPos > 0) and (vrLength - vrPos > I) and (vrSelStart >= vrPos) then
 Key := #0;
 end;
 ',', '.':
 begin
 if (vrPos > 0) or (vrSelStart = 0) or (vrLength = 0) then
 Key := #0
 else
 Key := #44; 
 end;
 #8: ; 
 else
 Key := #0;
 end;
end;


Как и с какими параметрами мне ее надо вызывать для конкретного Edit-а?

 procedure TToch.TKeyPress(Sender: TObject; var Key: Char);
begin
goblin([B][SIZE="3"]???????????[/SIZE][/B]);
end;
 

Streamdown


Рег
28 Feb, 2005

Тем
76

Постов
224

Баллов
634
  • 21, Feb 2006
  • #8
А зачем эту функцию в обработчике вызывать, если её можно сделать методом и тогда она сама и будет обработчиком? Она же ничего не возвращает?

То есть в классе TToch (насколько я понял, это форма) описать:

TTouch=class(TForm)

...

procedure goblin(Sender: TObject; var Key: Char);

...

end;

Затем можно хоть в инспекторе объектов, хоть в RunTime присваивать эту процедуру свойству OnKeyPress любого компонента.

Если же ты хочешь всё таки иметь отдельный обработчик для каждого TEdit'а, то вызывать её надо с параметрами goblin(Sender, Key). Но ведь получится куча лишнего кода?! И всё равно не понятно, почему она функция.

P.S. Замени типы byte на Integer.

И скорость повысишь (поможешь оптимизатору и избежишь кучи преобразований типов), и от возможных ошибок убережёшься.
 

Ploki


Рег
16 May, 2005

Тем
73

Постов
194

Баллов
569
  • 21, Feb 2006
  • #9
streamdown, тебе вроде как уже раза три тут все объяснили То, что ты пытаешься сделать функцией, нужно сделать процедурой, конкретный Edit ей везде передавать через Sender.

Единственное замечание.

Подумай, стоит ли обрабатывать KeyPress! Вот помини мое слово, обязательно найдется умник, который тебе влепясит в Edit чего-нибудь через буфер обмена Я бы сделал обработку уже окончательно введенного в Edit текста.

Хотя, все зависит от того, что нужно.
 

Ognev


Рег
20 Aug, 2004

Тем
76

Постов
294

Баллов
684
  • 08, Mar 2006
  • #10
Подумай, стоит ли обрабатывать KeyPress! Вот помини мое слово, обязательно найдется умник, который тебе влепясит в Edit чего-нибудь через буфер обмена
Так можно сделать удаление в Edit.Text ненужных символов в обработчике на событие OnChange.
 

N3tM4n


Рег
10 Oct, 2005

Тем
93

Постов
195

Баллов
690
  • 11, Mar 2006
  • #11
Можно, но зачем? По мне, правильнее было бы обрабатывать все введенное один раз, непосредственно перед использованием.

Разница - введен текст в 100 символов, при обработке на OnChange ты будешь проделывать обработку минимум сто раз (если он все правильно сразу ввел, а не правил много раз), а так - один.
 

Ognev


Рег
20 Aug, 2004

Тем
76

Постов
294

Баллов
684
  • 14, Mar 2006
  • #12
N3tM4n:Да можно как хочешь сделать =) Это дело вкуса.
Ognev прав - эконимия проц.времени .Код хорош токо когда он оптимизирован и полностью безглючно исполняет свою функцию
 

Lord Phoenix


Рег
10 Mar, 2006

Тем
74

Постов
220

Баллов
590
  • 11, May 2011
  • #13
streamdown, post: 534408:Всем привет! У меня такой вопрос:
есть обработка ввода в Edit:

(Таких Edit-ов у меня штук 30) Можно ли вынести эту обработку как функцию, и потом просто везде ее вызывать? Или тогда как бороться с обращением (то что подчеркнуто) на конкретный Edit?
обрабатывай senser
 

VVThanatos


Рег
11 May, 2011

Тем
81

Постов
167

Баллов
612
  • 28, May 2012
  • #14
1. Создаешь свою процедуру обработки данных в TEdit, например:

procedure AnalyseDataInEdit(aTargetEdit: TEdit; aText: String);

2. Объявляешь в форме 2 глобальные переменные:

varDataStr: String;

varCurrentControl: TEdit;

3. Создаешь для одного из своих Edit-ов метод edtMainFieldOnChange(Sender: TEdit);

4. В этом методе присваиваешь некоторой своей глобальной переменной текст из Edit-a, например:

procedure TfrmToch.edtMainFieldOnChange(Sender: TObject);

begin

varDataStr := edtMainField.Text; // Запоминаем текст в глобальной переменной.

varCurrentControl := TEdit(Sender);// Запоминаем сработавший TEdit в пеерменной.

tmrCheckData.Enable := FALSE; // на форме располагаешь таймер с интервалом в

tmrCheckData.Enable := TRUE; // 500 и в его обработчике вызываешь метод...

end;

procedure TfrmToch.OnTimer(Sender: TObject);

begin

Timer.Enabled := FALSE; // отключаешь таймер на время его обработки.

if (varDataStr <> '') and (varCurrentControl <> nil)

then AnalyseDataInEdit(varCurrentControl: TEdit; varDataStr: String);

varCurrentControl := nil; // чистим переменную сработавшего контрола.

end;

Метод с таймера нужен для исключения обработок каждого введённого символа, если текст вводиться посимвольно.

Интервал сработки таймера можно регулировать на усмотрение.

4. Создаешь ещё одну процедуру, как упоминалось ранее, которая при активации формы пробегается по циклу (перебирает все компоненты на твоей форме и как только находит TEdit, то присваивает этому контролу на его метод OnChange тот, что ты создал уже в п.1.). При размещении на форме всех TEdit-ов, которые требуют обработки, хорошо бы в их Property "Tag" ставить значение, отличное от "0" и в цикле проверять ещё и это значение.

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

Agent smith


Рег
15 Jan, 2009

Тем
85

Постов
192

Баллов
667
  • 08, Jan 2014
  • #15
Глобальные переменные лучше не использовать. Запросто можно обойтись локальными.
 

Goga2


Рег
01 Feb, 2007

Тем
74

Постов
193

Баллов
593
Тем
403,760
Комментарии
400,028
Опыт
2,418,908

Интересно