Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Компоненты";
Текущий архив: 2006.03.26;
Скачать: [xml.tar.bz2];

Вниз

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

 
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.



 
Quattro ©   (2005-09-24 00:12) [41]

извиняюсь,если надоел глупыми вопросами....в данном примере как мне вызвать обработчик сообщениея??
TMyButton = class(TControl)
 private
   procedure WndProc(var Message:TMessage);override;
   procedure WMLButtonClick(var Msg:TWMLButtonDown);message WM_LBUTTONDOWN;
 public
 end;

procedure TMyButton.WndProc(var Message: TMessage);
begin
 if Message.Msg = WM_LBUTTONDOWN then
   But.WMLButtonClick()//Что здесь нужно передать в качестве параметра,имеющего тим TWMouse?;
 inherited WndProc(Message);

end;


 
umbra ©   (2005-09-26 13:33) [42]

В метод-обработчик сообщения не надо ничего передавать. Его не надо даже вызывать самому! Этот метод вызывается автоматически каждый раз, когда контрол получает соответствующее сообщение от винды. Как параметр ей АВТОМАТИЧЕСКИ передается полученное сообщение. Приложение должно на основании информации в сообщении что-то решить. Кроме того, при клике надо обрабатывать 2 сообщения - нажатие левой кнопки мыши и отпускание. И только если для контрола произошли оба - тогда вызывать обработчик события. Честно говоря, я не специалист в этом, и то, что я написал - только мое понимание. Примеры лучше всего смотреть в модуле Controls - объявление и реализацию класса TControl и его наследников. Там есть и TWMLButtonDown.


 
Quattro ©   (2005-09-27 18:06) [43]

ок..спасибо за объяснения и за терпение..=)...



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

Форум: "Компоненты";
Текущий архив: 2006.03.26;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.58 MB
Время: 0.038 c
15-1141150109
strannik-ivan
2006-02-28 21:08
2006.03.26
dll+потоки


2-1141994458
jeka_t
2006-03-10 15:40
2006.03.26
Как определить текущий TDBGrid.Row при событии DrawColumnCell?


2-1142151949
@gent
2006-03-12 11:25
2006.03.26
проблема с компонентом Image


1-1140346133
-matrix-
2006-02-19 13:48
2006.03.26
Проблема поиска


15-1141227035
Pazitron_Brain
2006-03-01 18:30
2006.03.26
Покритикуйте страницу





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский