Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
2-1149186755
Mr tray
2006-06-01 22:32
2006.06.18
Dll не видит функции юнита


2-1149098807
newmaster
2006-05-31 22:06
2006.06.18
!!!Как получить данные из adoquery?????


2-1148971821
JustNick
2006-05-30 10:50
2006.06.18
Новый Button в TToolBar


15-1148124508
Другой
2006-05-20 15:28
2006.06.18
Может ли один программист создать Информационную Систему?


15-1148329988
DillerXX
2006-05-23 00:33
2006.06.18
Скажите, ну почему?





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