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

Вниз

TNotifyEvent   Найти похожие ветки 

 
афвуд ©   (2004-01-06 18:51) [0]

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


 
jack128 ©   (2004-01-06 19:02) [1]


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

TEventHandlers = class
public
class function NotifyEventHandler(Sender: TObject);
class function DatasetNotifyEventHandler(Sender: TDataSet);
// и так далее
end;


 
jack128 ©   (2004-01-06 19:03) [2]

пример использования -)

Button1.OnClick := TEventHandlers.NotifyEventHandler


 
YuRock ©   (2004-01-06 19:04) [3]

Межно разве-что создать класс с одним методом, объявить переменную этого класса и можно даже объект не создавать (пусть будет nil) - метод будет работать.

А потом можно писать что-то вроде:

OnClick := Object1.MyOnClick,

где Object1 на самом деле = nil.


 
Тимохов ©   (2004-01-06 19:08) [4]

jack128 © (06.01.04 19:02) [1]
Прикольная штука.
Сам придумал?


 
афвуд ©   (2004-01-06 19:09) [5]

>OnClick := Object1.MyOnClick,

>где Object1 на самом деле = nil.

Думаю будет Access Violation. Нужно хотя бы один обьект в памяти держать, чтобы в памяти его метод появился.


 
VMcL ©   (2004-01-06 19:10) [6]

Зачем спрашивать не буду.

Вот вариант:

procedure MyProc(Dummy: Pointer; Sender: TObject);
begin
ShowMessage("My");
end;

procedure TForm1.FormCreate(Sender: TObject);
var
MyMethod: TNotifyEvent;
begin
TMethod(MyMethod).Code := @MyProc;
TMethod(MyMethod).Data := nil;
Button1.OnClick := MyMethod;
end;


 
Тимохов ©   (2004-01-06 19:11) [7]

афвуд © (06.01.04 19:09) [5]
Вы как-то free вызываете для nil объектов и ничего - все работает.

Можете попробовать
TObject(nil).free();


 
афвуд ©   (2004-01-06 19:11) [8]

Тоже самое можно сказать про jack128-метод.

Надо ещё просто создать обьект.

Похоже это единтсвенный выход.


 
Vuk ©   (2004-01-06 19:13) [9]

Можно еще вспомнить, что указатель на метод - это структура, состоящая из двух указателей, на код метода и на данные экземпляра. А еще можно вспомнить, что методы от процедур отличаются неявным параметром self, который передается первым, и этот параметр - указатель на данные экземпляра (для методов экземпляра) или ссылка на класс (для методов класса).

Исходя из этого получаем:


procedure Test(DummySelf: pointer; Sender: TObject); register;
begin
...
end;

procedure TForm1.FormCreate(Sender: TObject);
var
N: TNotifyEvent;
begin
with TMethod(N) do
begin
Code := @Test;
Data := nil;
end;
Button1.OnClick := n;
end;


 
Тимохов ©   (2004-01-06 19:13) [10]

афвуд © (06.01.04 19:11) [8]
Често скажу [1] не проверял. Но этот метод (если работает) самый рульный - создать AV нереально...


 
YuRock ©   (2004-01-06 19:14) [11]

> афвуд © (06.01.04 19:09) [5]

Нет. Access Violation не будет никогда, т.к. MyOnClick (как и все методы) - просто функция, в которую параметром передается указатель на объект (Self). Ну и что, что он nil?

Access Violation будет только в том случае, если обратиться к свойствам несозданного объекта класса, но это делать в данном случае не нужно.


 
Vuk ©   (2004-01-06 19:15) [12]

Во! Пока писал уже ответили про то же самое! :o)


 
афвуд ©   (2004-01-06 19:16) [13]

Всё понял. Блин. Я сёня соображаловку похоже отключил :))

var m:TMethod

begin
m.Code=@MyProc;
m.Data=nil;
SetMethodProp(<Указатель на мой обьект>,"OnClick",&m);


Кажется так. Идею подал VMcL :) thx.


 
YuRock ©   (2004-01-06 19:17) [14]

... продолжение
> > афвуд © (06.01.04 19:09) [5]

