Форум: "Основная";
Текущий архив: 2006.06.18;
Скачать: [xml.tar.bz2];
ВнизУправление тултипами TTreeView Найти похожие ветки
← →
Андрей Молчанов (2006-05-08 19:44) [0]Возникла проблема. В TTreeView имеется список папок, названия сокращены для того, чтобы они умещались на экране ("C:\...\My folder\Image1.gif", например). Хотелось бы, чтобы при наведении мышки, появлялась подсказка с полным путем.
Не пойму следующие вещи:
1. Как сделать, чтобы Tooltip вылезал когда нужно, а не всегда, когда не помещается заголовок элемента
2. Как управлять текстом вылезающего Tooltip-а
Я так понял, мне надо перехватывать WM_NOTIFY дерева и затем обрабатывать.ё
Спасибо.
← →
Мефисто (2006-05-08 22:12) [1]Я чего-то не догоняю. Разве TTreeView не кажет хинтне влизающей строки?
← →
Мефисто (2006-05-08 22:13) [2]>> влизающей строки?
Вернее не влезающей строки
← →
Андрей Молчанов (2006-05-09 13:34) [3]Раньше было так:
В дереве были элементы с полным путем ("C:\Information\My Data\My folder\Image1.gif"). При этом, за счет TreeView.Tooltips=True, при наведении мышки на не влезающую строку, выводилась подсказка.
Сейчас пользователи жалуются на то, что несмотря на всплывающую подсказку, все равно неудобно просматривать список длинных элементов.
Пришла в голову мысль - отображать список в сокращенном виде ("C:\...\My folder\Image1.gif"), но при наведении мыши отображать полный путь. И вот с реализацией подсказки у меня как раз проблемы - она вылезает только когда сокращенный путь не помещается, причем отображает сокращенный путь.
← →
Loginov Dmitry © (2006-05-09 13:56) [4]Андрей Молчанов (09.05.06 13:34) [3]
Я бы сделал так:
- отключил бы Tooltips
- при наведении мышкой на элемент дерева запоминал бы текст подсказки TreeView.Hint := Text и выводил бы подсказку с помощью Application.ActivateHint();
← →
Мефисто (2006-05-09 14:07) [5]Андрей Молчанов (09.05.06 13:34) [3]
А вот так яснее :)
Как вариант:
1. Самый простой: В TTreeNode.Data хранить полный путь. При клике на итем дерева выводить полный путь из TTreeNode.Data в какойнибудь контрол, например в тотже TStatusBar к примеру.
2. Писать наследника от TCustomTreeView для вывода полного пути по наведени мыши с переписыванием
procedure TCustomTreeView.WMNotify(var Message: TWMNotify);
Если не ошибся :)
Так же создать наследника от TTreeNode со своим свойством, например MyPath - где содержится полный путь. Данный путь выводить при ловле выше приведенной мессаги. Т.е. будет не Node.Text, а Node.MyPatch.
Для вставки своего модифицированного TTreeNode в свой TTreeView нужно обрабатывать обработчик события OnCreateNodeClass
← →
Мефисто (2006-05-09 14:09) [6]Loginov Dmitry © (09.05.06 13:56) [4]
Для каждой ветки полный путь гдето хранить надо :) Просто так, TreeView.Hint не катит ;)
← →
Loginov Dmitry © (2006-05-09 14:18) [7]Мефисто (09.05.06 14:09) [6]
Для каждой ветки полный путь гдето хранить надо :) Просто так, TreeView.Hint не катит ;)
Так ведь полный путь автор уже где-то хранит, так что сложностей здесь я никаких не вижу.
← →
Мефисто (2006-05-09 14:22) [8]Loginov Dmitry © (09.05.06 14:18) [7]
Ждемс автора ;)
← →
Андрей Молчанов (2006-05-09 17:53) [9]Извините, что так поздно отвечаю.
У меня уже есть следующий вариант - я отключил Tooltips, поставил ShowHint = True и ловлю NewWndProc дерева (CheckTree - это название дерева):if Message.Msg = CM_HINTSHOW then begin
Node := CheckTree.GetNodeAt(TCMHintShow(Message).HintInfo^.CursorPos.X, TCMHintShow(Message).HintInfo^.CursorPos.Y);
if Assigned(Node) and (Node.Text <> PShellItem(Node.Data)^.Path) then begin
DisplayRect := Node.DisplayRect(True);
DisplayRect.TopLeft := CheckTree.ClientToScreen(DisplayRect.TopLeft);
DisplayRect.BottomRight := CheckTree.ClientToScreen(DisplayRect.BottomRight);
TCMHintShow(Message).HintInfo^.HintStr := PShellItem(Node.Data)^.Path;
TCMHintShow(Message).HintInfo^.HintPos := DisplayRect.TopLeft;
end else
Exit;
end;
//Обработка других сообщений, не относящихся к подсказкам...
OldWndProc(Message);
Проблема в плохом поведении подсказок - например, если убрать мышь с элемента, то тултип сразу исчезнет, а подсказка - нет.
← →
Андрей Молчанов (2006-05-09 18:01) [10]Да, еще одно - похоже, менять поведение тултипов не получится - судя по исходникам TTreeView, они включаются с помощью
SetComCtlStyle(Self, TVS_NOTOOLTIPS, False);
То есть устанавливается стиль дерева. Или все равно можно влиять на их поведение?
← →
Loginov Dmitry © (2006-05-09 20:45) [11]Андрей Молчанов (09.05.06 17:53) [9]
Е-мое, как все сложно :)
Может проще будет так:procedure TForm1.TreeView1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var
Node: TTreeNode;
CPos: TPoint;
begin
Node := TreeView1.GetNodeAt(X, Y);
if Node <> nil then
begin
CPos := TreeView1.ClientToScreen(Point(5, Y));
TreeView1.Hint := "Подсказка_" + Node.Text;
Application.ActivateHint(CPos);
end
else
Application.HideHint;
end;
← →
Мефисто (2006-05-09 21:18) [12]Андрей Молчанов (09.05.06 18:01) [10]
Думаю врядли ими особо управлять можно т.к. испольуется для стилей контрола TreeView Windows (еще и зависимость от версии есть). Т.е по сути борландовский TTreeView это скорее всего просто обертка над стандартным контролом TreeView windows. Также для тоолтипа для какойто версии есть ограничение на длину выводимой строки (судя по исходникам) :(
Предложение такого плана:
1. Создаем наследника TTreeView.
2. Переписываем ему мессагу: WMNotify (var Message: TWMNotify);
3. Но вместо тоолтипа, создатим в нашем новом TTreeView еще одно хинт-окно THintWindow. Уловил мысль :) Вместо тоолтипов у нас будет всплывать окно хинт для каждого итема отдельно и без ограничения на длину выводимой строки ;)
4. Смотрим в исходник WMNotify (var Message: TWMNotify);
5. Все что касается тоолтипов вычищаем нафиг. Только не торопись с зачисткой, там надо оставить вычисления позиции окна (где ему всплыть надо).
6. Кстати еще одна заметка. Тоолтипы всплывают если строка выходит за клиентские размеры TTreeView, а у нас хинт будет всплывать в любом случае (тебе ведь нужно вывести в подсказке полный путь и при любом условии, ведь так ;) ).
Вобщем я надеюсь, общую мысль понял. Если надо подробнее, то завтра ченить рожу по этому поводу, щяс мозга уже под вечер не очень соображает.
← →
Мефисто (2006-05-09 21:56) [13]Приблизительно так:
{ TMyTree }
constructor TMyTree.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FHW := THintWindow.Create(Self);
end;
destructor TMyTree.Destroy;
begin
FHW.Free;
inherited Destroy;
end;
procedure TMyTree.WMNotify(var Message: TWMNotify);
var
Node: TTreeNode;
Pt: TPoint;
HR: TRect;
begin
FHW.Visible := False;
with Message do
if NMHdr^.code = TTN_NEEDTEXTW then
begin
FHW.Visible := True;
GetCursorPos(Pt);
Pt := ScreenToClient(Pt);
Node := GetNodeAt(Pt.X, Pt.Y);
if FHW.Showing then FHW.Hide;
if (Node = nil) or (Node.Text = "") then Exit;
FHW.Hint := Node.Text;
HR := FHW.CalcHintRect(150, FHW.Hint, Nil);
HR.Left := ClientToScreen(Pt).X;
HR.Right := HR.Left + HR.Right;
HR.Top := ClientToScreen(Pt).Y - HR.Bottom;
HR.Bottom := HR.Top + HR.Bottom;
FHW.ActivateHint(HR, FHW.Hint);
Result := 1;
end
else inherited;
end;
← →
Андрей Молчанов (2006-05-09 23:11) [14]
> Loginov Dmitry
Реализовал, только есть проблема - подсказка появляется ниже положения курсора. Я так понимаю, надо будет вычислять это расстояние для текущего курсора и затем изменять точку CPos? В любом случае, спасибо - буду думать.
> Мефисто
Ага, мысль интересная - создавать свое THintWindow я что-то не догадался. Я это попробую, пожалуй и без наследника вывернуть.
Можно попутно глупый вопрос? Возвращать Message.Result := 1 нужно каждый раз, когда не передаешь сообщение стандартному обработчику через inherited?
В общем, пища для размышлений получена, буду думать, спасибо.
← →
Мефисто (2006-05-10 16:10) [15]Андрей Молчанов (09.05.06 23:11) [14]
>> Message .Result := 1
Точно сказать не могу т.к. компонент довольнотаки громоздкий, и все механизмы его работы разбирать довольно муторно.
← →
Андрей Молчанов (2006-05-10 22:19) [16]В общем, получилось примерно следующее:
var
LastTooltipNode: TTreeNode;
procedure TfrmItemProperties.NewWndProc(var Message: TMessage);
function PointInRect(Point: TPoint; Rect: TRect): boolean;
begin
Result :=
(Point.X >= Rect.Left) and
(Point.X <= Rect.Right) and
(Point.Y >= Rect.Top) and
(Point.Y <= Rect.Bottom);
end;
var
Node: TTreeNode;
begin
case Message.Msg of
CM_HINTSHOW: begin
Node := CheckTree.GetNodeAt(TCMHintShow(Message).HintInfo^.CursorPos.X, TCMHintShow(Message).HintInfo^.CursorPos.Y);
if Assigned(Node) and PointInRect(Point(TCMHintShow(Message).HintInfo^.CursorPos.X, TCMHintShow(Message).HintInfo^.CursorPos.Y), Node.DisplayRect(True)) and (Node.Level = 0) and (Node.Text <> PShellItem(Node.Data)^.Path) then begin
TCMHintShow(Message).HintInfo^.HintStr := PShellItem(Node.Data)^.Path;
TCMHintShow(Message).HintInfo^.HintPos := CheckTree.ClientToScreen(Node.DisplayRect(True).TopLeft);
Dec(TCMHintShow(Message).HintInfo^.HintPos.X, dmMain.ScaleInteger(1));
Dec(TCMHintShow(Message).HintInfo^.HintPos.Y, dmMain.ScaleInteger(2));
TCMHintShow(Message).HintInfo^.HideTimeout := -1;
end else begin
Message.Result := 1;
Exit;
end;
end;
WM_MOUSEMOVE: begin
Node := CheckTree.GetNodeAt(TWMMouseMove(Message).XPos, TWMMouseMove(Message).YPos);
if Assigned(Node) and PointInRect(Point(TWMMouseMove(Message).XPos, TWMMouseMove(Message).YPos), Node.DisplayRect(True)) then begin
if LastTooltipNode <> Node then begin
CheckTree.ShowHint := True;
Application.ActivateHint(CheckTree.ClientToScreen(Node.DisplayRect(True).TopLeft ));
end;
LastTooltipNode := Node;
end else begin
Application.CancelHint;
CheckTree.ShowHint := False;
LastTooltipNode := nil;
end;
end;
end;
OldWndProc(Message);
end;
Дмитрий, Мефисто - огромное вам спасибо за помощь!
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2006.06.18;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.012 c