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

Вниз

не работает динамически созданный обработчик   Найти похожие ветки 

 
vasek ©   (2005-11-23 23:48) [0]

для динамически созданной кнопки данный обработчик работает:

type

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

var

Form1: TForm1;

const

i : integer = 0;

implementation
{$R *.DFM}

procedure TForm1.myClick(Sender: TObject);
begin

with Sender as TButton do
Self.Caption := ClassName + " " + Name;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin

with TButton.Create(self) do begin
Left := 20;
Top := 30 + i;
Width := 120;
Height := 40;
Name := "ThisButton" + IntToStr(i);
Caption := "There" + IntToStr(i);
OnClick := MyClick;  { процедура, определенная где-то еще }
Parent := Form1;
end; {end with}
inc(i, 40);
end; {end button1.click}
end.

а так не хочет... :( :

program Project1;

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, ExtCtrls,
 Unit1 in "Unit1.pas";

{$R *.res}

type
 TButtonArray = array[1..4,1..4] of TButton;

var
 MainForm: TForm;
 Hnd, Hnd1: THandle;
 Buttons : TButtonArray;
 Panel1: TPanel;

procedure ButtonPressed(Sender: TObject);
var
B : TButton;
i1,j1: Integer;
begin
B := Sender as TButton;
  begin
{code}
  end;
end;

begin
 MainForm:= TForm.CreateParented(Hnd);
 Application.Initialize;
 Application.CreateForm(TForm, MainForm);
 Buttons[1,1]:= TButton.CreateParented(MainForm.Handle);
 Buttons[1,1].Parent:= MainForm;
 Buttons[1,1].OnClick:= ButtonPressed;
end;

почему ?

пишет следующее: incompatible types: "method pointer and regular procedure".


 
Zeqfreed ©   (2005-11-24 00:09) [1]

vasek ©   (23.11.05 23:48)
Код компилируется?
Где Apllication.Run в project.dpr?


 
Zeqfreed ©   (2005-11-24 00:15) [2]

vasek ©   (23.11.05 23:48)
А, увидел :)
Форматирование кода используй в следующий раз.

> пишет следующее: incompatible types: "method pointer
> and regular procedure".

Ну тут тебе же говорят, что требуется указать метод (процедуру-член класса), как и сделано у тебя в коде, что выше.
В общем-то можно использовать и регулярную процедуру, создав метод и назначив его в качестве обработчика, примерно так:

var
 Method : TMethod;
begin
 Method.Code := @YourEventHandler;
 Mathod.Data := nil;
 ButtonInstance.OnClick := TNotifyEvent(Method);
end;


 
vasek ©   (2005-11-24 01:19) [3]

Apllication.Run есть дальше...  
....
Application.Run;
end.
...

все работает но не получается сделать динамически обработчик, без него все ок.  если можно по подробнее, и если уж совсем не затруднит рабочий(полурабочий :)) кусочек...


 
ЮЮ ©   (2005-11-24 04:20) [4]

TForm1 = class(TForm)
...
private
 ButtonPressed(Sender: TObject);

...
end;

procedure Form1.ButtonPressed(Sender: TObject);


 
ЮЮ ©   (2005-11-24 04:28) [5]

Сорри, не обратил внимание, что ButtonPressed описан в dpr. А не лучше его описать, как в [4], только в public секции, тогда
 Buttons[1,1].OnClick:= MainForm.ButtonPressed;


 
sniknik ©   (2005-11-24 07:29) [6]

> и если уж совсем не затруднит рабочий(полурабочий :)) кусочек...
кусочек в Zeqfreed ©   (24.11.05 00:15) [2] полностью рабочий... (так, для справки)


 
sniknik ©   (2005-11-24 07:33) [7]

и кстати,
> begin
>    MainForm:= TForm.CreateParented(Hnd);
>    Application.Initialize;
>    Application.CreateForm(TForm, MainForm);
>    Buttons[1,1]:= TButton.CreateParented(MainForm.Handle);
>
>    Buttons[1,1].Parent:= MainForm;
>    Buttons[1,1].OnClick:= ButtonPressed;
> end;


если перенести создание в правильное место (onCreate MainForm) "проблема" исчезнет так и не родившись...


 
vasek ©   (2005-11-24 13:31) [8]

а куда переместить (onCreate MainForm), если не затруднит поподробнее..?
@YourEventHandler - это про кого?(это на тему полностью рабочего примера).


 
Zeqfreed ©   (2005-11-24 14:14) [9]

vasek ©   (24.11.05 13:31) [8]

procedure ClickEventHandler(Sender : TObject);
begin
 if (Sender is TButton) then
  ShowMessage(Format("Button with caption %s has just been clicked", [(Sender as TButton).Caption]));
end;

procedure AddButton(ParentForm : TForm; Handler : Pointer; const ButtonCaption : String; const ButtonLeft, ButtonTop : TPoint);
var
 Method : TMethod;
begin
 Method.Code := Handler;
 Method.Data := nil;

 with TButton.Create(nil) do begin
  Caption := ButtonCaption;
  Parent := ParentForm;
  Left := ButtonLeft;
  Top := ButtonTop;
  OnClick := TNotifyEvent(Method);
 end;
