Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.04.25;
Скачать: CL | DM;

Вниз

Реализация компонента-обертки   Найти похожие ветки 

 
pasha_golub ©   (2004-04-01 11:14) [0]

Реализовываю компонент-обертку над каким либо контролом (TWinControl). В задачу компонента входит обработка событий OnMouseLeave & OnMouseEnter (спасибо MBo за идею) и показ in-place подсказок. Компонент будет прародителем для заточенных под конкретный контрол компонентов.

Вообщем, сомнения меня берут по поводу добавления\удаления контрола в design-time, посему прошу взгялнуть на реализацию и ткнуть носом. Спасибо.

TCustomToolTip = class(TComponent)
   private
...
     FOldTipControlWndProc: TWndMethod;
     FTipControl: TWinControl;

...
     procedure SetEnabled(Value: boolean);

     procedure SetTipControl(Value: TWinControl);
     procedure SetWindowProc;
   protected
     procedure NewTipControlWndProc(var Msg: TMessage);
     procedure Notification(AComponent: TComponent;
               Operation: TOperation); override;
   public
...
     property Enabled:boolean read FEnabled
              write SetEnabled default True;
...
     property TipControl:TWinControl read FTipControl
               write SetTipControl;
...
   end;
implementation

procedure TCustomToolTip.Notification(AComponent: TComponent;
               Operation: TOperation);
begin
 inherited;
 if (AComponent = FTipControl) and (Operation = opRemove) then begin
  FTipControl := nil;
  SetEnabled(False);
end;
end;

procedure TCustomToolTip.SetTipControl(Value: TWinControl);
begin
 if FTipControl <> Value then
  begin
    if not (csLoading in ComponentState) then
    begin
      if Assigned(FTipControl) and FEnabled then
        FTipControl.WindowProc := FOldTipControlWndProc;
    end;
    FTipControl := Value;
    if Assigned(FTipControl) then
    begin
      FTipControl.FreeNotification(Self);
      if FEnabled then
        SetWindowProc;
    end;
  end;
end;

procedure TCustomToolTip.SetWindowProc;
begin
FOldTipControlWndProc := FTipControl.WindowProc;
FTipControl.WindowProc := NewTipControlWndProc;
end;

procedure TCustomToolTip.NewTipControlWndProc(var Msg: TMessage);
begin
if Msg.Msg = CM_MouseLeave then
   SetVisible(False)
else
   FOldTipControlWndProc(Msg);
end;


Поимка событий мыши производится через подмену оконной процедуры контрола.


 
pasha_golub ©   (2004-04-01 11:17) [1]

И когда и в каком случае (и кто и откуда) вызывает procedure TCustomToolTip.Notification? Спасибо.


 
pasha_golub ©   (2004-04-01 11:58) [2]

И все-таки, попрошу расстолковать. Спасибо.


 
Asdor ©   (2004-04-01 12:49) [3]

Notification вызывается в нескольких случаях:
1. При создании компонента если указан его Owner, то для всех компонентов, для которых Owner является Owner"ом вызывается Notification о добавлении нового компонента.
2. При уничтожении компонента если у него есть Owner, то для всех компонентов, для которых Owner является Owner"ом вызывается Notification о удалении компонента.
3. Если компонент1 подписывается на FreeNotification другого компонента2, по перед своим уничтожением тот другой компонент2 вызовет Notification компонента1.

Вроде так. :)


 
pasha_golub ©   (2004-04-01 13:24) [4]

Asdor ©   (01.04.04 12:49) [3]
Хм, спасибо и на этом.


 
pasha_golub ©   (2004-04-01 16:34) [5]

Ну, скажите мне, пожалуйста, правильно или нет?


 
Юрий Зотов ©   (2004-04-01 18:49) [6]

1. Нет восстановления оконной прцедуры при удалении компонента.
2. Вообще говоря, игры с WindowProc небезопасны. Что будет, если юзер кинет на форму несколько таких компонентов и назначит им один один и тот же TipControl - а потом удалит их в произвольной последовательности? Чтобы разрулить такую ситуацию придется делать еще один класс (менеджер TCustomToolTip"ов). Он должен создаваться в initialization, уничтожаться в finalization, вести список TCustomToolTip"ов и следить за корректным назначением/восстановлением оконных процедур.


 
pasha_golub ©   (2004-04-01 19:01) [7]

Юрий Зотов ©   (01.04.04 18:49) [6]
1. Есть, я просто деструктор не привел.
2. А как же тогда красиво?


 
Юрий Зотов ©   (2004-04-01 19:14) [8]

> pasha_golub ©   (01.04.04 19:01) [7]

Паш, изложи задачу. Обычно путей бывает несколько и не всегда самый короткий - это самый лучший. Поищем другой вариант, а если не найдем - придется писать менеджер или рулить как-то еще. От задачи многое зависит, надо ее знать.


 
pasha_golub ©   (2004-04-01 19:21) [9]

Задача:

Написать компонент-предок TCustomToolTip, который будет показывать ин-пласе подсказки в обход привычного механизма Делфи, а именно с помошью ToolTips.

1. К каждому контролу необходимо прилепить один компонент-обертку.
2. Компонент-обертка должден ловить сообщения о выходе мыши за пределы контрола и соответственно прятать ин-пласе подсказку.

В принципе все.


 
Vuk ©   (2004-04-01 19:24) [10]

А зачем в обход стандартного механизма?


 
Юрий Зотов ©   (2004-04-01 19:43) [11]

Зачем в обход - мне тоже непонятно. Но если уж так нужно выпендриться, то я бы сделал не компонент, а специальную форму. Все входы-выходы мыши по контролам форма уже и так ловит и остается только написать показ-прятанье, без всякой подмены оконных процедур. И еще очень простой эксперт IDE - чтобы в репозитории на странице New появилась строка а-ля ToolTip Form.

А чтобы все совсем было красиво, добавил бы в эту спецформу свойство ToolTips (через TCustomModule), а к нему диалоговый редактор из двух связанных листбоксов (слева - список контролов, справа - назначенный контролу класс тултипа). Тогда можно будет написать библиотечку суперпупертултипов, зарегистрировать их в своем же модуле и все будет кульно и рулезно - каждый контрол сможет показывать свой собственный тултип, хоть в виде бублика. AvtoShema отдыхает.

Только на фига все это?


 
Vuk ©   (2004-04-01 19:49) [12]

Нафига может возникнуть желание сделать свои тултипы, как раз понятно. Непонятно, зачем делать это в обход стандартной системы, которая позволяет себя расширять. Зачем прикручивать сбоку механизм, который еще неизвестно как состыкуется с существующей системой?


 
pasha_golub ©   (2004-04-02 09:38) [13]

Vuk ©   (01.04.04 19:49) [12]

Вообщем-то существующая система, по моему субъектнивному, не реализовывает механизма tracking tooltip, а именно как показали в нужном месте и ждем до упора пока мыша не выйдет за пределы данного места.

То есть стандартным механизмом я то подсказку покажу, но она же зараза отработает и свернется через Application.HintHidePause. А какая же это in-place подсказка.

Далее, in-place подсказка перекрывает клиентскую область контрола для которого показывается, то есть просто как бы расширяет ее. А стандартная подсказка (встроенная) всплывает по координатам мыши.

Далее стандартная подсказка прячется, как только контрол получает события мыши (WM_FIRST..WM_LAST) или от клавиатуры, и этого никак не победить, потому как проверка идет внутри класса TApplication.  А подсказка по месту прячется в случае выхода за пределы контрола или при клике мыши.

2Юрий

Я вот тут ночью подумал. Вы привели пример нескольких компонентов с одинм целевым контролом. Но позвольте, ведь можно же кинуть на форму десять листбоксов, например, и всем им назначить одно и то же popupmenu. И страшного ничего вроде не будет. Вот и я думаю, если все правильно разрулено... Вообщем, надеюсь понятно.

Спасибо


 
Vuk ©   (2004-04-02 11:42) [14]

to pasha_golub ©   (02.04.04 09:38) [13]:
А если CM_HINTSHOW обработать?


 
pasha_golub ©   (2004-04-02 11:50) [15]

Vuk ©   (02.04.04 11:42) [14]
Не догнал, сорри. Где в ThintWindow или в TApplication.OnMessage или еще где?


 
Vuk ©   (2004-04-02 11:54) [16]

В контроле, для которого Hint.


 
pasha_golub ©   (2004-04-02 12:21) [17]

Vuk ©   (02.04.04 11:54) [16]

Да, есть такое, но вот чего-то я не найду по этому сообщению в хелпе ничего. Нашел только, что посылается перед показом хинта вместе со структурой, которая дрежит координаты и т.д.

Может я искал плохо? Тоды прошу по возможности пихануть конкретно где оно. Спасибо


 
pasha_golub ©   (2004-04-02 12:48) [18]

Нашел, вроде бы оно. Но вопрос про отключение подсказки при Wm_first..WM_last & сообщения от клавы, остается открытым


 
Юрий Зотов ©   (2004-04-02 17:19) [19]

> ведь можно же кинуть на форму десять листбоксов, например, и
> всем им назначить одно и то же popupmenu. И страшного ничего
> вроде не будет.

А разве popupmenu замещает оконные процедуры? Все дело-то ведь в этом.


 
pasha_golub ©   (2004-04-02 17:53) [20]

Юрий Зотов ©   (02.04.04 17:19) [19]
Ну да, ну да.

Но все-таки, Юрий, смоделируйте еще раз ситуацию при которой будет Отсос Виалайшн. И другими словами, чем в Юрий Зотов ©   (01.04.04 18:49) [6], потому как туманно тама все. Спасибо.


 
Mim ©   (2004-04-02 21:02) [21]

Например

cmp1 constructor
 old wp := cur wp;
 cur wp := new wp;

cmp2 constructor
 old wp := cur wp; \\ вот тут то в переменную old wp попрадает процедура от компонента cmp 1
 cur wp := new wp;

cmp1 desctuctor
 cur wp := old wp;

cmp2 desctuctor
 cur wp := old wp; \\ а тут мы присваиваем оконную процедуру уничтоженого компоенета (av)

Прощу прощения за "образность" :).


 
Юрий Зотов ©   (2004-04-03 13:07) [22]

