7

After Mr. TLama have answered my last question (How to trap the TTN_LINKCLICK notification?) one point went unanswered because it was not asked :)

How to identify each link I clicked on the balloon, if there are more than one link?

I want to be able to include more than one link in the balloon and to respond to clicks differently.

Community
  • 1
  • 1
  • i found this on the net. Seems uses the windows API and seems there are a way to get the clicked link, but I'm not sure what's that language. Here is the link http://www.autohotkey.com/forum/topic40165.html. Maybe there are a way to do that with some more unusual programming... – Carlos B. Feitoza Filho Dec 14 '11 at 14:04

2 Answers2

8

The notification has no parameters, so you don't know which link was clicked. The moral: If you need more than one link, consider a more versatile interface than a tool tip, such as a toast notification or a dialog box.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
  • Wow!! Are you sure man? :S This is very bad bacause I'm using the balloons to show fill errors to users and i would like to provide links to help topics. If i need more than 1 link... This is bad. – Carlos B. Feitoza Filho Dec 14 '11 at 13:10
  • Yep, exactly as Rob said (+1). There's no way to deal with more than one link with tooltip. What is even worse, if you catch the click notification still you have to parse the link target by your own. – TLama Dec 14 '11 at 13:18
  • But @Tlama, you shouldn't really need to parse anything. Since there's only one link, and you put it there, you should already know what clicking the link should do. – Rob Kennedy Dec 14 '11 at 13:22
  • Sure, but is you use e.g. `For further info go to www.example.com` then you have to. – TLama Dec 14 '11 at 13:25
  • Well, gentleman, if the problem is parse, how to get the text encolsed between "" tags? Any way to do that? – Carlos B. Feitoza Filho Dec 14 '11 at 13:30
  • There are plenty of ways to parse text, if you really need to. I'll bet there are several answers to that question on Stack Overflow. If there aren't, please ask a new question. The comments of a tool-tip question are not the place to explain string parsing. – Rob Kennedy Dec 14 '11 at 13:44
  • @Tlama, you only have to parse that string if you don't already know what clicking on the link is supposed to do. If you created the tool tip with the intention that clicking the link would open a new browser window with example.com as the URL, then you don't need to parse anything. Just open the browser window with that URL. You only need to parse if you don't already know what you're going to get. I would hope you know what URLs you're displaying within your own program. – Rob Kennedy Dec 14 '11 at 13:48
  • @RobKennedy - Sorry, I was talking about how to GET the text of the tooltip link. To parse i know how to do. But there are no way to get the link clicked, so, there are no way to do a parse on it ;) – Carlos B. Feitoza Filho Dec 14 '11 at 14:00
  • @RobKennedy - "I would hope you know what URLs you're displaying within your own program" --> Acid comment dude ;) – Carlos B. Feitoza Filho Dec 14 '11 at 14:01
  • 3
    Why do you need to *get* to tool-tip text? Didn't you have the text when you showed the tool tip? Just use the same text you had before. If you must, send the control a `ttm_GetText` message. – Rob Kennedy Dec 14 '11 at 14:21
  • No No No, I should have said "get the text for the link being clicked" on TTN_LINKCLICK notification, but this is not possible, however, do you saw http://www.autohotkey.com/forum/topic40165.html? – Carlos B. Feitoza Filho Dec 15 '11 at 01:10
3

Finally I managed to solve this problem and YES, it is possible to get information from the link that was clicked in the ToolTip!

There really isn't any official documentation talking about it, which is a big mistake by Microsoft. I believe that anyone who works with Windows from the beginning already knew the answer, however either these people are dead or they simply have more important problems than helping people solve this type of problem which YES, it's ridiculously simple to solve. Let's explain...

The help regarding the WM_NOTIFY message says the following about its lParam parameter:

A pointer to an NMHDR structure that contains the notification code and additional information. For some notification messages, this parameter points to a larger structure that has the NMHDR structure as its first member.

