Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.03.26;
Скачать: CL | DM;

Вниз

Как вызвать событие   Найти похожие ветки 

 
rds ©   (2005-09-20 21:07) [0]

В своем компоненте Определяю событие, как

 type TEvent=procedure(Sender:TObject)
....
 private
   fOnEvent: TEvent;
....
 published
   property OnEvent: TEvent read fOnEvent write fOnEvent

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


 
Sphinx ©   (2005-09-20 21:30) [1]

Может ошибусь, но кажется так
if Assigned(fOnEvent) then fOnEvent;


 
RDS ©   (2005-09-20 21:59) [2]

спасибо, сечас попробую


 
jack128 ©   (2005-09-20 22:02) [3]

rds ©   (20.09.05 21:07)
TEvent=procedure(Sender:TObject)

обычно события компонентов отпереляют как методы, а не процедуры: TEvent = procedure (Sender: Tobject) of object;
правда уже существует такой стандартный тип - TNotifyEvent;

вызов обычно делается так:

type
 TEsComponent = class(TComponent)
 private
   fEvent: TNotifyEvent; // обычно в название поля не в ключают приставку On
 protected
   procedure DoEvent; virtual; // обычно в название метода диспетчеризации включают приставку Do и этот метод делают виртуальным или динамическим
 published
   property OnEvent: TNotifyEvent read fOnEvent write fOnEvent;
 end;

{ TEsComponent }

procedure TEsComponent.DoEvent;
begin
 if Assigned(fEvent) tehn
   fEvent(Self);
end;


 
Юрий Зотов ©   (2005-09-20 22:37) [4]

> jack128 ©   (20.09.05 22:02) [3]

> этот метод делают виртуальным или динамическим

Обычно динамическим, т.к. методы диспетчеризации перекрываются нечасто, а в таком случае динамический метод дает тот же расход памяти, что и виртуальный, но работу ускоряет.


 
RDS ©   (2005-09-20 23:37) [5]

jack128 ©   (20.09.05 22:02) [3]
Конечно же TEvent = procedure (Sender: Tobject) of object; - моя вина, не правильно написал.


 
Leonid Troyanovsky ©   (2005-09-21 11:53) [6]


> Юрий Зотов ©   (20.09.05 22:37) [4]

> Обычно динамическим, т.к. методы диспетчеризации перекрываются
> нечасто, а в таком случае динамический метод дает тот же
> расход памяти, что и виртуальный, но работу ускоряет.


Virtual methods optimize for speed, while dynamic methods optimize for code size.
..
Dynamic methods are useful when a base class declares many overridable  
methods which are inherited by many descendant classes in an application,
but only occasionally overridden.

Т.е., не ускоряет, а уменьшает размер (вкупе с наследниками).

--
Regards, LVT.


 
Quattro ©   (2005-09-21 17:04) [7]

Прошу меня извинить за то что влезаю в разговор,но не могли бы вы подсказать как назначить обработчик данному событию Event:TNotifyEvent ???


 
Reindeer Moss Eater ©   (2005-09-21 17:27) [8]

Оператором присваивания.
:=

Слышал про такой?


 
Quattro ©   (2005-09-21 17:38) [9]


> Оператором присваивания.
> :=
>
> Слышал про такой?

угу...что такое когда то слышал=)......

TMyButton = class(TControl)
 private
   FOnClick:TNotifyEvent;
   procedure DoMouseDown;
   procedure WMLButtonClick(var Msg:TWMLButtonDown);message  WM_LBUTTONDOWN;
 protected
   procedure qwe(Sender: TObject);
 public
   Constructor Create(AOwner:TComponent);override;
   Destructor Destroy;override;

   property OnClick:TNotifyEvent read FOnClick write FOnClick;
 end;


затем пытаюсь назначить обработчик
procedure TForm1.FormCreate(Sender: TObject);
var
 But:TMyButton;
begin
 But:=TMyButton.Create(nil);
 But.Parent:=Self;
 But.Show;
 But.Top:=10;
 But.Left:=10;
 But.OnClick:=qwe;
end;

да вот пишет что qwe-ндекларед идентифир ......не подскажите,в чём проблема?


 
Reindeer Moss Eater ©   (2005-09-21 17:39) [10]

Проблема в том, что идентификатор qwe не объявлен.


 
Reindeer Moss Eater ©   (2005-09-21 17:42) [11]

Точнее объявлен не там где его ищет компилятор.

But.OnClick:=But.qwe;


 
Quattro ©   (2005-09-22 03:05) [12]