end;

procedure TMainForm.Button1Click(Sender : TObject);
begin
AddButton(Self, @ClickEventHandler, "Button 1", 8, 8);
AddButton(Self, @ClickEventHandler, "Button 2", 8, 32);
end;


Код не проверял, но вроде все должно работать.


>  на тему полностью рабочего примера

Пример в [2] очень даже рабочий, если не считать опечатки в слове Method.


 
Плохиш ©   (2005-11-24 14:18) [10]


> vasek ©   (23.11.05 23:48)


> procedure ButtonPressed(Sender: TObject) of object;


 
Zeqfreed ©   (2005-11-24 14:25) [11]

Zeqfreed ©   (24.11.05 14:14) [9]

> const ButtonLeft, ButtonTop : TPoint);

Читать как const ButtonLeft, ButtonTop : Integer);


 
Leonid Troyanovsky ©   (2005-11-24 15:30) [12]


> vasek ©   (23.11.05 23:48)  
> для динамически созданной кнопки данный обработчик работает:
..
> а так не хочет... :( :
..
> почему ?


Потому, что для динамически создаваемых контрола нужно
не назначать обработчик OnClick, а перекрывать метод Click, т.е.

TMyButton = class(TButton);
public
  procedure Click; override;
  ..
end;

procedure TMyButton.Click;
begin
  inherited;
  MyClick; { процедура, определенная где-то еще }
end;


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

Советую сделать памятную зарубку на носу.

--
Regards, LVT.


 
sniknik ©   (2005-11-24 20:10) [13]

Zeqfreed ©   (24.11.05 14:14) [9]
а вот это хреновый пример, Method локальная переменная, тоже не проверял но думаю могут быть проблемы.


 
vasek ©   (2005-11-25 00:32) [14]

зарубку сделал... но а в случае когда массив кнопок:

type
 TButtonArray = array[1..n,1..n] of TButton;

TMyButton = class(TButton)
public
 procedure Click; override;
end;

procedure ButtonPressed;
var
B : TButton;
begin
B := Sender as TButton;
  begin
   
  end;
end;

procedure TMyButton.Click;
begin
 inherited;
 ButtonPressed;
end;

begin
 MainForm:= TForm.CreateParented(Hnd);
 Application.Initialize;
 Application.CreateForm(TForm, MainForm);

   for i:= 1 to n do
     for j:= 1 to n do
       begin
           Buttons[i,j]:= TButton.CreateParented(MainForm.Handle);
           Buttons[i,j].Parent:= MainForm;
           Buttons[i,j].OnClick:= TMyButton.Click;;
         end;
       end;

 Application.Run;
end.

... не срабатывает :(

incompatible types "parametr lists differ"


 
Германн ©   (2005-11-25 01:57) [15]

2 vasek ©

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


 
Плохиш ©   (2005-11-25 02:20) [16]


> ... не срабатывает :(
>
> incompatible types "parametr lists differ"

Потому что Click не является классовой функцией.


 
Leonid Troyanovsky ©   (2005-11-25 10:27) [17]


> vasek ©   (25.11.05 00:32) [14]
> зарубку сделал... но а в случае когда массив кнопок:

>            Buttons[i,j].OnClick:= TMyButton.Click;;


Это совсем не нужно.

А вот кнопки надо создавать уже нового класса: TMyButton.

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2005-11-25 10:32) [18]


> Плохиш ©   (25.11.05 02:20) [16]

> Потому что Click не является классовой функцией.


Если уж точней, то процедурой.
Однако, является методом класса (но не классовым методом ;)

Но, причина неудачи не этом, а в том, что список параметров разный.
Хотя, собс-но, такое назначение, в рассматриваемом случае,
категорически  противопоказано.

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2005-11-25 10:38) [19]


> sniknik ©   (24.11.05 20:10) [13]
> Zeqfreed ©   (24.11.05 14:14) [9]
> а вот это хреновый пример, Method локальная переменная,
> тоже не проверял но думаю могут быть проблемы.


Никаких проблем, в поле копируется 8 байт.

--
Regards, LVT.


 
sniknik ©   (2005-11-25 10:52) [20]

Leonid Troyanovsky ©   (25.11.05 10:38) [19]
на первый взгляд решил что передается указатель на структуру.

был не прав. исправлюсь.


 
vasek ©   (2005-11-25 13:41) [21]

на тему:
 Германн ©   (25.11.05 01:57) [15]

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

все просто: необходимо создать массив кнопок и чтобы каждая умела чтото делать без дфм.


 
Плохиш ©   (2005-11-25 13:44) [22]


> vasek ©   (25.11.05 13:41) [21]
> все просто: необходимо создать массив кнопок и чтобы каждая
> умела чтото делать без дфм.

Ответ на это был дан ещё ЮЮ ©   (24.11.05 04:20) [4]


 
Leonid Troyanovsky ©   (2005-11-25 14:20) [23]


> Плохиш ©   (25.11.05 13:44) [22]

> Ответ на это был дан ещё ЮЮ ©   (24.11.05 04:20) [4]


И, в данном контексте, он был единственно верным, бо
избыточный корм, как правило, идет не в коня.

--
Regards, LVT.


 
vasek ©   (2005-11-26 02:33) [24]

хм.. в коня или мимо коня, а вопрос ведь остался неразрешенным, то что предложенно ЮЮ - компилятор говорит что не хватает файла ресурсов, а я ведь хотел без дфм обойтись. странно столько было сказанно слов хороших и разных, а воз и ныне там... :(


 
Германн ©   (2005-11-26 02:41) [25]

Ну, опять же про садомазохизм. А чем "дфм" так претит?
Ведь в vasek ©   (23.11.05 23:48)  - без "дфм" вообще, просто не обойтись.

Совсем без "дфм", так это в "WinAPI".


 
vasek ©   (2005-11-26 03:48) [26]

извиняюсь, пример Zeqfreed © работает вот только сендер, вот здест почемуто ничего не передает:

procedure ClickEventHandler(Sender : TObject);
begin
if (Sender is TButton) then
 ShowMessage(Format("Button with caption %s has just been clicked", [(Sender as TButton).Caption]));
end;

т.е не понятно какая кнопочка нажата...


 
sniknik ©   (2005-11-26 11:48) [27]

> т.е не понятно какая кнопочка нажата...
это потому что поле Data в примере не определено (nil). а в хелп по нему ты не заглядывал и не догадатся не пытался (элементарное же рассуждение/действие пропущено) .

> странно столько было сказанно слов хороших и разных, а воз и ныне там... :(
это потому что ты как донкихот сражаешся с ветряными мельницами там где их никто не видит.

и при том в зависимости от того какая мельница тебе примерешилась спосбы борьбы с ней будут разные... а видения твои до сих пор для всех тайна, смысла никто не понимает. вот скажи зачем уходить от dfm? смысл?, если ты оставляеш VCL то ничего от того где ты их создаш не изменится, а если их создавать в события создания формы то и проблемы твоей не будет, если наследовать и непосредственно в событии обработчики писать то тоже твоя проблема исчезает (она похоже в единственном выбраном тобой варианте существует... и так не делают, обычно). а если это типа переход на WinApi такой, ну тогда тут все неправильно начиная с того что весь Appliction надо убирать.


 
begin...end ©   (2005-11-26 11:56) [28]

> vasek ©   (26.11.05 03:48) [26]
> procedure ClickEventHandler(Sender : TObject)

procedure ClickEventHandler(Self, Sender : TObject)

> sniknik ©   (26.11.05 11:48) [27]
> это потому что поле Data в примере не определено (nil)

Неверно.


 
sniknik ©   (2005-11-26 13:16) [29]

> Неверно.
а ты проверь.
> Неверно.
а ты проверь.

procedure ClickEventHandler(Sender : TObject)
begin
 //
end;

...
var
  Method : TMethod;
begin
 Method.Code := @ClickEventHandler;
 Method.Data := Button1;
 ButtonInstance.OnClick := TNotifyEvent(Method);
end;

и посмотри заодно что в генофонде дельфи используется.


 
sniknik ©   (2005-11-26 13:18) [30]

хм. чтото меня сглючило (это про повтор в начале), надо осторожнее методом копи пасте пользоваться... ;)


 
begin...end ©   (2005-11-26 13:21) [31]

> sniknik ©   (26.11.05 13:16) [29]

Data -- это Self, а не Sender. Ку?

> и посмотри заодно что в генофонде дельфи используется

"Не говорите загадками, Вы меня изводите" (с)


 
Zeqfreed ©   (2005-11-26 14:05) [32]

sniknik ©   (26.11.05 13:16) [29]
begin...end ©   (26.11.05 11:56) [28]

Вариант 1.
procedure ClickEventHandler(Sender : TObject);
begin
if (Sender is TButton) then
 ShowMessage(Format("Button with caption %s has just been clicked", [(Sender as TButton).Caption]));
end;

procedure AddButton(ParentForm : TForm; Handler : Pointer; const ButtonCaption : String; const ButtonLeft, ButtonTop : Integer);
var
Method : TMethod;
btn : TButton;
begin
btn := TButton.Create(nil);

Method.Code := Handler;
Method.Data := btn;

with btn do begin
 Caption := ButtonCaption;
 Parent := ParentForm;
 Left := ButtonLeft;
 Top := ButtonTop;
 OnClick := TNotifyEvent(Method);
end;
end;


Вариант 2.
procedure ClickEventHandler(Self, Sender : TObject);
begin
if (Sender is TButton) then
 ShowMessage(Format("Button with caption %s has just been clicked", [(Sender as TButton).Caption]));
end;

procedure AddButton(ParentForm : TForm; Handler : Pointer; const ButtonCaption : String; const ButtonLeft, ButtonTop : Integer);
var
Method : TMethod;
begin
Method.Code := Handler;
Method.Data := nil;

with TButton.Create(nil) do begin
 Caption := ButtonCaption;
 Parent := ParentForm;
 Left := ButtonLeft;
 Top := ButtonTop;
 OnClick := TNotifyEvent(Method);
end;
end;


Оба варианта работают, не спорьте :)

p.s. Щас открыл справку по TMethod да что-то она состоит из нескольких строк, где ничего толком и не говорится :( Может не там ищу?


 
sniknik ©   (2005-11-26 14:09) [33]

> "Не говорите загадками, Вы меня изводите" (с)
не переваливай с больной головы на здоровую. сам подкинунул "загадку" сказал "неверно" на тот код который непосредственно борландом используется. вот и обьясни. почему неверно? оно что глюки дает? или просто твоему мироощущению не соответствует?

Zeqfreed ©   (26.11.05 14:05) [32]
> Оба варианта работают, не спорьте :)
это было без вопросов, вариантов всегда больше чем один. (и к тому же я сразу проверил, в отличии от некоторых, не будем показывать пальцами... но это был слоник ;)
вопрос в том почему рабочий код - "неверно". (и без обьяснений...)


 
begin...end ©   (2005-11-26 14:23) [34]

> Zeqfreed ©   (26.11.05 14:05) [32]

Вариант 1. Указываем в Method.Data любой другой объект (например, форму), и при нажатии на кнопку получаем, что событие OnClick возбудила форма. Это неправильно, потому что на самом деле его возбудила кнопка. Следовательно, вариант 1 нельзя считать корректным.

Вариант 2. Вне зависимости от того, что указано в Method.Data, при обращении к Sender получаем верную информацию об инициаторе события. В этом легко убедиться, назначив кнопкам с разными именами один и тот же обработчик, и обращаясь внутри него к свойству (Sender as TComponent).Name.

Как же так? Method.Data, судя по утверждениям в [27] -- это и есть Sender, т.е. объект, инициировавший событие. Однако, даже если Method.Data = nil, вариант 2 будет работать правильно, и определять возбудивший событие объект, хотя он якобы должен быть равен nil.

> sniknik ©   (26.11.05 14:09) [33]

> код который непосредственно борландом используется
Где?

> оно что глюки дает?
Даёт.


 
Zeqfreed ©   (2005-11-26 14:32) [35]

begin...end ©   (26.11.05 14:23) [34]

> Вариант 1. Указываем в Method.Data любой другой объект
> (например, форму), и при нажатии на кнопку получаем,
> что событие OnClick возбудила форма. Это неправильно,
> потому что на самом деле его возбудила кнопка.
> Следовательно, вариант 1 нельзя считать корректным.

Ответственность за то, что писать в Method.Data целиком лежит на программисте; и если он хочет туда написать любой другой объект, то должен понимать к чему это приведет. Выводов не делаю.


> Method.Data, судя по утверждениям в [27] -- это и есть
> Sender

Я не вижу ничего подобного в [27], ей богу. Про Sender там ни слова.


 
sniknik ©   (2005-11-26 15:12) [36]

про Sender я действительно не говорил и даже не думал в тот момент. это все домыслы "from self".

> Указываем в Method.Data любой другой объект
также как через pointer можно передать указателю на класс указатель на переменную. ничего страшного... с точки зрения языка, программа да порушится при обращении к этой структуре, но вина ли эта pointer-а?

и даже наоборот, элегантное решение может быть, когда одним обработчиком обрабатываются разные данные...  (не для того ли это и сделано? подумай)
или пришлось бы плодить одинаковый код при разный данных в разных структурах. (такой вот будет копи пасте компиляторный)

;) вот теперь можеш обвинять в том что я путаю селф и сендер, потому как в предыдушем абзатце намек на подобное "кощунство"

