Параметр Sender Delphi

ПараметрSender у Delphi-програмі є у кожному обробнику подій будь-якого компонента. Однак, оскільки у використанні параметра Sender часто не потрібно, новачки про нього "забувають" і часто навіть не здогадуються про його призначення. У цій статті я хочу розповісти про те, для чого призначений параметрSender Delphi і як працювати з таким, як виявляється, важливим і зручним параметром як Sender.

Sender має тип TObject і має значення об'єкта - джерела події, в обробнику якого він використовується. Тобто, якщо на Формі знаходиться кілька однакових компонентів, які до того ж виконують однакові функції, то немає необхідності для кожного з них створювати свої процедури-обробники подій. Цілком достатньо одного комплекту обробників, а з'ясувати, до якого компонента відноситься подія оброблювана саме зараз, дозволить саме параметр Sender.

ifSender = Button1thenCaption:='Клацання за кнопкою №1'elseCaption:='Клацання за кнопкою №2' ;

Програма покаже, за якою саме кнопкою було клацання. Ну а знаючи це, можна передбачити подальшу реакцію програми.

Це ще не все! Працюючи з параметром Sender, можна обійтися навіть без з'ясування імені компонента-джерела. Наприклад, завдання таке: ми повинні стежити за властивістю Text декількох компонентів Edit і при появі в будь-якому з них символу ',' (кома) міняти його на '.' (крапка). Створіть такий обробник події OnChange для одного з Edit'ів, а іншим просто зіставте, як у попередньому випадку:

Насамперед зауважимо, що слово Edit1 написано багато разів, що насправді зайве. За допомогою оператора приєднанняwithпозбавимося необхідності писати Edit1 всередині операторів:

Всі! Тепер дляЩоб позбутися від ком у всіх Edit'ах, потрібно замінити в операторі приєднання Edit1 на (SenderasTEdit) - краще ось так, у дужках. Справа в тому, що конструкція (SenderasTObject) дозволяє працювати з джерелом події як з відповідним об'єктом. Зокрема, якщо після (SenderasTEdit) поставити крапку, Delphi видасть нам список властивостей і методів компонента Edit. Хоча, за особисто моєю логікою, замість (Sender as TEdit) досить було б просто Sender. Та ні, не виходить.

Тепер ви розумієте, чому ми позбулися Edit1 всередині операторів - замінювати кожен Edit1 на (SenderasTEdit) було б важко!

Зрештою, іноді буває необхідно з'ясувати не ім'я, а тип джерела події. У цьому допоможе операторis, за допомогою якого параметр Sender можна порівняти з одним із типів Delphi:

if(SenderisTButton)thenCaption:='Джерело події - кнопка TButton';

До речі, щодо використаного вище способу заміни комою на точку. Замість замінювати їх у тексті рядка, набагато зручніше робити це прямо "на льоту", використовуючи процедуру OnKeyPress:

procedureTForm1.Edit1KeyPress(Sender: TObject; var Key: Char);beginifKey=','thenKey:='.';end;

Чому я одразу не використовував цей спосіб? Тому що тут взагалі не використовується параметр Sender! Хоча працювати ця процедура також буде всім компонентів, яким вона зіставлена. Але вчитеся бачити різні можливості, колись і перший спосіб стане в нагоді. І взагалі, навчайтеся.

Огляд компонентів Delphi На початок уроку Компонент Delphi SpeedButton

if Sender=Label2 then Caption:='Був стерт Label2'; else Caption:='Був стертий lb';

Яж це показав у статті, чи читали її? Порівняйте:

if Sender = Button1 then Caption:='Клацання за кнопкою №1' else Caption:='Клацання за кнопкою №2';Ольга,додано 29.05.12, 11:40:00 Я це читала. Загвоздка в тому що lb буде не один при кожному натисканні кнопки створюється новий і якщо надавати кожному ім'я з цифрою або використовувати tag все одно запам'ятовується останній, а як зробити щоб програма дізнавалася який lb був стертий перший другий або наприклад третій із створених?Автор,додано 29.05.12, 12:08:37 Не розумію. Sender вказує на джерело, яка різниця який він за рахунком? З'ясувати, що за компонент – не проблема. І навіть через Tag, чому ні? А ви куштували, чи умоглядно сумніваєтесь?Ольга,додано 29.05.12, 12:17:33 Пробувала. не виходить. якщо було створено 5 компонентів lb потім праю один з них і в Label2.caption хочу щоб написав lb.tag стертого він пише останній тобто 5 а не один або 2 який був стертАвтор,додано 29.05.12, 12:30:41 Давайте, скопіюйте сюди процедури створення компонентів і натискання на них, я скопіюю собі і подивимося разом що не так.Автор,додано 29.05.12, 12:45:24 Скасувати. Взагалі не розумію, в чому проблема. Ось я не створював, просто поставив 5 лабелів, кожному тагу від 1 до 5. Процедура OnDblClick:

