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

Вниз

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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.01 c
3-62972
NickNaz
2003-12-23 12:49
2004.01.20
Столбец DbGrid


1-63203
vgb
2004-01-10 00:09
2004.01.20
TWebBrowser


4-63447
Rul
2003-11-13 12:29
2004.01.20
ICQ


1-63237
hfa
2004-01-09 11:34
2004.01.20
Теперь такой вопрос как получить весь список расширений


3-62985
Chel
2003-12-23 17:11
2004.01.20
DBGrid





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