ёлки зелёные..почему же не србатывает ShowMessage?
type
 TMyButton = class(TControl)
 private
   FOnClick:TNotifyEvent;
   procedure DoMouseDown;
   procedure WMLButtonClick(var Msg:TWMLButtonDown);message WM_LBUTTONDOWN;
 protected

 public
   procedure DoShowMes(Sender: TObject);
   Constructor Create(AOwner:TComponent);override;
   Destructor Destroy;override;

   property OnClick:TNotifyEvent read FOnClick write FOnClick;
 end;
 TForm1 = class(TForm)
   Button1: TButton;
   procedure FormCreate(Sender: TObject);
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

{ TMyButton }

constructor TMyButton.Create(AOwner: TComponent);

begin
 inherited;
 CreateWindow("BUTTON","QWERTY",WS_CHILD or WS_VISIBLE or BS_PUSHBUTTON
  ,123,115,100,28,Form1.Handle,0,hInstance,nil);

end;

destructor TMyButton.Destroy;
begin

 inherited;
end;

procedure TMyButton.DoMouseDown;
begin
 if Assigned(FOnClick) then FOnClick(Self);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
 But:TMyButton;
begin
 But:=TMyButton.Create(nil);
 But.Parent:=Self;
 But.Show;
 But.Top:=10;
 But.Left:=10;
 But.OnClick:=But.DoShowMes;
end;

procedure TMyButton.WMLButtonClick(var Msg: TWMLButtonDown);
begin
DoMouseDown;
end;

procedure TMyButton.DoShowMes;
begin
 ShowMessage("qweqwe");
end;


 
Reindeer Moss Eater ©   (2005-09-22 09:13) [13]

Что бы оно срабатывало, надо как минимум обрабатывать нужные сообщения посылаемые твоему окну.
Где твоя оконная процедура?


 
Quattro ©   (2005-09-22 12:25) [14]

хм...обработки сообщения WMLBUTTONDOWN классом  TMyButton не достаточно??


 
Reindeer Moss Eater ©   (2005-09-22 12:42) [15]

И как зовут того дядю, который вызовет твой WMLButtonClick?


 
icWasya ©   (2005-09-22 12:46) [16]

IMHO - что бы работали  вот такие процедуры
procedure WMLButtonClick(var Msg:TWMLButtonDown);message WM_LBUTTONDOWN;
компонент должен быть наследником TWinControl


 
Quattro ©   (2005-09-22 12:57) [17]

Reindeer Moss Eater ©
Прошу меня извинить,если я задаю глупые вопросы.....но что значит как зовут дядю??...я нажму на контрол и обработчик сообщени нажатия должен ,собственно,обработать сообщение....нет?


 
Quattro ©   (2005-09-22 12:58) [18]

icWasya ©
 ??..а какая разница??..


 
Reindeer Moss Eater ©   (2005-09-22 13:03) [19]

я нажму на контрол и обработчик сообщени нажатия должен ,собственно,обработать сообщение....нет?

Канечно нет. Иначе бы ты не спрашивал почему не генерируется событие.


 
Quattro ©   (2005-09-22 14:01) [20]

Reindeer Moss Eater ©
Логично=)..не поспоришь=)...хм есть предположение что нужен обработчик сообщения WMLBUTTONDOWN для формы....

TForm1 = class(TForm)
  Button1: TButton;
  procedure FormCreate(Sender: TObject);
  procedure WMLButtonClick(var Msg:TWMLButtonDown);message   WM_LBUTTONDOWN;
  { Private declarations }
public
  { Public declarations }
end;

procedure TMyButton.WMLButtonClick(var Msg: TWMLButtonDown);
begin
DoMouseDown;
end;


 
umbra ©   (2005-09-22 14:03) [21]


> Quattro ©



> ёлки зелёные..почему же не србатывает ShowMessage?


Потому, что у тебя на форме не ТMyButton - наследник TControl, а TButton - наследнк TWinControl. А ТMyButton на форме вообще не видно. Отсюда -

> TMyButton.DoShowMes

НИКОГДА не вызывается


 
Quattro ©   (2005-09-22 15:28) [22]

umbra ©
вообще тогда ничего не понимаю......я же в конструктора TMyButton сам создаю кнопку функцией CreateWindow!!....


 
Reindeer Moss Eater ©   (2005-09-22 15:32) [23]

И думаешь что ты после этого молодец?
А где обработка сообщений этому окну?


 
Reindeer Moss Eater ©   (2005-09-22 15:37) [24]

Откуда по твоему созданное окно должно узнать, что оно - твоя новая супер-кнопка и что у этой кнопки есть какое-то событие которое должно срабатывать при получении окном WM_LBUTTONDOWN?


 
Quattro ©   (2005-09-22 17:56) [25]

Reindeer Moss Eater ©
 так..давай по порядку....
 1) Извини,если я чего то не понимаю и раздражаю тебя ,на твой взгляд , глупыми вопросами
 2)Я сам в конструкторе класса TMyButton создаю окно функцие CreateWindow
3)Вновь созданную мной кнопку на форме видно(она нажимается и всё такое)

> Откуда по твоему созданное окно должно узнать, что оно -
>  твоя новая супер-кнопка и что у этой кнопки есть какое-
> то событие которое должно срабатывать при получении окном
> WM_LBUTTONDOWN?

как это откуда?я же указал обработчик сообщения WMLBUTTONCLICK!!
TMyButton = class(TControl)
 private
   FOnClick:TNotifyEvent;
   procedure DoMouseDown;
   procedure WMLButtonClick(var Msg:TWMLButtonDown);message WM_LBUTTONDOWN;
 protected

 public
   procedure DoShowMes(Sender: TObject);
   Constructor Create(AOwner:TComponent);override;
   Destructor Destroy;override;

   property OnClick:TNotifyEvent read FOnClick write FOnClick;
 end;


 
umbra ©   (2005-09-22 18:48) [26]


> созданную мной кнопку на форме видно


Если код из [12] остается в силе, то там на форме есть TButton и вот его-то и видно на форме. Если была бы и TMyButton, то на форме было-бы две кнопки.


 
Quattro ©   (2005-09-22 18:56) [27]

umbra ©    
 так я создаю кнопку только когда программа запущена....TButton случайно там оказалась...считай что её нет...просто я смотрел как она устроена и забыл вычеркнуть из кода......конечный вариант  кода вот такой
type
 TMyButton = class(TControl)
 private
   FOnClick:TNotifyEvent;
   procedure DoMouseDown;
   procedure WMLButtonClick(var Msg:TWMLButtonDown);message WM_LBUTTONDOWN;
 public
   procedure DoShowMes(Sender: TObject);
   Constructor Create(AOwner:TComponent);override;
   Destructor Destroy;override;
   property OnClick:TNotifyEvent read FOnClick write FOnClick;
 end;
 TForm1 = class(TForm)
   procedure FormCreate(Sender: TObject);
   { Private declarations }
 public
   { Public declarations }
 end;
var
 Form1: TForm1;

implementation

{$R *.dfm}

{ TMyButton }

constructor TMyButton.Create(AOwner: TComponent);
begin
 inherited;
 CreateWindow("BUTTON","QWERTY",WS_CHILD or WS_VISIBLE or BS_PUSHBUTTON
  ,123,115,100,28,Form1.Handle,0,hInstance,nil);

end;

destructor TMyButton.Destroy;
begin

 inherited;
end;

procedure TMyButton.DoMouseDown;
begin
 if Assigned(FOnClick) then FOnClick(Self);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
 But:TMyButton;
begin
 But:=TMyButton.Create(nil);
 But.Parent:=Self;
 But.Show;
 But.Top:=10;
 But.Left:=10;
 But.OnClick:=But.DoShowMes;
end;

procedure TMyButton.WMLButtonClick(var Msg: TWMLButtonDown);
begin
DoMouseDown;
end;

procedure TMyButton.DoShowMes;
begin
 ShowMessage("qweqwe");
end;


 
umbra ©   (2005-09-22 19:33) [28]

вот я скопировал твой код, вставил в новый проект, запустил - и не вижу на форме ни одной кнопки.


 
Quattro ©   (2005-09-22 20:52) [29]

umbra ©

??????? как это так??...тогда почему этот же скопированный код прекрасно отображает кнопку???...
З.Ы. Начинаю чувствовать себя идиотом...


 
Reindeer Moss Eater ©   (2005-09-22 20:53) [30]

2)Я сам в конструкторе класса TMyButton создаю окно функцие CreateWindow

А я щас отнаследуюсь от TObject, создам такое же окно, а про себя подумаю, что мой новый компонент - это супер пупер навороченный тулбар из аутлука и еще круче в 10 раз.
И напишу кучу процедур реагирующих на все возможные сообщения windows.

И чё?
По твоей логике должен таки получиться супер-пупер навороченный тулбар из аутлука и еще круче в 10 раз.


 
Quattro ©   (2005-09-22 22:18) [31]


> А я щас отнаследуюсь от TObject, создам такое же окно, а
> про себя подумаю, что мой новый компонент - это супер пупер
> навороченный тулбар из аутлука и еще круче в 10 раз.

так ведь я написал для этого окна обработчик сообщения!!..или что я сделал??
Почему тогда этот код для формы прекрасно работает ?
TForm1 = class(TForm)
 private
   { Private declarations }
   procedure WMLButtonDown(var Msg:TWMLButtonDown);message WM_LBUTTONDOWN;
 public
   { Public declarations }
 end;

procedure TForm1.WMLButtonDown(var Msg: TWMLButtonDown);
begin
ShowMessage("qwqwe");
end;


 
Reindeer Moss Eater ©   (2005-09-22 22:39) [32]