И вообще я советую только то, что сам проверял и использовал.


 
Тимохов ©   (2004-01-06 19:22) [15]

Граждане!
Если уж зашел разговор на эту тему, то может объясните мне почему это работает.

tc = class
private s: string;
public procedure SetS( const S: string);
end;

tp = procedure ( {const}S: String) of object;

var
p: tp;
c: tc;
begin
c := tc.create();

tmethod(p).code := @tc.SetS;
tmethod(p).data := c;
p("1111");
end;

Мне казалось, что p("1111") должен давать AV.


 
афвуд ©   (2004-01-06 19:22) [16]

Т.е. SetMethodProp(<Указатель на мой обьект>,"OnClick",m);


 
Тимохов ©   (2004-01-06 19:27) [17]

забыл еще реализацию SetS

procedure tc.sets;
begin
fs := s;
showmessage(fs);
end;

Так вопрос - вроде, когда пишешь const, то передается указатель, а в случае без const, должна строка засовываться в буфер. Т.е. вроде как разный метод передачи данных, а все работате.
Или я что-то не понимаю в передаче параметров типа string?


 
YuRock ©   (2004-01-06 19:28) [18]

> Тимохов © (06.01.04 19:22) [15]

А почему это должно не работать? Ты же присваиваешь tmethod(p).data := c, а указатель на объект с - и есть указатель на структуру данных объекта (на сколько я понимаю).


 
Тимохов ©   (2004-01-06 19:29) [19]

YuRock © (06.01.04 19:28) [18]
См 17. Я там дал уточнение вопроса.


 
YuRock ©   (2004-01-06 19:30) [20]

> YuRock © (06.01.04 19:28) [18]

[18] к [17] относится. Правда я не знаю, что такое "fs"


 
jack128 ©   (2004-01-06 19:33) [21]


> Тимохов © (06.01.04 19:08) [4]


> Сам придумал?

Да.
Вообще лично я считаю, то что компилятор это пропускает - это баг. в procedure(Sender: Tobject) of object - первым неявным параметром передается объект(экземпляр класса), а в моем случае - классовая ссылка на teventhandler.На лицо несоответствее типов. Но борланду веднее. -)

> афвуд © (06.01.04 19:11) [8]
> Тоже самое можно сказать про jack128-метод.
Нет. Причины см выше.


 
VMcL ©   (2004-01-06 19:37) [22]

>>YuRock © (06.01.04 19:04) [3]

Если MyOnClick - виртуальный метод, то будет немного грустно.


 
Тимохов ©   (2004-01-06 19:37) [23]

jack128 © (06.01.04 19:33) [21]
Классный метод. Хотя с тем, что на лицо ошибка (вернее неточность) компилятора согласен.


 
YuRock ©   (2004-01-06 19:40) [24]

> [22]

Интересно... кому понадобится делать метод класса, объектов которого даже создаваться не будет, виртуальным?..

Все равно спасибо за уточнение.


 
Vuk ©   (2004-01-06 19:43) [25]

to jack128:
>Вообще лично я считаю, то что компилятор это пропускает - это
>баг.
С какого перепугу это баг-то? Указатель на метод = код + данные. В случае с объектом данные - это ссылка на экземпляр, а в случае с классом - ссылка на класс. И где баг?


 
VMcL ©   (2004-01-06 19:43) [26]

>>jack128 © (06.01.04 19:02) [1]

Кстати, гы: [Error] Function needs result type :))


 
VMcL ©   (2004-01-06 19:45) [27]

>>YuRock © (06.01.04 19:40) [24]

Ну мало что в голову взбредет. Человеку ж понадобилось обработчики of object на процедуры сослать (см. [0]) :))


 
jack128 ©   (2004-01-06 19:45) [28]


> Тимохов © (06.01.04 19:22) [15]

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


 
Vuk ©   (2004-01-06 19:48) [29]

to VMcL:
>Если MyOnClick - виртуальный метод, то будет немного грустно.
А также если даже метод невиртуальный, но там используются поля экземпляра.


 
jack128 ©   (2004-01-06 19:48) [30]


> Vuk © (06.01.04 19:43) [25]