Caption: = IntToStr ((Sender as TLabel). Tag);Ольга,додано 29.05.12, 12:47:06 var lb:Tlabel;b:boolean;i:byte; procedure TForm1.SpeedButton1Click(Sender: TObject); begin lb:=tlabel.Create(self); lb.Parent:=self; lb.Font.Color:=clnavy; lb.Font.Name:='Arial'; lb.Font.Size:=26; lb.Caption:='('; inc(i); іf b then lb.Tag:=i-1 else lb.Tag:=i; lb. OnDblClick:=label1.OnDblClick; lb.Left:= 20+random(100); lb.Top:=20+random(100);

procedure TForm1.Label1DblClick(Sender: TObject); begin b:=true; якщо sender is Tlabel then begin tlabel(sender).Visible:=false; label1.Caption:=inttostr(lb.tag); end else label1.Caption:='net'; end;

procedure TForm1.FormCreate(Sender: TObject); begin b:=false; i:=0; end;

end.Автор,додано 29.05.12, 13:02:46 Все ясно. Проблема в тому, що у вас всі лабелі створюються однією змінною, і фактично ви надаєте таг не компоненту, а цій змінній lb. Звісно, ​​вона й матиме останній таг. А зникнення ви робите не цією змінною, а саме компонента типу TLabel - джерела події, тому це виходить.Ольга,додано 29.05.12, 13:05:54 А як привласнювати таг компоненту в моєму випадку?Автор,додано 29.05.12, 13:21:02 Підемо методом послідовного наближення 1. Привласнювати треба ж не змінною а компоненту, який ви створили. А звернення до компонента відбувається ЗАВЖДИ із зазначенням його імені. 2. Або використовувати для кожного компонента власну змінну. Але і тоді ви використовуватимете таг не компонента а змінної, просто вони збігатимуться.Ольга,додано 29.05.12, 13:36:59 А конкретніше можна? в моєму випадку мені змінювати створювати вектор змінних, але і тоді буде запам'ятовуватися кінцева змінна. Допоможіть будь ласка!Ольга,додано 29.05.12, 13:57:10 з вектором теж не виходитьОльга,додано 29.05.12, 14:24:45 як привласнювати компоненту ? lb із змінної після рядків lb:=tlabel.Create(self); lb.Parent:=self; стає компонентом логічно? чи ні? і що робити? куди та як привласнювати?Автор,додано 29.05.12, 15:14:18 Створюється динамічний масив - ви ценазиваєте вектором? Ну хай.

var lb: Array of Tlabel;

Втім, вам весь проект. Тільки не копіюйте сліпо, а подивіться в чому різниця:

var Form1: TForm1; b:boolean;i:byte; lb: Array of Tlabel;

procedure TForm1.Button1Click(Sender: TObject); begin SetLength(lb, i+1); lb[i]:=tlabel.Create(Self); lb[i].Parent:=Self; lb[i].Font.Color:=clnavy; lb[i].Font.Name:='Arial'; lb[i].Font.Size:=26; lb[i].Caption:='('; if b then lb[i]. [i].OnDblClick:=label1.OnDblClick; lb[i].Left:= 20+random(100); lb[i].Top:=20+random(100); inc(i); end;

procedure TForm1.Label1DblClick(Sender: TObject); begin b:=true; if (sender is Tlabel) then begin tlabel(sender).Visible:=false; label1.Caption:=inttostr(tlabel(sender).tag); end else label1.Caption:='net'; end;Ольга,додано 29.05.12, 16:07:13 Дякую! я не списувала тупо. у моєму масиві були дві помилки, і я їх виправила! setlength(lb,10) на setlength(lb,i-1) але це не таке велике завантаження було в цьому: label1.Caption:=inttostr(i-1);я афіщувала тільки і label1.Caption:=inttostr(tlabel( sender). Tag); Дякую велике! і вибачте за занепокоєння!Ольга,додано 29.05.12, 16:33:04 до речі знищувати компонент цим же способом не виходить!чи тільки у мене? видає помилку Access violation of adress. if (sender is Tlabel) then tlabel (sender). Free; і це теж if (sender is Tlabel) then freeandnil(tlabel(sender));Автор,додано 29.05.12, 17:36:24 Так, щось нічого поки не виходить. Так що вам дякую - думатиму. Як придумаю - допишу спосіб знищення статті "Динамічне створення компонентів". А то там поки що теж Free, а це виявляється накомпоненти створені у масиві не діє. Точніше, діє - компонент знищується, але відразу з'являється непереборна помилка.Ольга,додано 29.05.12, 17:51:26 Дякую! Ваші статті дуже допомагають!Автор,додано 29.05.12, 19:49:34 Щодо знищення компонентів. Помилка виникає тому, що "не можна знищувати компонент у його події" - цитую відповідь на програмістському форумі. Тому беремо таймер, передаємо в нього по клацанню параметр Tag, а з його спрацьовування розшукуємо на Формі компонент типу TLabel з Tag'ом рівним переданому - і знищуємо.Євген,додано 1.06.12, 08:09:51 на сайті статті дуже корисні, але чи можете ви мені допомогти в такій ситуації: я створив динамічно кнопки і у них є порядкові номери (масив) ось як би мені дізнатися індекс тієї кнопки, на яку я натиснув? що потрібно напсати для процедури proc: