Форум: "Основная";
Текущий архив: 2004.04.04;
Скачать: [xml.tar.bz2];
Внизметоды объектов Найти похожие ветки
← →
_Guest_ (2004-03-12 14:33) [0]
unit Unit1;
implementation
var
FTimer: TTimer;
initialization
FTimer := TTimer.Create(nil);
FTimer.OnTimer := ?
finalization
FTimer.Free;
end.
как мне описать процедуру, которая будет вызываться по событию OnTimer?
← →
alless © (2004-03-12 14:39) [1]po moemu tak:
FTimer.OnTimer:=MyProcedure;
procedure MyProcedure(Sender:TObject)
begin
Showmessage("OnTimer")
end;
← →
Amoeba © (2004-03-12 14:40) [2]Читаем:
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=342
← →
MU (2004-03-12 14:41) [3]unit Unit2;
interface
implementation
uses ExtCtrls;
type
TMyTimer = class(TTimer)
procedure OnMyTimer(Sender : TObject);
end;
var
FTimer: TMyTimer;
{ TMyTimer }
procedure TMyTimer.OnMyTimer(Sender: TObject);
begin
//...
end;
initialization
FTimer := TMyTimer.Create(nil);
FTimer.OnTimer := FTimer.OnMyTimer;
finalization
FTimer.Free;
end.
← →
_Guest_ (2004-03-12 14:56) [4]2alless: это работать не будет.
2amoeba: ссылка клёвая да беспонтовая. Если нужную мне процедуру объвить внутри класса, то никаких проблем нету, так как она будет являться методом класса. А как это сделать, если нету класса?
2MU: а без объявления наследника?
← →
MU (2004-03-12 15:01) [5]unit Unit2;
interface
implementation
uses ExtCtrls, Dialogs;
type
TMyObject = class(TObject)
class procedure OnMyTimer(Sender : TObject);
end;
var
FTimer: TTimer;
{ TMyTimer }
class procedure TMyObject.OnMyTimer(Sender: TObject);
begin
FTimer.Enabled := false;
ShowMessage("Timer");
FTimer.Enabled := true;
end;
initialization
FTimer := TTimer.Create(nil);
FTimer.Interval := 1000;
FTimer.OnTimer := TMyObject.OnMyTimer;
FTimer.Enabled := true;
finalization
FTimer.Free;
end.
:))
← →
PVOzerski © (2004-03-12 15:01) [6]А метод без класса не бывает. Во-первых, процедурная переменная для метода - не один указатель, а связка из двух, во-вторых, вызов метода сопровождается неявной передачей как параметра указателя на экземпляр. "Хакерский" вариант решения состоит в том, чтобы вручную сварганить через какой-нибудь move "метод" из процедуры, нормальное же решение - написать метод как метод.
← →
Amoeba © (2004-03-12 15:05) [7]А как это сделать, если нету класса?
Никак. Процедура обязательно должна быть методом какого-нибудь класса. Надо учить матчасть.
В частности можно использовать совет
MU (12.03.04 14:41) [3]
Как вариант можно создать наследника TObject c необходимым методом. Экземпляр этого класса создавать в initialization до создания таймера.
← →
_Guest_ (2004-03-12 15:06) [8]спасибо, понял - вопросов больше не имею :)
← →
PVOzerski © (2004-03-12 15:10) [9]2Amoeba:
а надо ли создавать экземпляр? Описать как class procedure и прямо так и передавать: tMyClass.MyProc?
← →
MU (2004-03-12 15:12) [10]PVOzerski © (12.03.04 15:10) [9]
[5] ;)
← →
evvcom (2004-03-12 15:37) [11]procedure OnMyTimer(TimerObject, Sender: TObject);
begin
// Здесь TimerObject - формальный параметр.
// OnMyTimer вызывается как procedure of object,
// поэтому в нее неявно передается еще указатель на
// экземпляр класса, в котором должно
// обрабатываться это событие, поэтому,
// чтобы обмануть компилятор введем в параметры явную
// передачу ссылки на экземпляр!
end;
TMethod(FTimer.OnTimer).Code := @OnMyTimer;
← →
evvcom (2004-03-12 15:39) [12]TimerObject - поспешил, просто указатель на экземпляр какого-то класса, который не имеет здесь никакого смысла, но обозвать этот параметр как-то надо! А анализировать его нельзя.
А вот Sender и будет TTimer
← →
evvcom (2004-03-12 15:41) [13]TimerObject лучше обозвать каким-нибудь Nothing
← →
WebErr © (2004-03-12 15:42) [14]
> evvcom (12.03.04 15:37) [11]
Вот это уже дорогого стоит! А работать будет ли? :))))
← →
KSergey © (2004-03-12 15:45) [15]> [3] MU (12.03.04 14:41)
Если уж беретесь писать наследников - так хоть пишите грамотно, ага?
> type
> TMyTimer = class(TTimer)
private
procedure Timer; override;
> end;
>
> var
> FTimer: TMyTimer;
>
> { TMyTimer }
>
> procedure TMyTimer.Timer;
> begin
> //...
> end;
>
> initialization
> FTimer := TMyTimer.Create(nil);
> FTimer.OnTimer := FTimer.OnMyTimer;
>
> finalization
> FTimer.Free;
> end.
← →
KSergey © (2004-03-12 15:50) [16]> [15] KSergey © (12.03.04 15:45)
Промашечка вышла! Главное убрать забыл:
> FTimer.OnTimer := FTimer.OnMyTimer; - убрать!
← →
MU (2004-03-12 15:54) [17]>>KSergey © (12.03.04 15:45) [15]
И что же было неправильно, я не понял?
← →
MU (2004-03-12 15:57) [18]>>KSergey © (12.03.04 15:50) [16]
>>Промашечка вышла! Главное убрать забыл
Так не работает... Надо убирать все...
← →
evvcom (2004-03-12 15:59) [19]
> WebErr © (12.03.04 15:42) [14]
>
> > evvcom (12.03.04 15:37) [11]
>
> Вот это уже дорогого стоит! А работать будет ли? :))))
У меня работает. В свое время про TMethod я у Юрия Зотова вычитал. Так что апплодисменты ему адресуйте.
← →
KSergey © (2004-03-12 16:08) [20]> [17] MU (12.03.04 15:54)
> >>KSergey © (12.03.04 15:45) [15]
> И что же было неправильно, я не понял?
В потомках принято перекрывать предназначенные для этого методы, а не вешать свои обработчики на события компонента.
Да, в данном случае формально результат будет одинаков, т.к. не создание компонента обсуждаем, но все же считаю, что такой стиль привьет неверные привычки.
А по поводу [11] evvcom (12.03.04 15:37) или > [6] PVOzerski © (12.03.04 15:01) (в части "хакерских" методов) - в данном случае не вижу разницы: описать простейшего потомка, в котором перекрыть метод Timer или написать TMethod(...) - по-моему, здесь - одинаково.
Однако в данном случае решение через потомка в перекрытым методом Timer видится мне наиболее красивым и правильным.
← →
MU (2004-03-12 16:17) [21]>>KSergey © (12.03.04 16:08) [20]
Вы извините, я не придираюсь, но у меня
это код не работает.
в proc TMyTimer.Timer не попадает.
unit Unit2;
interface
implementation
uses ExtCtrls, Dialogs;
type
TMyTimer = class(TTimer)
private
procedure Timer; override;
end;
var
FTimer: TMyTimer;
{ TMyTimer }
procedure TMyTimer.Timer;
begin
FTimer.Enabled := false;
ShowMessage("Timer");
FTimer.Enabled := true;
end;
initialization
FTimer := TMyTimer.Create(nil);
FTimer.Interval := 10;
FTimer.Enabled := true;
finalization
FTimer.Free;
end.
← →
MU (2004-03-12 16:21) [22]Не работает...
unit Unit2;
interface
implementation
uses ExtCtrls, Dialogs;
type
TMyTimer = class(TTimer)
private
procedure Timer; override;
end;
var
FTimer: TMyTimer;
{ TMyTimer }
procedure TMyTimer.Timer;
begin
Enabled := false;
ShowMessage("Timer");
Enabled := true;
end;
initialization
FTimer := TMyTimer.Create(nil);
FTimer.Interval := 10;
FTimer.Enabled := true;
finalization
FTimer.Free;
end.
← →
_Guest_ (2004-03-12 16:29) [23]2evvcom:
не работает TMethod(FTimer.OnTimer).Code := @OnMyTimer;
говорит, Left side cannot be assigned to
← →
evvcom (2004-03-12 16:40) [24]Прошу прощения. Немного не туда глянул в свои исходники. Поправь так:
var
pMethod: ^TMethod;
begin
pMethod := @@FTimer.OnTimer;
pMethod.Code := @OnMyTimer;
end;
← →
_Guest_ (2004-03-12 16:48) [25]другое дело - так работает
← →
evvcom (2004-03-12 22:56) [26]Или более оптимально:
type
PMethod = ^TMethod;
begin
PMethod(@@FTimer.OnTimer)^.Code := @OnMyTimer;
end;
← →
KSergey © (2004-03-15 09:25) [27]> MU (12.03.04 16:21) [22]
Мда.. Маненько я погорячился.
Оказывается, есть определенная проблема с таймером: собственно запуск таймера осуществляется в методе TTimer.UpdateTimer, где проеврятеся обязательное задание метода обработчика в FOnTimer. Иначе таймер не устанавливается.
Вот в этом вся и беда, потому этот код не работат. В общем-то был не прав, недодумал, что так может быть. Хотя это, конечно, частный случай...
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2004.04.04;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.038 c