Форум программистов, компьютерный форум, киберфорум
Delphi для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.57/148: Рейтинг темы: голосов - 148, средняя оценка - 4.57
1 / 1 / 1
Регистрация: 10.12.2009
Сообщений: 22
1

Как создать свое событие для своего класса?

15.12.2009, 15:40. Просмотров 30994. Ответов 12
Метки нет (Все метки)

Добрый день всем!
Подскажите как создать событие для своего класса? Экземпляр класса должен реагировать на
определенные события, обработчик которых вызывается при определенных условиях. Познания не очень обширны, по сему не знаю как это реализуется.
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
15.12.2009, 15:40
Ответы с готовыми решениями:

Как отловить событие для своего класса?
класс: TSomeClass = class(TObject) procedure OnKeyDown(var Message); message WM_KEYDOWN; end;...

Событие для своего класса
Я зоздал класс TPeople и класс TTrafficlight. Сответственно создал код: type TPeople=class ...

Событие onCick для своего класса
Можно ли для своего класса (без родительского) создать событие onClick или любое другое событие с...

Как создать свое событие?
В общем суть такая: есть абстрактный класс фигуры, и три производных от него. На экране (...

12
13057 / 5843 / 1705
Регистрация: 19.09.2009
Сообщений: 8,807
15.12.2009, 17:52 2
Лучший ответ Сообщение было отмечено как решение

Решение

Стандартный подход такой:
Определяем новый класс: TMyClass. И добавляем в него механизм работы с событием MyEvent.
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
unit uMyClass;
 
interface
 
uses
  Classes, Dialogs;
 
type
 
  TMyClass = class
  private
    FName : String;
    //...
    //Поле ссылающееся на обработчик события MyEvent.
    //Тип TNotifyEvent описан в модуле Clases так: TNotifyEvent = procedure(Sender: TObject) of object;
    //Фраза  "of object" означает, что в качестве обработчика можно назначить только метод какого-либо
    //класса, а не произвольную процедуру.
    FOnMyEvent : TNotifyEvent;
    //...
  protected
    //...
    //Эта процедура проверяет задан ли обработчик события. И, если задан, запускает его.
    procedure DoMyEvent; dynamic;
  public
    //...
    //Это свойство позволяет назначить обработчик для обработки события MyEvent.
    property OnMyEvent : TNotifyEvent read FOnMyEvent write FOnMyEvent;
    //...
    //Процедура, которая принимает решение - произошло событие MyEvent или нет.
    //Таких процедур может быть несколько - везде где может возникнуть событие MyEvent.
    //Если событие MyEvent произошло, то вызвается процедура DoMyEvent().
    procedure GenericMyEvent;
    //...
    //Имя экземпляра класса.
    property Name : String read FName write FName;
    //...
  published
    //...
  end;
 
implementation
 
{ TMyClass }
 
procedure TMyClass.DoMyEvent;
begin
  //Если обработчик назначен, то запускаем его.
  if Assigned(FOnMyEvent) then FOnMyEvent(Self);
end;
 
procedure TMyClass.GenericMyEvent;
var
  MyEventIsOccurred : Boolean;
  //...
begin
  //...
  MyEventIsOccurred := True;
  //Если верно некоторое условие, которое подтверждает, что событие MyEvent
  //произошло, то делаем попытку запустить связанный обработчик.
  if MyEventIsOccurred then begin
    DoMyEvent;
  end;
  //...
end;
 
end.
Модуль с формой (TForm), в котором тестируется механизм событий класса TMyClass.
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls
 
  ,uMyClass;
 
type
 
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    
    //Обработчик события MyEvent для объектов, принадлежащих типу TMyClass.
    procedure MyObjectMyEvent(Sender : TObject);
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
{ TForm1 }
 
//Обработчик события MyEvent для объектов, принадлежащих типу TMyClass.
procedure TForm1.MyObjectMyEvent(Sender: TObject);
var
  MyObj : TMyClass;
begin
  if not (Sender is TMyClass) then Exit;
 
  MyObj := Sender as TMyClass;
  ShowMessage('Событие MyEvent произошло! Имя объекта, который породил событие: ' + MyObj.Name);
end;
 
procedure TForm1.Button1Click(Sender: TObject);
var
  MyObj1, MyObj2, MyObj3 : TMyClass;
begin
  //Создаём экземпляры класса TMyClass.
  MyObj1 := TMyClass.Create;
  MyObj1.Name := 'MyObj1';
  MyObj2 := TMyClass.Create;
  MyObj2.Name := 'MyObj2';
  MyObj3 := TMyClass.Create;
  MyObj3.Name := 'MyObj3';
 
  //Для MyObj1 и MyObj2 назначаем обработчики события MyEvent.
  MyObj1.OnMyEvent := MyObjectMyEvent;
  MyObj2.OnMyEvent := MyObjectMyEvent;
 
  //Работаем с экземплярами класса. При этом в каждом из экзепляров
  //возникает событие MyEvent.
 
  MyObj1.GenericMyEvent;
  MyObj2.GenericMyEvent;
 
  //При выполнении метода MyObj3.GenericMyEvent, событие MyEvent наступит, но оно
  //не будет обработано процедурой MyObjectMyEvent, т. к., ранее, мы не назначили её в качестве
  //обработичика события MyEvent для экземпляра MyObj3.
  MyObj3.GenericMyEvent;
 
  MyObj1.Free;
  MyObj2.Free;
  MyObj3.Free;
end;
 
end.
Возможно я замудрёно объяснил тут. Можно сделать проще. И тип обработчика события не обязательно должен быть TNotifyEvent. Можно свой тип создать. TNotifyEvent - обработчик этого типа обязательно должен являться методом какого-либо класса. Можно объявить свой тип обработчика, без этого ограничения.
В приложенном архиве рабочий код.
5
Вложения
Тип файла: rar MyEvent.rar (171.3 Кб, 689 просмотров)
1 / 1 / 1
Регистрация: 10.12.2009
Сообщений: 22
16.12.2009, 10:07  [ТС] 3
Спасибо большое. Буду разбираться.
0
1 / 1 / 2
Регистрация: 03.06.2015
Сообщений: 98
03.06.2015, 23:55 4
а можно еще параметры ему передать? дело в том, что создаю динамически панели, ну и по нажатию, нужно в определенную переменную писать конкретную строку.. как это можно реализовать?
0
пофигист широкого профиля
4269 / 2794 / 790
Регистрация: 15.07.2013
Сообщений: 16,194
04.06.2015, 00:51 5
Цитата Сообщение от ptytb1 Посмотреть сообщение
а можно еще параметры ему передать?
Кому ему? Классу?
Цитата Сообщение от ptytb1 Посмотреть сообщение
дело в том, что создаю динамически панели, ну и по нажатию, нужно в определенную переменную писать конкретную строку.
Ну и пиши. Но в своей пользовательской программе. Классы/компоненты то тут при чем? Они ничего не знают и главное ничего не должны знать о программе, в которой их используют.
0
Продавец времени
4732 / 2574 / 583
Регистрация: 12.03.2015
Сообщений: 12,530
04.06.2015, 01:23 6
Цитата Сообщение от ptytb1 Посмотреть сообщение
а можно еще параметры ему передать? дело в том, что создаю динамически панели, ну и по нажатию, нужно в определенную переменную писать конкретную строку.. как это можно реализовать?
заменить TNotifyEvent на другой тип (можно на свой) - с аргументами. могу навалить кучу примеров из своих прожэктов. но утром, щас - спать.
0
пофигист широкого профиля
4269 / 2794 / 790
Регистрация: 15.07.2013
Сообщений: 16,194
04.06.2015, 01:28 7
Цитата Сообщение от Verevkin Посмотреть сообщение
заменить TNotifyEvent на другой тип (можно на свой) - с аргументами. могу навалить кучу примеров из своих прожэктов
А может не надо портить новичков? И не надо плодить монстров?

Добавлено через 2 минуты
Свой класс/компонент, если он ДСП, не очень то и нужен. Всю функциональность можно реализовать в самой программе.
0
1 / 1 / 2
Регистрация: 03.06.2015
Сообщений: 98
04.06.2015, 09:43 8
делал вот так, создавал процедуру с константой procedure opendialog(const Name: t componentName); и при создании очередной панели на событие онклик вешал эту прцседуру NewPanel.OnClick:=opendialog(NewPanel.name); но делфи сильно ругался и выдавал ошибки
Вот одна из них
[dcc32 Error] Unit1.pas(180): E2010 Incompatible types: 'TNotifyEvent' and 'procedure, untyped pointer or untyped parameter'

Добавлено через 1 час 13 минут
проще говоря у каждой панели есть имя содержащее в себе айди, мне нужно по нажатию на конкретную панель получать именно ее айди (айди можно записать в тег, но я пока с именем делаю)
0
13057 / 5843 / 1705
Регистрация: 19.09.2009
Сообщений: 8,807
04.06.2015, 10:10 9
Цитата Сообщение от ptytb1 Посмотреть сообщение
делал вот так, создавал процедуру с константой procedure opendialog(const Name: t componentName); и при создании очередной панели на событие онклик вешал эту прцседуру NewPanel.OnClick:=opendialog(NewPanel.name); но делфи сильно ругался и выдавал ошибки
TPanel.OnClick принадлежит типу TNotifyEvent. Этот тип определён так:
Delphi
1
type TNotifyEvent = procedure (Sender: TObject) of object;
Т. е., это процедура-метод, а не самостоятельная процедура. И этот метод должен иметь один параметр указанного типа. Компилятор в сообщении об ошибке пишет об этом несовпадении типов:
Цитата Сообщение от ptytb1 Посмотреть сообщение
[dcc32 Error] Unit1.pas(180): E2010 Incompatible types: 'TNotifyEvent' and 'procedure, untyped pointer or untyped parameter'
"Несовместимые типы: 'TNotifyEvent' и 'процедура, нетипизированный указатель или нетипизированный параметр'".
Цитата Сообщение от ptytb1 Посмотреть сообщение
делал вот так, создавал процедуру с константой procedure opendialog(const Name: t componentName);
В данном случае новый обработчик не нужен. Потому, что сведения об объекте, который вызвал этот обработчик (в том числе его имя), можно получить через параметр Sender, который передаётся в обработчик типа TNotifyEvent.
Пример:
Delphi
1
2
3
4
5
6
7
procedure TForm1.Panel1Click(Sender: TObject);
var
  Panel : TPanel;
begin
  Panel := Sender as TPanel;
  ShowMessage('Обработчик TForm1.Panel1Click() вызвал компонент с именем: ' + Panel.Name);
end;
Если обработчик может быть назначен компонентам разных типов, тогда так:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
procedure TForm1.Panel1Click(Sender: TObject);
var
  Cmp : TComponent;
  Panel : TPanel;
begin
  //Если в проекте обработчик мог быть назначенным разным типам компонентов (а не только экземплярам TPanel).
  Cmp := Sender as TComponent;
  ShowMessage('Обработчик TForm1.Panel1Click() вызвал компонент типа ' + Cmp.ClassName
    + ' с именем: ' + Cmp.Name);
 
  //Если экземпляр принадлежит классу TPanel или его потомку, то выполняем какие-то специальные действия:
  if Sender is TPanel then
  begin
    Panel := Sender as TPanel;
    if Panel.Color <> clRed then
      Panel.Color := clRed
    else
      Panel.Color := clGreen;
    ShowMessage('Изменён цвет панели.');
  end;
end;
1
Продавец времени
4732 / 2574 / 583
Регистрация: 12.03.2015
Сообщений: 12,530
04.06.2015, 10:23 10
Цитата Сообщение от northener Посмотреть сообщение
Свой класс/компонент, если он ДСП, не очень то и нужен.
а я про класс не говорил.
я говорил про тип события.
Если я правильно понял автора, ему в обработчик события надо что-то передавать изнутри класса наружу.
Delphi
1
2
3
4
type TNotifyEvent = procedure (Sender: TObject) of object; // простой обработчик
type TMyShitEvent1 = procedure (Sender: TObject; const Param: <тип_параметра>)  of object; // не совсем простой обработчик
type TMyShitEvent2 = procedure (Sender: TObject; var Param: <тип_параметра>)  of object; // не совсем простой обработчик
type TMyFuncEvent = function (Sender: TObject<; другие параметры>): <тип> of object; // и даже так можно!
0
1 / 1 / 2
Регистрация: 03.06.2015
Сообщений: 98
04.06.2015, 11:11 11
Цитата Сообщение от Mawrat Посмотреть сообщение
Пример:
огромное спасибо!! работает хорошо)
0
0 / 0 / 0
Регистрация: 13.05.2014
Сообщений: 36
16.10.2018, 08:16 12
Судя по количеству сообщений galdora на форуме, он таки не разобрался.Жестокий пример) А можно примерчик по-проще?
0
3476 / 2967 / 799
Регистрация: 29.08.2013
Сообщений: 19,872
Записей в блоге: 1
16.10.2018, 20:30 13
Цитата Сообщение от Vinder Посмотреть сообщение
А можно примерчик по-проще?
пример чего?
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
16.10.2018, 20:30

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

Как создать своё событие, к которому можно обращаться с другого события.
Подскажите как создать событие с определёнными операциями внутри, к которому можно обратиться через...

Как создать событие event которое можно изменить для конкретного экземпляра класса?
создал свой класс MyDGV и создал в нем событие BeforeLoad и AfterLoad например Friend Event...

Создать свое событие
Ребята помогите пожалуйста, мне нужно создать собственное событие. Вот к примеру можно сделать так,...

Как создать объект своего класса в билдере?
Написал в билдере класс class Point { public: Point() ; void DrawPoint(float, float);...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.