> pasha_golub ©   (02.04.04 17:53) [20]

Бросьте на форму кнопку и 2 своих компонента (будем называть их c1 и c2). Им обоим назначьте ToolTip"ом эту кнопку - сначала с1, потом c2. Теперь удалите с формы сначала c1, потом c2 - и при удалении c2 получите AV. Причину см. в [21].

Поэтому и нужен менеджер - чтобы отслеживать такие ситуации и правильно их разруливать. Но если юзер использует еще какой-нибудь подобный компонент (из совершенно другого пакета, о котором менеджер ничего не знает и знать не может) - то не поможет и менеджер.


 
Юрий Зотов ©   (2004-04-03 13:47) [23]

Забыл добавить.

Если юзер использует еще какой-нибудь подобный компонент (из совершенно другого пакета, о котором мы ничего не знаем и знать не можем), то этот компонент может заменить уже НАШУ WndProc. И привет - даже если с формы ничего не удалялось и AV не возникает, наш компонент просто не будет работать.


 
pasha_golub ©   (2004-04-05 12:59) [24]

Мдя, блин. Есть такое, есть. То есть замена оконной процедуры не есть харащо. Ну, а каким методом можно поймать сообщения чужого контрола? Вот ведь, как.


 
Юрий Зотов ©   (2004-04-05 13:20) [25]

> pasha_golub ©   (05.04.04 12:59) [24]

Зачем подменять WndProc формы, если можно вместо компонента написать свою, специальную форму - и у нее заместить WndProc (благо, что этот метод виртуальный)? И все будет ОК, и все будет безопасно.

См. [11].


 
pasha_golub ©   (2004-04-05 13:33) [26]

Нет, дело не в этом. Допустим уже имеется программа, написана, со своей формой? Нет, метод конечно рабочий, но к сожалению утопичный, при нем не будет гибкости. А если я захочу использовать другую форму из репозитория?



Страницы: 1 вся ветка

Текущий архив: 2004.04.25;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.026 c
4-1077900302
PVR
2004-02-27 19:45
2004.04.25
Как получить список импортируемых модулей


4-1077815228
lmatveev
2004-02-26 20:07
2004.04.25
Как узнать о недоступности диска, с которого запущена программа?


1-1080897165
Stas
2004-04-02 13:12
2004.04.25
Перемещение формы не имеющей заголовка


7-1077525696
AlexPiv
2004-02-23 11:41
2004.04.25
Как в Delphi написать программу которая отловит процесс открытия


3-1080633337
Innokenty
2004-03-30 11:55
2004.04.25
Умножение или деление. Что быстрее.