> Указатель на метод = код + данные.
Ну если так, то бага нету. Просто я считаю, что нужно различать КЛАССОВЫЙ метод и просто метод. Но это мое личное мнение :-). А по твоему получается что данные могут быть любые (ну например целое число).


 
Vuk ©   (2004-01-06 19:49) [31]

to jack128:
>Просто я считаю, что нужно различать КЛАССОВЫЙ метод и просто
>метод.
А на кой черт оно надо? :o)


 
YuRock ©   (2004-01-06 19:49) [32]

> VMcL © (06.01.04 19:45) [27]

В принципе, иногда это удобно (вернее, не [0], а [1] или [3]), когда одинаковые по смыслу и реализации события разных по типу классов надо использовать. Или даже одинаковых по типу классов, но не всегда, а, скажем, часто...


 
Тимохов ©   (2004-01-06 19:50) [33]

jack128 © (06.01.04 19:45) [28]
Хорошо. Но это работает также для всех других типов.
Я всегда думал, что если не написать const для массива array[0..99] of integer то при передаче в метод он весь затолкался бы в стек. Если с const, то только указатель на начало массива. Насколько я понимаю в этом и есть суть (вернее ее часть) директивы const - в оптимизации.

Но даже для указанного массива это работает.
Я ясно сформулировал вопрос?


 
YuRock ©   (2004-01-06 19:52) [34]

> Vuk © (06.01.04 19:48) [29]

См. [11] (самый конец). Там этот вариант оговаривается.


 
jack128 ©   (2004-01-06 19:56) [35]


> Я всегда думал, что если не написать const для массива array[0..99]
> of integer то при передаче в метод он весь затолкался бы
> в стек
Я всегда считал иначе -). Если SizeOf(MyType) > 4 d регистры проца или в стек загоняется УКАЗАТЕЛЬ на переменную (мы говорим передаче по значению) В случае константной ссылки - всегда передается ссылка. За константностью следит компилятор.


 
Тимохов ©   (2004-01-06 19:59) [36]

jack128 © (06.01.04 19:56) [35]
А все-таки пример с массивом - там ясно больше чем 4 байта.

код

type
sss = array[1..10] of integer;
tc = class
public procedure SetS(const a: sss);
end;

procedure tc.sets;
begin
showmessage(inttostr(a[1]) + "-"+inttostr(a[10]));
end;

type
tp = procedure ({const}S: sss) of object;

procedure TForm1.Button17Click(Sender: TObject);
var
p: tp;
c: tc;
a: sss;
begin
a[1] := 12;
a[10] := 122;
c := tc.create();
tmethod(p).code := @tc.SetS;
tmethod(p).data := c;
p(a);
end;

выведется строка "12-122"


 
Vuk ©   (2004-01-06 20:00) [37]

to YuRock:
>Там этот вариант оговаривается.
Свойства, извините, это есть более хитрая вещь, чем поля экземпляра и с ними не так уж все однозначно. В конце концов для свойства в качестве аксессоров могут быть указаны два метода класса...


 
YuRock ©   (2004-01-06 20:02) [38]

> Тимохов © (06.01.04 19:59) [36]

Ну и что здесь удивительного?


 
Тимохов ©   (2004-01-06 20:04) [39]

YuRock © (06.01.04 20:02) [38]
Прочтите 33. Там я постарался сформулировать вопрос. В 36 пример кода.

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


 
YuRock ©   (2004-01-06 20:05) [40]

> Vuk © (06.01.04 20:00) [37]

Я имелл в виду классику ("классы состоят из методов (функций) и свойств (данных)")



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

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

Наверх




Память: 0.57 MB
Время: 0.033 c
3-62969
Danilas
2003-12-24 14:00
2004.01.20
Проблема с созданием сервера в InterBase


3-63005
Alex-kosmonavt
2003-12-23 11:21
2004.01.20
Insert


1-63152
Intell
2004-01-06 16:47
2004.01.20
Как убить любой процесс?


6-63269
Карелин Артем
2003-11-19 13:52
2004.01.20
Ftp-сервер на ICS. Как передавать/принимать потоки. Не файлы.


6-63284
Novenkij
2003-11-18 01:31
2004.01.20
Пересылка файлов