И я написал 1000 обработчиков.
И что?
Кто их вызывает (должен вызывать) по твоему?
Зеленые человечки?


 
Quattro ©   (2005-09-22 22:41) [33]

Reindeer Moss Eater ©
 Форма?


 
Reindeer Moss Eater ©   (2005-09-22 22:44) [34]

А с какого щасться форма должна заботиться о сообщениях твоему баттону?
Тем более, что у него есть окно.
Ты его (окно) зачем вообще создавал?
Что бы смотреть сквозь него на унылый осенний пейзаж?


 
Quattro ©   (2005-09-22 22:54) [35]

эээ..так кто же должен вызывать эти сообщения то???


 
Reindeer Moss Eater ©   (2005-09-22 23:00) [36]

Сообщения посылаются созданному тобой окну.
Для этого ты и создал его.
А дальше их надо обрабатывать.
В оконной процедуре.


 
Quattro ©   (2005-09-22 23:04) [37]


> Сообщения посылаются созданному тобой окну

это вот это!так?
CreateWindow("BUTTON","QWERTY",WS_CHILD or WS_VISIBLE or BS_PUSHBUTTON
 ,123,115,100,28,Form1.Handle,0,hInstance,nil);


> А дальше их надо обрабатывать.
> В оконной процедуре.

оконная процедура это вот это??
TMyButton = class(TControl)
  private
    procedure WMLButtonClick(var Msg:TWMLButtonDown);message  WM_LBUTTONDOWN;
   protected
   public
 end;


 
Reindeer Moss Eater ©   (2005-09-22 23:09) [38]

Это не оконная процедура.
Это метод класса.


 
Quattro ©   (2005-09-23 00:48) [39]

Reindeer Moss Eater ©
аа!!!понял!..WndProc!!!
TMyButton = class(TControl)
 private
   FOnClick:TNotifyEvent;
   procedure DoMouseDown;
   procedure WndProc(var Message:TMessage);override;
 public
   procedure DoShowMes(Sender: TObject);
   Constructor Create(AOwner:TComponent);override;
   Destructor Destroy;override;
   property OnClick:TNotifyEvent read FOnClick write FOnClick;
 end;


Только как указать что если сообщение WM_LBUTTONDOWN ,то вызывать обработчик этого сообщения??

procedure TMyButton.WndProc(var Message: TMessage);
begin
 if Message.Msg = WM_LBUTTONDOWN then
  ????? But.WMLButtonClick?????
   
  inherited WndProc(Message);

end;


 
umbra ©   (2005-09-23 10:44) [40]

Ты создал окно. Оно получает от винды ВСЕ сообщения от мыши или клавиатуры. Если ты клацнешь мышой где угодно на экране, твое окно получит сообщение WM_LBUTTONDOWN, в котором указано где имеено на экране клацнули мышой. И тебе надо, как минимум, филтровать эти сообщения и обрабатывать только клики  на твоем окне. Дальше. Тебе надо твое окно рисовать! Ты ведь наследуешь от TControl, а отрисовка окон реализована только в TCustomControl (наследнике TWinControl). Посему в твоей оконной процедуре должны обрабатываться сообщения об отрисовке окна и рисовать его. Иначе его никто не увидит. И т.д. Писать окно снуля - нелегкий труд. Чтобы его избежать и создана VCL.

В общем, наследуй не от TControl, а от TButton, или, в общем, от ближайшего класса, в котором есть похожая функциональность.

Насколько я помню, первоначально вопрос был о том, как присвоить обработчик событию. Ниже - рабочий пример. При запуске проги у Button2 нет обработчика OnClick. После нажатия на Button1 обработчик присваивается, после повторного опять убирается.


unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;

type
 TForm1 = class(TForm)
   Button1: TButton;
   Button2: TButton;
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
   procedure Clicker(sender: TObject);
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

{ TForm1 }

procedure TForm1.Clicker(sender: TObject);
begin
 Randomize;
 Color := TColor(Random($FFFFFF));
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 if not Assigned(Button2.OnClick) then
   Button2.OnClick := Clicker
 else
   Button2.OnClick := nil;
end;

end.




Страницы: 1 2 вся ветка

Текущий архив: 2006.03.26;
Скачать: CL | DM;

Наверх




Память: 0.59 MB
Время: 0.042 c
11-1123058007
Ajax
2005-08-03 12:33
2006.03.26
Form.CanResize:=False и програмное изменение размеров


6-1134514285
Змей
2005-12-14 01:51
2006.03.26
WebBrowser не зависимо от IE


15-1141480795
постигаю
2006-03-04 16:59
2006.03.26
окно


3-1138958029
Ega23
2006-02-03 12:13
2006.03.26
Создание View - поясните


1-1140586210
__DATA__
2006-02-22 08:30
2006.03.26
Сохранение заголовков всех компонентов формы