![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Наследник от TShape со встроенным таймером
ssk © (2004-07-06 14:38:00)Всем привет! Посмотрите, пожалуйста, код и поправьте меня, где я ошибся. Проблема в том, что после установки компонента в среду, код, прописанный в обработчике OnShapeTimer, не отрабатывает, хотя при компиляции видно, что строки в обработчике отмечаются как "прокомпилированные" синими метками. Почему? Что не так? Спасибо.
unit ShapeTimer;
interface
uses
Classes, ExtCtrls;
type
TShapeTimer = class(TShape)
private
FTimer: TTimer;
FOnShapeTimer: TNotifyEvent;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property OnShapeTimer: TNotifyEvent read FOnShapeTimer write FOnShapeTimer;
property Timer: TTimer read FTimer write FTimer;
end;
procedure Register;
implementation
constructor TShapeTimer.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FTimer:=TTimer.Create(Self);
FTimer.Enabled:=False;
FTimer.Interval:=1000;
FTimer.OnTimer:=OnShapeTimer;
end;
destructor TShapeTimer.Destroy;
begin
inherited Destroy;
end;
procedure Register;
begin
RegisterComponents('Samples', [TShapeTimer]);
end;
end.
Юрий Зотов (2004-07-06 17:04:00) [1]> ssk © (06.07.04 16:51) [7]
Это и имелось в виду. Поле - private, а соответствующее ему свойство - public (либо protected) и read-оnly. Никаких ресурсов не жрет, но очень полезно в плане возможных наследников.
ssk (2004-07-06 16:51:00) [2]>3. Убрать свойство FTimer в public и сделать его read-only, а Enabled и Interval вытащить наружу по аналогии с OnTimer.
именно так я и сделал, только FTimer поместил в private.
Юрий Зотов (2004-07-06 16:36:00) [3]> ssk © (06.07.04 16:06) [5]
Тут три варианта решения:
1. Для D6 и выше - посмотрите csSubComponent.
2. Объявить свойство Timer со stored False и писать его в DFM ручками (см. DefineProperties, и TReader/TWriter - Read/WriteComponent).
3. Убрать свойство FTimer в public и сделать его read-only, а Enabled и Interval вытащить наружу по аналогии с OnTimer.
Рекомендую вариант 3. Об этом же говорил и MBo в [3].
ssk (2004-07-06 16:06:00) [4]>MBo
>Юрий Зотов
спасибо за помощь.
переделал, попробовал. работает. в принципе разобрался и идею понял, но остался один момент: после изменения в design-time значения интервала для таймера, в самой программе оно не меняется: как было 1000, так и осталось. меняется тогда, когда в run-time изменить принудительно. попробую теперь это сам исправить...
Юрий Зотов (2004-07-06 15:15:00) [5]> ssk
1. В момент выполнения конструктора компонент еще не загружен из DFM и поэтому FOnShapeTimer равно nil. Таким образом, реально никакой обработчик не назначается и, соответственно, событие не отрабатывает.
2. При объявлении
property Timer: TTimer read FTimer write FTimer;
есть опасность утечки памяти.
3. Деструктор здесь не нужен.
4. Чтобы свойство Timer появлялось в Object Inspector с плюсиком и списком подсвойств, для него нужно назначить другй редактор.
В итоге получим вот что.
type
TShapeTimer = class(TShape)
private
FTimer: TTimer;
procedure SetTimer(const Value: TTimer);
function GetOnShapeTimer: TNotifyEvent;
procedure SetOnShapeTimer(const Value: TNotifyEvent);
public
constructor Create(AOwner: TComponent); override;
published
property Timer: TTimer read FTimer write SetTimer;
property OnShapeTimer: TNotifyEvent
read GetOnShapeTimer write SetOnShapeTimer;
end;
constructor TShapeTimer.Create(AOwner: TComponent);
begin
inherited;
FTimer := TTimer.Create(Self);
FTimer.Enabled := False
end;
procedure TShapeTimer.SetTimer(const Value: TTimer);
begin
FTimer.Assign(Value) // Или оставить пустое тело метода
end;
function TShapeTimer.GetOnShapeTimer: TNotifyEvent;
begin
Result := FTimer.OnTimer
end;
procedure TShapeTimer.SetOnShapeTimer(const Value: TNotifyEvent);
begin
FTimer.OnTimer := Value
end;
procedure Register;
begin
RegisterComponents('Samples', [TShapeTimer]);
RegisterPropertyEditor
(TTimer.ClassInfo, TShapeTimer, 'Timer', TClassProperty)
end;
MBo (2004-07-06 15:05:00) [6]Тьфу ты, проглядел ;(
таймер же не связывается с обработчиком
...
procedure SetShapeTimer(const Value: TNotifyEvent);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property OnShapeTimer: TNotifyEvent read FShapeTimer write SetShapeTimer;
procedure TShapeTimer.SetShapeTimer(const Value: TNotifyEvent);
begin
FTimer.OnTimer:=Value;
FShapeTimer:=Value;
end;
А вообще, нужно переработать интерфейс компонента - не светить наружу FTimer, только методы доступа к нему.
ssk (2004-07-06 14:51:00) [7]>а где запуск?
запуск делается потом в приложении в нужном месте:
ShapeTimer1.Timer.Enabled:=True;
а при создании (вернее, при "кидании" компонента на форму) по умолчанию таймер выключен. или я что-то не так понимаю?
MBo (2004-07-06 14:45:00) [8]> FTimer.Enabled:=False;
а где запуск?