> Где?

function InvokeImplGetter(Self: TObject; ImplGetter: Cardinal): IInterface;
{$IFDEF PUREPASCAL}
var
 M: function: IInterface of object;
begin
 TMethod(M).Data := Self;
 case ImplGetter of
   $FF000000..$FFFFFFFF:  // Field
       Result := IInterface(Pointer(Cardinal(Self) + (ImplGetter and $00FFFFFF)));
   $FE000000..$FEFFFFFF:  // virtual method
     begin
       // sign extend vmt slot offset = smallint cast
 TMethod(M).Code := PPointer(Integer(Self) + SmallInt(ImplGetter))^;
       Result := M;
     end;
 else // static method
   TMethod(M).Code := Pointer(ImplGetter);
   Result := M;
 end;
end;

зачем дата инициализируется? по твоему это не нужно, ставили бы nil... а скажу зачем, затем что описаны события(переменние) во всех классах всетаки как
TNotifyEvent = procedure(Sender: TObject) of object;
без self-а вначале, и потому без инициализации Data просто не обойтись, что и говорит что именно такой способ и подразумевался при разработке VCL. (т.е. это основной способ)


 
vasek ©   (2005-11-26 17:42) [37]

спасибо всем большое, что приняли участие в обсуждении данной темы. код Zeqfreed © вариант 1 работает отлично - это то что я хотел ;)


 
begin...end ©   (2005-11-26 18:59) [38]

