Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.04.25;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.52 MB
Время: 0.036 c
1-1081148741
zxcvb
2004-04-05 11:05
2004.04.25
Как в ячейки StringGrid сделать CheckBox?


6-1077881008
4ward
2004-02-27 14:23
2004.04.25
работа с TClient/TServerSocket


14-1080821975
Layner
2004-04-01 16:19
2004.04.25
Помогите перевести ООО на др. человека...если есть кто из юристов


4-1077406924
OverSet
2004-02-22 02:42
2004.04.25
Перемещение заголовка окна


3-1080788521
Badboy
2004-04-01 07:02
2004.04.25
Добавление





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