Форум: "Компоненты";
Текущий архив: 2007.07.01;
Скачать: [xml.tar.bz2];
ВнизНаследник TImage с парочкой новых свойств Найти похожие ветки
← →
Любопытствующий (2006-05-17 21:24) [0]Мастера! Создаю вот компонент - первый раз. Наследник
TImage
с парой свойств отTLabel
-OnMouseEnter
,OnMouseLeave
. Попытался просто скопировать изTLabel
описание этих свойств - только теперь после этой операции все старые свойства новогоTNewImage
стали недоступны - типаPicture.LoadFromFile
и все такое... Что там надо написать, чтобы и старые свойства остались открыты и новые появились?
← →
Любопытствующий (2006-05-17 21:50) [1]Уважаемые, помогите! ОЧень нужно!
← →
Юрий Зотов © (2006-05-17 21:54) [2]
type
TMyImage = class(TImage)
private
FOnMouseEnter: TNotifyEvent;
FOnMouseLeave: TNotifyEvent;
procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
protected
procedure MouseEnter; dynamic;
procedure MouseLeave; dynamic;
published
property OnMouseEnter: TNotifyEvent read FOnMouseEnter write FOnMouseEnter;
property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave;
end;
procedure TNotifyLabel.CMMouseEnter(var Message: TMessage);
begin
inherited;
MouseEnter
end;
procedure TNotifyLabel.CMMouseLeave(var Message: TMessage);
begin
inherited;
MouseLeave
end;
procedure TNotifyLabel.MouseEnter;
begin
if Assigned(FOnMouseEnter) then
FOnMouseEnter(Self)
end;
procedure TNotifyLabel.MouseLeave;
begin
if Assigned(FOnMouseLeave) then
FOnMouseLeave(Self)
end;
← →
Любопытствующий (2006-05-17 22:04) [3]Спасибо!
← →
Юрий Зотов © (2006-05-17 22:22) [4]TNotifyLabel везде заменить на TMyImage.
← →
Любопытствующий (2006-05-18 12:54) [5]Это я понял! А вот еще вопрос: можно ли автоматизировать события
OnMouseEnter
,OnMouseLeave
? Например создать еще одно свойствоPicture2
куда будет загружаться еще одна картинка, а затем поOnMouseEnter
будет загружатьсяPicture2
, а поOnMouseLeave
будет грузиться обратноPicture
? Типа такой кнопки в виде рисунка... Второе свойствоPicture2
я уже сделал и описал, а вот чего нужно дописать вOnMouseEnter
,OnMouseLeave
?
← →
DimaBr (2006-05-18 13:51) [6]Тогда нужно хранить два рисунка и показывать их поочереди
procedure TMyImage.MouseEnter;
begin
Picture.Assign(Picture1);
if Assigned(FOnMouseEnter) then
FOnMouseEnter(Self)
end;
procedure TMyImage.MouseLeave;
begin
Picture.Assign(Picture2);
if Assigned(FOnMouseLeave) then
FOnMouseLeave(Self)
end;
← →
DimaBr (2006-05-18 13:53) [7]Не, лучше менять местами, типа
Tmp = Picture
Picture := Picture2
Picture2 := Tmp
← →
Любопытствующий (2006-05-18 13:56) [8]А чем так лучше будет?
← →
Любопытствующий (2006-05-18 14:04) [9]Почему-то не работает - пишет method identifier expected
← →
Любопытствующий (2006-05-18 15:25) [10]В общем вышел такой код:
unit ExtImage;
interface
uses
Windows, Messages, SysUtils, Classes, Controls, ExtCtrls, Graphics;
type
TExtImage = class(TImage)
private
{ Private declarations }
FPictureActive: TPicture;
FPicturePassive: TPicture;
FOnMouseEnter: TNotifyEvent;
FOnMouseLeave: TNotifyEvent;
procedure SetPicture2(Value: TPicture);
procedure SetPicture3(value: TPicture);
procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
protected
{ Protected declarations }
procedure MouseEnter; dynamic;
procedure MouseLeave; dynamic;
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
{ Published declarations }
property PictureActive: TPicture read FPictureActive write SetPicture2;
property PicturePassive: TPicture read FPicturePassive write SetPicture3;
property OnMouseEnter: TNotifyEvent read FOnMouseEnter write FOnMouseEnter;
property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave;
end;
procedure Register;
implementation
constructor TExtImage.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FPictureActive := TPicture.Create;
FPicturePassive := TPicture.Create;
end;
procedure TExtImage.SetPicture2(Value: TPicture);
begin
FPictureActive.Assign(Value);
end;
procedure TExtImage.SetPicture3(Value: TPicture);
begin
FPicturePassive.Assign(Value);
end;
procedure TExtImage.CMMouseEnter(var Message: TMessage);
begin
inherited;
TExtImage(self).Picture.Assign(TExtImage(self).PictureActive);
MouseEnter
end;
procedure TExtImage.CMMouseLeave(var Message: TMessage);
begin
inherited;
TExtImage(self).Picture.Assign(TExtImage(self).PicturePassive);
MouseLeave
end;
procedure TExtImage.MouseEnter;
begin
if Assigned(FOnMouseEnter) then
FOnMouseEnter(Self)
end;
procedure TExtImage.MouseLeave;
begin
if Assigned(FOnMouseLeave) then
FOnMouseLeave(Self)
end;
destructor TExtImage.Destroy;
begin
FPictureActive.Free;
FPicturePassive.Free;
inherited Destroy;
end;
procedure Register;
begin
RegisterComponents("Additional", [TExtImage]);
end;
end.
Работает, только когда создано два дополнительных Picture, а это ж я так понимаю, дополнительный расход ресурсов? Нельзя по-другому?
← →
Юрий Зотов © (2006-05-18 16:06) [11]Если хотите иметь 2 картинки, значит, где-то их надо хранить? Они же не могут взяться ниоткуда?
Но у Вас полоучилось 2 дополнительные картинки, плюс одна родная - итого 3. А можно обойтись и двумя - если сделать только одну дополнительную картинкой, а в качестве второй использовать родную.
Как - см. [7]. Заодно и вопрос [8], видимо станет понятен.
← →
Любопытствующий (2006-05-18 18:37) [12]Все, понял! Всем большое спасибо!
← →
DimaBr (2006-05-19 09:26) [13]
TExtImage = class(TImage)
private
fPictureTmp: TPicture;
FOnMouseEnter: TNotifyEvent;
FOnMouseLeave: TNotifyEvent;
procedure SetPictureTmp(const Value: TPicture);
procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
protected
procedure MouseEnter; dynamic;
procedure MouseLeave; dynamic;
procedure SwapPicture;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property PictureTmp: TPicture read fPictureTmp write SetPictureTmp;
property OnMouseEnter: TNotifyEvent read FOnMouseEnter write FOnMouseEnter;
property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave;
end;
var
Form1: TForm1;
a: TExtImage;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
a := TExtImage.Create(self);
a.Parent := form1;
a.PictureTmp.LoadFromFile("D:\MyProject\Bmp\BitMapAnimation\Apple.bmp");
a.Picture.LoadFromFile("D:\MyProject\Bmp\BitMapAnimation\Info.bmp");
end;
//**********************************************************
constructor TExtImage.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
fPictureTmp := TPicture.Create;
end;
procedure TExtImage.SetPictureTmp(const Value: TPicture);
begin
fPictureTmp.Assign(Value);
end;
procedure TExtImage.CMMouseEnter(var Message: TMessage);
begin
inherited;
MouseEnter;
end;
procedure TExtImage.CMMouseLeave(var Message: TMessage);
begin
inherited;
MouseLeave;
end;
procedure TExtImage.MouseEnter;
begin
SwapPicture;
if Assigned(FOnMouseEnter) then FOnMouseEnter(Self);
end;
procedure TExtImage.MouseLeave;
begin
SwapPicture;
if Assigned(FOnMouseLeave) then FOnMouseLeave(Self);
end;
destructor TExtImage.Destroy;
begin
fPictureTmp.Free;
inherited Destroy;
end;
procedure TExtImage.SwapPicture;
var APicture: TPicture;
begin
APicture:= TPicture.Create;
try
APicture.Assign(Picture);
Picture.Assign(PictureTmp);
PictureTmp.Assign(APicture);
finally
APicture.Free;
end;
end;
← →
Юрий Зотов © (2006-05-19 17:37) [14]> DimaBr (19.05.06 09:26) [13]
Хороший код. Чистый, понятный, надежный. Eсть все, что нужно и нет ничего лишнего. Так и надо писать, особенно компоненты.
Но почему выбрано имя "PictureTmp" Это же не временная картинка, более подошло бы что-то вроде "AlternatePicture", или уж хотя бы просто "Picture2".
И еще. Помня о возможных потомках, я бы сделал метод SwapPicture динамическим - чтобы смену картинок можно было легко перехватить и выполнить какие-то дополнительные действия (например, это позволит потомку легко и просто ввести событие OnSwapPicture).
← →
DimaBr (2006-05-19 18:08) [15]1. Обозвал TMP? поскольку это первое что пришло в голову. Согласен, что AlternatePicture подойт, можно и "SwapPicture".
2. Так вроде бы легко перехватить MouseEnter, типаprocedure TNewExtImage.MouseEnter;
begin
inherited;
if Assigned(OnSwapPicture) then OnSwapPicture(self);
end;
← →
Юрий Зотов © (2006-05-19 19:01) [16]> DimaBr (19.05.06 18:08) [15]
> Так вроде бы легко перехватить MouseEnter, типа
Да, если точно знать, что смена картинок происходит непосредственно в этом месте кода, а не через еще какую-то цепочку. То есть, при наличии исходников.
А теперь представьте, что Вы написали пакет компонентов, а я купил его без исходников, только с документацией (например, с интерфейсными частями модулей). И мне понадобилось написать потомок Вашего компонента, добавив в него событие смены картинок. Увидев в интерфейсной части динамический метод SwapPicture, я тут же соображу, что именно его и надо перекрывать - и на 99% не ошибусь. А если этот метод статический - как мне быть? Оно, конечно, понятно, что все построено на перехвате сообщений СМ - но, не имея исходников, откуда я знаю, какую цепочку Вы оттуда запускаете, в какое ее место мне можно безопасно вклиниться и как это сделать? Проблема, однако.
Скажете, ситуация невероятная? Возможно. Однако, если подходить к разработке компонентов профессионально (а НЕпрофессионально лучше не подходить к ней вообще), то именно такую ситуацию и следует предполагать заранее. Как раз подобными штучками и отличается мышление профессионального component writer"а от мышления прикладного программиста. Он пишет не КОНКРЕТНУЮ ПРОГРАММУ, он пишет УНИВЕРСАЛЬНЫЙ ИНСТРУМЕНТ. И мыслить должен соответственно.
← →
DimaBr (2006-05-22 08:25) [17]Ладно, уговорили. Доверюсь профессионалу. Спасибо (и в моём лице тоже) за небольшую лекцию.
← →
Txc © (2006-08-25 09:58) [18]А как можно отловить нажатие левой клавиши мыши на такую картинку?
← →
StriderMan © (2006-08-25 10:35) [19]событие OnMouseDown, и в нем проанализировать
mbLeft in Button
← →
Наиль © (2006-08-25 11:28) [20]
> событие OnMouseDown, и в нем проанализировать
Нельзя назначать события на этапе разработки компоненты.
Поэтому для данной задачи надо перекрыть метод MouseDown, выполнить обработку mbLeft и не забыть про inherited.
А события предназначены для конечного пользователя компонентов.
Исключением является использование скрытых (private) компонентов, являющихся частью собсвеного, тогда можно им назначать события, ибо нельзя изменить такие события, ни когда, кроме как, на этапе разработки собственного компонента.
← →
StriderMan © (2006-08-25 16:09) [21]
> Наиль © (25.08.06 11:28) [20]
складно излагаете, вам бы книжки писать :))
а в чем проблема в ран-тайме прицепить к такому компоненту обработчик? или в дизайн-тайме?
впрочем все верно, если поведение контрола на нажатие кнопки мыши определяется для компонента раз и навсегда то конечно надобно просто перекрыть MouseDown
← →
Юрий Зотов © (2006-08-25 16:19) [22]> StriderMan © (25.08.06 16:09) [21]
Разница в том, что в OnMouseDown юзер может заменить Ваш обработчик своим - и компонент работать перестанет.
← →
StriderMan © (2006-08-25 17:25) [23]
> Юрий Зотов © (25.08.06 16:19) [22]
в вопросе:
> как можно отловить нажатие левой клавиши мыши на такую картинку?
никаких дополнительных условий не было. не так ли?
или это вытекает из сабжа?
← →
Юрий Зотов © (2006-08-25 18:07) [24]> StriderMan © (25.08.06 17:25) [23]
Это вытекает из сабжа. Пишется компонент, а не приложение - что и есть то самое дополнительное условие.
← →
StriderMan © (2006-08-25 18:29) [25]
> Юрий Зотов © (25.08.06 18:07) [24]
ладно, убедили :)
Страницы: 1 вся ветка
Форум: "Компоненты";
Текущий архив: 2007.07.01;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.005 c