The most important part of the text above is that some notification messages point to larger structures whose first member is an NMHDR. Reading this I thought "Hmm, is there any message for clicked links in general context?" So I googled for "wm_notify link click" and the first result came up with the answer: NM_CLICK

NM_CLICK is a notification message, sent via WM_NOTIFY to a control's parent window when the user clicks a link with the left mouse button. The link referred to here is a SysLink Control, for which there is extensive documentation on MSDN. It makes perfect sense that when using the TTF_PARSELINKS flag, the text inside the ToolTip that is a link is converted into a SysLink Control.

Also on the NM_CLICK documentation page, the NMLINK structure is mentioned, which contains additional information about the notification. When looking at the documentation about NMLINK I realized that its first member is an NMHDR and its second member is a LITEM, a structure that contains information about the link.

It is clear from now on that what the WM_NOTIFY message carries when it comes to a TTN_LINKCLICK, is actually an NMLINK structure, which contains the default first member (NMHDR) and the second member which contains everything we need to know about the clicked link. (LITEM).

Now, with this information, it is super easy to get information from the link that was clicked. The example below contains only Pascal (Delphi) pseudocode and is a method that handles WM_NOTIFY messages in the window that was informed in the hwnd member of TOOLINFO

procedure TFormPrincipal.HandleNotifyMessages(var AMessage: TWMNotify);
var
  Link: TNMLink;
begin
  if Assigned(AMessage.NMHdr) and (AMessage.NMHdr.code = TTN_LINKCLICK) then
  begin
    Link := PNMLink(AMessage.NMHdr)^;

    Application.MessageBox(PChar('O link clicado tem href="' + Link.item.szUrl + '" e id="' + Link.item.szID + '"'),'Sou foda!',MB_ICONINFORMATION);
  end;
end;

The final result follows:

ToolTip with TTS_BALLOON (not required)

When clicking on one of the links the message is displayed

Message showing href, id and the index

The text included in the ToolTip was as follows:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus tincidunt
accumsan ex, et congue sem aliquam eget. Mauris ut arcu condimentum, tristique 
mauris quis, consequat urna. Morbi id molestie erat. Sed egestas est elit. In a 
faucibus lorem. Nam laoreet tincidunt risus ac tincidunt. Vivamus condimentum ex 
id nulla porttitor. Isso é um link: <a href="xyz">oi oi oi</a> e isso é <a 
href="soufoda">outro link</a>. Este é mais <a href="http://www.example.com" 
id="iddestelink">um link</a> e outro <a href="x" id="idolink">link</a>
Joe DF
  • 5,438
  • 6
  • 41
  • 63
  • I'm glad that after a decade you found something that seems to work for you. I think it's definitely _not_ "clear from now on" that the TTN_LINKCLICK argument is a pointer to an NMLINK. TTN_LINKCLICK and NM_CLICK are distinct notifications. It's plausible that a tooltip control might create a syslink child control for itself. The tooltip would receive an NMLINK pointer with the NM_CLICK notification it receives, but it seems like you're merely lucky that Microsoft was lazy by having the tooltip simply forward that same NMLINK when it sends the TTN_LINKCLICK notification to its own parent. – Rob Kennedy Feb 11 '22 at 07:06
  • Well, I really don't know if it was luck or not, but either way I respectfully disagree with you. The fact that there is no documentation on how to know which link has been clicked within a ToolTip and that the memory pointed to by NMHdr actually contains an NMHDR structure followed by a LITEM structure – Carlos B. Feitoza Filho Feb 15 '22 at 15:41
  • As described in the WM_NOTIFY documentation, which says that some notifications contain more information than just NMHDR and that this structure, in these cases, is the first one within a larger structure that contains it, and contains more information after it, I really believe that this is how we should do it and that there was same MS laziness to document more clearly – Carlos B. Feitoza Filho Feb 15 '22 at 15:42