> Zeqfreed ©   (26.11.05 14:32) [35]

> Я не вижу ничего подобного в [27], ей богу.

А я вижу. Человек пытается по Sender"у определить, какая кнопка нажата. [26] -- у него не получается (что и неудивительно). Далее следует [27], где говорится, что определить не получается именно потому, что в Data находится nil. По-моему, здесь налицо отождествление содержимого Data и  Sender"а.

> sniknik ©   (26.11.05 15:12) [36]

> про Sender я действительно не говорил и даже не думал в
> тот момент.

Странно. Вроде, говорим, говорим, а Вы об этом даже и не думаете, оказывается.

> и даже наоборот, элегантное решение может быть, когда одним
> обработчиком обрабатываются разные данные...  (не для того
> ли это и сделано? подумай)

Да, параметр Sender -- объект, возбудивший событие -- для того и придуман. Только Вы никак не поймёте, что в варианте 1 из [32] Sender -- это на самом деле не Sender, а Self.

> вот теперь можеш обвинять в том что я путаю селф и сендер,
> потому как в предыдушем абзатце намек на подобное "кощунство"

Извините, ничего не понял. Переформулируйте, если можно.

> зачем дата инициализируется? по твоему это не нужно, ставили
> бы nil...

Какое отношение к обсуждаемому вопросу имеет приведённый Вами код?

> именно такой способ и подразумевался при разработке VCL.
> (т.е. это основной способ)

Извините, опять ничего не понял.

> TNotifyEvent = procedure(Sender: TObject) of object;

Вы вот это "of object" видите? Различие между procedure (как в [29]) и procedure of object понимаете? Пока что -- не похоже.


 
sniknik ©   (2005-11-26 20:37) [39]

> procedure of object понимаете?
как ни странно да. понимаю. ;) хелп читать умею, а разница расписана на первой странице описания of object.

> ... Человек пытается по Sender"у определить, какая кнопка нажата. ...
ааааа... вот. теперя я понял с чего ты взьелся, название не понравилось...

так без разницы как переменную назвать. ку?

берем пример, и переделываем в соответствии с
> begin...end ©   (26.11.05 11:56) [28]
> procedure ClickEventHandler(Self, Sender : TObject)

procedure ClickEventHandler(Self, Sender : TObject);
begin
 Form1.Label1.Caption:= TButton(Self).Name;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
 Method : TMethod;
begin
 Method.Code := @ClickEventHandler;
 Method.Data := nil;
 ButtonInstance.OnClick := TNotifyEvent(Method);
end;

нажимаем кнопочку... оппа а self то у нас и нету, self у нас nil. и почему бы это? не потому ли что дату не заполнили? проверяем
Method.Data := batton1;
работает.

теперь берем вариант
procedure ClickEventHandler(Sender : TObject);
begin
 Form1.Label1.Caption:= TButton(Sender).Name;
end;

при Method.Data := nil; сендер тоже нил. странное совпадение, отложим в памяти...
заполняем  Method.Data := batton1;
работает.

почему? не потому ли что у нас переменная Sender образно говоря стала "ио" Self-a?

проверяем еще на кнопку вешаем
procedure TForm1.Button3Click(Sender: TObject);
begin
 Button1.OnClick(Button4);
end;
т.e. по идее сендер у нас сейчас Button4
и при
Method.Data := batton1;
procedure ClickEventHandler(Sender : TObject);
begin
 Form1.Label1.Caption:= TButton(Sender).Name;
end;
должен показать имя Button4 (раз я не прав)
нажимаем кнопочку показывает имя batton1 которое Method.Data прописано...
чешем репу и делаем вывод: под названием Sender в данном случае прячется Self! который "живет", как оказывается, в Method.Data...

обана. какой неожиданный результат. и что скажи сто тогда неверно в
>> это потому что поле Data в примере не определено (nil)
> Неверно.
?
с чего все и началось.


 
begin...end ©   (2005-11-26 21:38) [40]

> sniknik ©   (26.11.05 20:37) [39]

> как ни странно да. понимаю. ;)

Тогда мне совершенно непонятно, к чему и о чём был последний абзац в [36].

> self у нас nil. и почему бы это? не потому ли что дату не
> заполнили?

Да, именно поэтому.

> почему? не потому ли что у нас переменная Sender образно
> говоря стала "ио" Self-a?

Да, именно поэтому.

> и что скажи сто тогда неверно в
> >> это потому что поле Data в примере не определено (nil)

Подход неверен, понимаете? Описывая регулярную процедуру, код которой предполагается использовать в качестве кода метода-события OnClick, с одним параметром, Вы теряете один параметр! Т-е-р-я-е-т-е! Вы сами зачем-то назначаете Data (Self), чтобы использовать потом его как Sender, и игнорируете автоматически передающийся при возбуждении события параметр -- "настоящий" Sender. Неужели непонятно?


 
sniknik ©   (2005-11-26 23:14) [41]

>> как ни странно да. понимаю. ;)
> Тогда мне совершенно непонятно, к чему и о чём был последний абзац в [36].
зачем говорю что без заполниения даты не обойтись? странно, вроде выяснили, что без нее действительно не обойтись.

>> self у нас nil. и почему бы это? не потому ли что дату не
>> заполнили?
> Да, именно поэтому.
и зачем было отрицать?

> Неужели непонятно?
конечно непонятно. без обяснений что имеется в виду
а это
>> это потому что поле Data в примере не определено (nil)
> Неверно.
без обьяснений, воспринимается однозначно, как необязательность даты к заполнению, что гораздо более грубая ошибка, чем простая потеря значения ненужного в общемто в данном случае параметра.

т.е. надо было не отрицать, что заполнение даты неверно, а дополнить, что кроме этого еще описание процедуры надо поправить, если нужны все параметры. (в принципе это только если предполагаются вызовы вида Button1.OnClick(Button4);) подход обьяснить.
а то я ему про фому, он про ерему...

ты сам то понимаеш, что своим заявлением ты просто... как бы это сказать, "потряс до глубины души", вроде того (офигел просто), и доказывал я только то что ее всетаки необходимо заполнять... то что ты связываеш "неверность" с параметром  (на который никакого намека) я понял только в [38] по абзатцу с "Человек пытается по Sender"у определить, какая кнопка нажата." когда "ваше величество" всетаки соблагоизволило опустится до обьяснений, что оно считает неверным.
и как видиш следующий же пост, все разьясил. вроде бы... нет?


 
Германн ©   (2005-11-27 02:46) [42]

А я всё равно не понимаю, для чего нужно кому-то реально сие извращение!


 
begin...end ©   (2005-11-27 10:12) [43]

> sniknik ©   (26.11.05 23:14) [41]

> зачем говорю что без заполниения даты не обойтись?

Нет, я не про это. Вы приводите описание типа TNotifyEvent и говорите, что там нет явно указанного параметра Self вначале, в то время как я говорил о том, что Self нужно явно указывать для обычной процедуры, а не для метода. Это говорит о том, что Вы видите не всю разницу между procedure и procedure of object.

> странно, вроде выяснили, что без нее действительно не обойтись.

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

> простая потеря значения ненужного в общемто в данном случае
> параметра
.

LOL. 3 раза. Пол-ветки талдычим, как определить, какая кнопка нажата, а сейчас выясняется, что параметр, по которому это следует определять, не нужен.

Вот пример "обычного" назначения обработчика:

type
 TMyForm = class(TForm)
   ...
   procedure ClickEventHandler(Sender: TObject);
 end;

procedure TMyForm.ClickEventHandler(Sender: TObject);
begin
 ShowMessage((Sender as TComponent).Name);
end;

Button.OnClick := ClickEventHandler


Параметр Sender приходит сюда из самой кнопки -- из метода Click. Кнопка сама вызывает назначенный обработчик и передаёт в него указатель на себя -- это и есть Sender.

Теперь вернёмся к нашему случаю (варианту, который Вы считаете правильным):

procedure ClickEventHandler(Sender: TObject);
begin
 ShowMessage((Sender as TComponent).Name)
end;

var
 M: TMethod;
begin
 M.Code := @ClickEventHandler;
 M.Data := Button;
end;

Button.OnClick := TNotifyEvent(M)


Теперь скажите -- Вам понятно, что здесь Sender -- это содержимое Data, а не тот параметр, который приходит из кнопки (как в предыдущем примере)? И почему Вы игнорируете параметр, который даёт кнопка?

Пусть есть несколько кнопок, которым надо назначить одинаковый обработчик. Зачем нужно перед присваиванием каждой кнопке настраивать на неё поле Data, когда можно ничего не настраивать, а просто описать обработчик правильно, и для определения нажатой кнопки использовать предназначенный для этого параметр?

P.S. И всё же, в чём отличие вызова P от M:

var
 P: procedure;
 M: procedure of object;
begin
 P := ...;
 M := ...;
 P;  // вызов процедуры
 M; // вызов метода
end


?


 
Набережных С. ©   (2005-11-27 10:55) [44]


> begin...end ©   (27.11.05 10:12) [43]


> P.S. И всё же, в чём отличие вызова P от M: ...

Это вопрос риторический,  или нужен ответ?

Видимо риторический, поскольку в [43] все верно сказано, объявление procedure() of Object компилятор воспринимает как procedure(Self: TObject) , автоматически подставляя Self из TMethod.Data. В принципе, в некоторых случаяхопустить Self в регулярной процедуре не так уж страшно... но смысла так делать я тоже как-то не улавливаю:))


 
begin...end ©   (2005-11-27 11:00) [45]

> Набережных С. ©   (27.11.05 10:55) [44]

> Это вопрос риторический,  или нужен ответ?

Вопрос адресован автору [41]. Ответ нужен. Чтобы было понятно, о чём и как говорить дальше.


 
Набережных С. ©   (2005-11-27 11:14) [46]


> begin...end ©   (27.11.05 11:00) [45]

Вопросов больше не имею:)


 
sniknik ©   (2005-11-27 11:54) [47]

> Вопрос адресован автору [41]. Ответ нужен. Чтобы было понятно, о чём и как говорить дальше.
о чем дальше? в чем ты хочеш меня убедить?

и почему сам не отвечаеш на то почему считаеш что заполнение даты не нужно вовсе? ведь именно это я тебе пытался донести а не то что в каком параметре приходит.
но видимо не доносится...

