By: Steve Waring
Home Pages: Journal Dolphinharbor
Created: 20021101
Last Update: 20021101
Most of the support code for displaying tooltips for controls other than just the toolbar, is present in the base image. It just needs a bit of tweaking to make it happen.
I wanted to use a tooltip for a normal PushButton. A quick browse through the View classes looked encouraging; methods such as ControlView>>ttnNeedText: and the Presenter>>onTipTextRequired: pattern, suggested it could be done, however the base UI only seemed to display Tooltips for Toolbar buttons, and there is no ControlView subclass for the ToolTip control.
The key is on this MSDN page ... A ToolTip control can support any number of tools.
The lock is that a toolbar contains a ToolTip control, and it is this control that can be reused.
With this information, it was time to start prodding and poking, using a workspace and the Flipper inspector. I created a quick Shell subclass, and using the ViewComposer, created a Shell with a Toolbar and a PushButton. To allow easier access from a workspace, I named the Toolbar "toolbar" and the PushButton "button".
Firstly, setup a few temporary variables in a workspace. The important message is the base method Toolbar>>tbGetToolTips.
The approach we need to take is described in the "Supporting Tools" section on this MSDN page. The TOOLINFO structure is already wrapped in the base image, so we dont have much work to do. To make things neater, you can add the constants in the CommCtrlConstants PoolDictionary to your workspace by using the Workspace/Pools menu command.
The above TOOLINFO settings look like the simplest thing that will work. The base image methods look like they expect the "uId" to be a window handle, and the TTF_SUBCLASS flag means that we can get Windows to do the work of TTM_RELAYEVENT.
Continuing on with the easiest way; we can set the tooltip text into the TOOLINFO instead of dealing with callbacks. If you look at the comment in the TOOLINFO>>text: helper method, you can see that it is important that we keep a reference to this string.
It's now time to join the dots, and tell Windows about our button. We can't use the typical View>>sendMessage: helper methods because we don't have a View instance for the ToolTip control, all we have is an external handle that the ToolBar gave us. We can use the UserLibrary DLL function directly.
Keep your fingers crossed, hold your breath, pray to the windows gods, or whatever it is you do before entering the unknown of the the Windows API and:
Hopefully nothing much happened, but if you move your mouse over to the button, sooner or later this should appear:
Yippee! ... too easy :)
To test this technique on various Windows versions, I moved the workspace code into my Shell presenter's onViewOpened method, created an instance variable to hold the tooltip string, and deployed it as a ToGo test application (390k). This is released as TestWare; if you have any problems running this in your environment please let me know about it. It has been run successfully on WinXP, Win2k, and even works on my Win95 torture test machine.
Functionally, the disadvantage of the above approach is that the tooltip text is not easily changed. It would be nice to take advantage of the base ControlView>>ttnNeedText: method, which will use the handle we set into the TOOLINFO structure, to locate our presenter, and ask it for the text using #onTipTextRequired:.
From reading the TOOLINFO MSDN page it looks like we need to set lpszText to LPSTR_TEXTCALLBACK. A quick "Containing text ..." search through the image turns up a couple of hits ... what do you know, Objects-Arts already has a helper method in TOOLINFO that does this for us.
With the trusty debugger always ready to go, I use a policy of leaping before I look. I re-evaluated the workspace code, this time sending the toolInfo the #textCallback message. mmm, nothing happens ... where is that debugger when you need it? I put Transcript trace code in the #ttnNeedText: methods, but nothing was turning up.
An hour or two of teeth gnashing, Transcript tracing, MSDN searching and Messaging spying turned up the answer (in an Object-Art's comment of course!). I copied Toolbar>>wmNotify:wParam:lParam to PushButton, and Yippee! ... I have my debugger up asking for a PushButton>>toolTipText method. I implemented this as "^self commandDescription description" and Yippee again, it worked.
The above screenshot is from a second ToGo test application (473k). This is released as TestWare; if you have any problems running this in your environment please let me know about it. It has been run successfully on WinXP, Win2k, and Win95 machines.
The following loose methods were added to PushButton, and were mostly cut and pastes:
This routes the windows notification to the pushButton (instead of looking for a non-Dolphin ToolTip control).
The next two methods enable similar behavior to a ToolBar in that the Presenter that implements the PushButton's command, gets the opportunity to set the tooltip text. In the Test ToGo, this is demonstrated by including a count of how many times #onTipTextRequired: is sent.
The following is the onViewOpened method of the test Shell:
Copyright Steve Waring 2002.