Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Компоненты";
Текущий архив: 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.53 MB
Время: 0.006 c
1-1178129410
Nicky000
2007-05-02 22:10
2007.07.01
Фильтр с использованием ComboBox


3-1175679671
Сергей Ю
2007-04-04 13:41
2007.07.01
Открыть приложение с IBQuery на другой машине


2-1181153421
framez
2007-06-06 22:10
2007.07.01
процессы


1-1178164475
Novice
2007-05-03 07:54
2007.07.01
Поиск файлов FindNext, FindFirst


2-1181152092
Ламер 2.Х
2007-06-06 21:48
2007.07.01
Админ





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