> Теперь вернёмся к нашему случаю (варианту, который Вы считаете правильным):
конечно считаю. он более правильный чем ваш! у вас хоть и два параметра но один из них nil, при незаполнении дата.
у меня один просто прячется, у вас один как "бомба недотрога" (причем именно тот который и предлагается использовать).

предпочитаю вообше ничего не получить чем получить AV при обращении к одному из них.
(вернее мне это пофигу потому как сам подобного изврата делать никогда не буду, а там где это правильно делать там все автоматом)

вообще мне непонятно почему я стал "ответчиком", ваш "проступок"  гораздо серьезнее а вы почемуто считаете себя вправе "экзаменовать" меня.
т.е. пока не скажете почему вы считаете что незаполнение Data - верно. дальнейшие выяснения прекращаю.
"Чтобы было понятно, о чём и как говорить дальше."


 
begin...end ©   (2005-11-27 12:40) [48]

> sniknik ©   (27.11.05 11:54) [47]

> у меня один просто прячется, у вас один как "бомба недотрога"
> (причем именно тот который и предлагается использовать).

Что за бред?

procedure ClickEventHandler(Self, Sender: TObject);
begin
 ShowMessage((Sender as TComponent).Name)
end;

var
 M: TMethod;
begin
 M.Code := @ClickEventHandler;
 Button.OnClick := TNotifyEvent(M)
end;


AV не видно.

> вы почемуто считаете себя вправе "экзаменовать" меня

Я не экзаменую, а спрашиваю. А Вы не отвечаете. Почему-то.

> почему вы считаете что незаполнение Data - верно

Посмотрите код выше, и подумайте, почему Data не заполняется, а код работает. Причём единожды подготовленный TMethod можно назначить куче кнопок, ничего при этом не меняя. И он всё равно будет нормально работать.


 
sniknik ©   (2005-11-27 13:20) [49]


> Что за бред?
>
> procedure ClickEventHandler(Self, Sender: TObject);
> begin
>  ShowMessage((Sender as TComponent).Name)
> end;
>
> var
>  M: TMethod;
> begin
>  M.Code := @ClickEventHandler;
>  Button.OnClick := TNotifyEvent(M)
> end;
>
> AV не видно.


борьба за Self ради чего была? ради получения данных из правильного места, так? т.е. из Self -а кнопки, а не из Sender-а которого можно поменять вызвав к примеру непосредственно Button1.OnClick(Button4);
борешся за одно, а в примере сам используеш Sender (реального, не переименованого как в первом варианте)

> Я не экзаменую, а спрашиваю. А Вы не отвечаете. Почему-то.
спрашивают значит хотят чтото узнать, я часто отвечаю только поэтому.

> почему Data не заполняется, а код работает.
потому что Sender-а передают непосредственно при вызове метода.


 
begin...end ©   (2005-11-27 13:30) [50]

> sniknik ©   (27.11.05 13:20) [49]

> борьба за Self ради чего была? ради получения данных из
> правильного места, так?

Вообще ничего не понял.

> спрашивают значит хотят чтото узнать, я часто отвечаю только
> поэтому.

Так ведь и я спрашиваю не просто так, а для того, чтобы что-то узнать.

> потому что Sender-а передают непосредственно при вызове
> метода.

Где? Ещё раз: бросьте на форму кнопку, напишите код из [48] и нажмите кнопку. Код работает. То же можете повторить для нескольких кнопок. Где в коде [48] "Sender-а передают непосредственно при вызове метода"?


 
sniknik ©   (2005-11-27 13:52) [51]

> Где в коде [48] "Sender-а передают непосредственно при вызове метода"?
вызови для своего примера

Button1.OnClick(Button2);
Button1.OnClick(Button3);
Button1.OnClick(Button4);
Button1.OnClick(Button5);
Button1.OnClick(Button6);
Button1.OnClick(Button7);

работает событие кнопки 1, а что показывает?


 
sniknik ©   (2005-11-27 13:53) [52]

и попробуй получи что за кнопка работает на самом деле. те. прочитай Self.


 
begin...end ©   (2005-11-27 14:33) [53]

> sniknik ©   (27.11.05 13:52) [51]

Показывать будет, естественно, Button2, Button3 и т.д. Так же, как если бы OnClick был вызван в случае, когда ClickEventHandler является методом (т.е. как в первом примере кода из [43]). Вообще, назначьте кнопке обработчик обычным образом (в design-time), и вызовите OnClick с каким-нибудь параметром. Будет та же самая картина, что и в [48]. И что?

Вы так и не ответили, где в коде [48] "Sender-a передают непосредственно при вызове метода".

> sniknik ©   (27.11.05 13:53) [52]

А зачем мне его читать? Я же ничего не положил в Data -- значит, Self недействителен. Вот я к нему и не обращаюсь. Да и ClickEventHandler -- регулярная процедура, а не метод. Поэтому не совсем понятно, зачем внутри неё обращаться к Self"у.


 
sniknik ©   (2005-11-27 15:15) [54]

> Поэтому не совсем понятно, зачем внутри неё обращаться к Self"у.
чтобы узнать
vasek ©   (26.11.05 03:48) [26]
....
> т.е не понятно какая кнопочка нажата...
какая. не переданное кемто, а именно чей обьект работает. в вашем варианте, будет путаница.

