Добрый день! Помогите решить проблему! По клику на каком-либо элементе необходимо отобразить подсказку в стиле Ballon Hint. Подсказка должна отображаться пару секунд. При перемещении мыши или любом другом пользовательском вводе, подсказка должна сразу исчезнуть.
Нашел в интернете нижеследующий код, который модифицировал в части активации подсказки. Однако проблема в том, что при повторном наведении курсора на элемент, активировавший подсказку, она появляется опять! Как от этого избавиться???
Код "помощника"
unit ComponentBaloonHintU;
interface
uses
Controls, CommCtrl, Graphics;
{$SCOPEDENUMS ON}
type
TIconKind = (None = TTI_NONE, Info = TTI_INFO, Warning = TTI_WARNING, Error = TTI_ERROR, Info_Large = TTI_INFO_LARGE, Warning_Large = TTI_WARNING_LARGE, Eror_Large = TTI_ERROR_LARGE);
TComponentBaloonhint = class helper for TWinControl
public
procedure ShowBalloonTip(Icon: TIconKind; const Title, Text: string);
end;
implementation
uses
Windows;
{ TComponentBaloonhint }
procedure TComponentBaloonhint.ShowBalloonTip(Icon: TIconKind; const Title, Text: string);
var
hWndTip: THandle;
ToolInfo: TToolInfo;
BodyText: pWideChar;
begin
hWndTip := CreateWindow(TOOLTIPS_CLASS, nil, WS_POPUP or TTS_NOPREFIX or TTS_BALLOON or TTS_ALWAYSTIP, 0, 0, 0, 0, Handle, 0, HInstance, nil);
if hWndTip = 0 then
exit;
GetMem(BodyText, 2 * 256);
try
ToolInfo.cbSize := SizeOf(TToolInfo);
ToolInfo.uFlags := TTF_CENTERTIP or TTF_TRANSPARENT or TTF_SUBCLASS;
ToolInfo.hWnd := Handle;
ToolInfo.lpszText := StringToWideChar(Text, BodyText, 2 * 256);
SetWindowPos(hWndTip, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE);
ToolInfo.Rect := GetClientRect;
Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице. Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.
04-09-2018 04:26 | Комментарий к предыдущим ответам
А есть ли необходимость использовать именно окно TOOLTIPS_CLASS?
Для подобной задачи можно показывать когда надо своё окно. А то лишние сложности, чтобы создать окно, а потом подавлять его главную функциональность. Имхо, конечно.
Если я не ошибаюсь, то в хелпере можно объявлять поля, которые, естественно, доступны только в методах хелпера.
Но, кажется, класс может иметь лишь один хелпер. (?). А вдруг где-то уже используется хелпер, или будет добавлен?
Поправьте меня, если я не прав.
И еще надо проверить TTM_TRACKACTIVATE - по-моему именно оно включает-отключает подсказку. Так что можно так:
SendMessage(hWndTip, TTM_ACTIVATE, integer(false), integer(@ToolInfo));
Я пишу в билдере, но попробую сделать набросок
procedure TWinControl.WMNotify(var Message: TWMNotify);
var
ToolInfo: TToolInfo;
begin
if Message.NMHdr.code = TTN_POP then begin
ToolInfo.cbSize := SizeOf(TToolInfo);
ToolInfo.uFlags := TTF_IDISHWND;
ToolInfo.hWnd := Handle;
ToolInfo.uId := hWndTip;
SendMessage(hWndTip, TTM_DELTOOL, 0, integer(@ToolInfo));
end
else inherited;
end;
От этого можно попробовать оттолкнуться. Вместо хэндла подсказки можно использовать целочисленный идентификатор, который также следует задать в TTM_ADDTOOL, и тогда нужно убрать флаг TTF_IDISHWND
>>>Как это реализовать?
Так-то надо обрабатывать WM_NOTIFY, но у Вас хелпер, а не полноценный класс. Попробуйте завести метод-обработчик события:
procedure WMNotify(var Message: TMessage); message WM_NOTIFY;
не забывайте внутри вызвать inherited метод. Внутри в lParam ждем заголовок с информацией и кодом события (TTN_POP), которое, если верить msdn, оповещает о сокрытии подсказки. А потом уж снова вызываем SendMessage(hWndTip, TTM_ADDTOOL, 1, integer(@ToolInfo)), только в хэндл пишем nil.
Сам такое не пробовал, предлагаю в качестве эксперимента
Как это реализовать? Создать компонент, который будет реализовать процедуру вызова хинта и создать в нем обработчик данного события? Он будет получать это событие?
1. По задаче, ситуация такая: Есть форма с рядом надписей типа StaticText с возможностью фокусирования. Из них (на выбор) мне нужно копировать текст в буфер обмена. Я сделал конечно всплывающее меню, с пунктом копирования, но когда часто приходится пользоваться, через меню неудобно. Я решил сделать через клик. Но нужна визуальная реакция контрола, что команда выполнена или ответ о недоступности операции. Через диалоговое окно слишком неудобно (закрывать его - отдельно мышкой по экрану рыскать). Т.е. нужно сделать визуальное оповещение, не требующее специальной реакции пользователя. Хинты в этом плане идеально подходят.
2. TBallonHint не подходит, поскольку топорно отображает иконки и многострочный текст, а также не исчезает при перемещении мышки, только по таймеру (или по клику, вызывающему его отображение на другой надписи).
03-09-2018 06:06 | Вопрос к автору: запрос дополнительной информации
А почему бы не использовать TBalloonHint? Его можно показать когда надо и где надо. Или код подсмотреть. Там, вроде, все просто и можно в Helper использовать.
А по вопросу предполагаю, что TOOLTIP-окно привязывается к контролу и ведет себя стандартным образом.
Т.е. активируется при наведении. И тут вопрос: действительно ли необходимо показывать хинт именно в Click? Не могу представить такой задачи.
Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter. Функция может не работать в некоторых версиях броузеров.