Форум: "Основная";
Текущий архив: 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