> Вы так и не ответили, где в коде [48] "Sender-a передают непосредственно при вызове метода".
например
procedure TControl.Click;
begin
 { Call OnClick if assigned and not equal to associated action"s OnExecute.
   If associated action"s OnExecute assigned then call it, otherwise, call
   OnClick. }
 if Assigned(FOnClick) and (Action <> nil) and (@FOnClick <> @Action.OnExecute) then
   FOnClick(Self)
 else if not (csDesigning in ComponentState) and (ActionLink <> nil) then
   ActionLink.Execute(Self)
 else if Assigned(FOnClick) then
   FOnClick(Self);
end;
все пользоваельские евенты так вызываются, из собственно события, проверка на определенность и вызов, то что сдесь Self там стало Sender. просто совпало так, порождаются то(и вызваются) всетаки они самими обьектами. но ничего не мешает и самому этот вызов сделать и тогда как говорил уже ты получиш не то какая кнопка отработала а то что тебе передадут.


 
begin...end ©   (2005-11-27 15:25) [55]

> sniknik ©   (27.11.05 15:15) [54]

> > т.е не понятно какая кнопочка нажата...
> какая. не переданное кемто, а именно чей обьект работает.
> в вашем варианте, будет путаница.

Не будет никакой путаницы. Sender -- это объект, который инициировал событие. Событие может инициироваться самой кнопкой (если просто нажать на неё) -- тогда она и будет Sender"ом, либо вручную -- тогда Sender"ом будет тот объект, который я указал при ручном вызове.

> но ничего не мешает и самому этот вызов сделать и тогда
> как говорил уже ты получиш не то какая кнопка отработала
> а то что тебе передадут.

Конечно. Повторю: так же, как и при обычном назначении обработчика:

procedure TForm1.Button1Click(Sender: TObject);
begin
 ShowMessage((Sender as TComponent).Name)
end;

Button1Click(Form1)


И я не вижу в этом ничего страшного. Мой вариант работает так, как и обычный способ, а Ваш -- нет.


 
begin...end ©   (2005-11-27 15:30) [56]

> sniknik ©   (27.11.05 15:15) [54]

> > какая кнопочка нажата...

Вот именно. "Какая кнопочка нажата". Кнопочки у автора нажимаются, а не OnClick для них вручную вызывается.


 
sniknik ©   (2005-11-27 16:59) [57]

ну, если буквально, это не мой способ, мой был ответ почему при обращении ошибка вылетает. вылетала потому что в том виде он обращался к self который был не заполнен.
а по хорошему надо и то и то делать. (если бы не Data была не нужна то и борланд бы ее не заполнял, а так мало ли кто на self обьекта закладывается)


 
begin...end ©   (2005-11-27 18:22) [58]

> sniknik ©   (27.11.05 16:59) [57]

> ну, если буквально, это не мой способ

ОК, не Ваш. А тот, который Вы считаете правильным.

Или Вы уже не считаете его правильным? Если считаете -- то скажите, почему (я так и не понял, зачем Sender подменять чем-то своим), и почему он лучше моего (см. [47]). Если нет -- признайте, что ошибались.

> а по хорошему надо и то и то делать

По хорошему, надо делать только то, что надо. Предполагается внутри процедуры обращаться к Self -- значит, Data заполнять надо. Нет -- значит, нет.


 
sniknik ©   (2005-11-27 20:25) [59]

>  Нет -- значит, нет.
давай так. если не надо то и борланд не заполняет там где не надо, "расскрутим" операцию в обратку. любое пользовательское событие онклик/онкрейт/... любое слеланое нормально, борландом в дизайнере... ну без извратов.

найдеш такое, да согласен не надо.

например oncreate
procedure TForm1.Button1Click(Sender: TObject);
var Method: TMethod;
begin
 TNotifyEvent(Method):= Form1.onCreate;
 if Assigned(Method.Data) then Label1.Caption:= TComponent(Method.Data).Name;
end;
заполнено.
onDestroy
заполнено. и т.д.

любой метод любого компонента, до первого глюка (незаполнено).


 
begin...end ©   (2005-11-27 20:56) [60]

> sniknik ©   (27.11.05 20:25) [59]

Опять передёргиваем? Ну-ну.

Создаваемые в дизайнере обработчики -- это методы объекта (формы). В методе мы вправе пользоваться Self, поэтому недопустимо, чтобы он был равен nil.



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

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

Наверх





Память: 0.68 MB
Время: 0.033 c
1-1132156397
markers
2005-11-16 18:53
2005.12.11
"Конец перетаскивания"


2-1132557936
Alex_C
2005-11-21 10:25
2005.12.11
Как создать "независимый" телнет?


3-1130411409
diwww
2005-10-27 15:10
2005.12.11
Получить позицию первой выводимой записи в DBGrid-е


14-1132313939
dr Tr0jan
2005-11-18 14:38
2005.12.11
Новое крепление твоего вентилятора


1-1131740019
redlord
2005-11-11 23:13
2005.12.11
как узнать на сколько прога грузит проц ?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский