Background Text (Label)
Background Text objects in TD are static controls. They are used to display text in the GUI which do not have keyboard focus
and do not offer any mouse input like clicking. These objects are mostly placed next to datafields as label text.
By implementing some minor tricks we are able to make those objects responsive so that they will react on clicks.
In fact we can create hover effects (when moving the mouse over texts) or even move them by dragging the text.
First you will have to know that background texts in TD are created in two ways :
- Older TD versions (up to TD 6.1), the texts are painted by TD on the form canvas by default
- Older TD versions (up to TD 6.1), by setting a system variable, texts will be created as WinApi static controls on the canvas.
Set bStaticsAsWindows = TRUE
When setting bStaticsAsWindows system variable to TRUE (before a form is created), TD will create background text objects as WinApi static controls.
- TD 6.2 and higher will create background text objects as static controls on the canvas, even when the system variable is not set.
When TD paints text on the canvas (so no static control) there is no easy way to implement notifications like clicks.
The objects really need to be static controls, so for TD versions up to 6.1, the system variable must be set.
For TD 6.2 this is not needed anymore.
Even as static controls, it is not possible to be notified of any mouse actions on background texts. The controls do not process any WM messages we could
use to be informed a text has been clicked.
We have to set a specific style to the control so that the most WM messages are processed by the object: SS_NOTIFY
Now the first issue we have to overcome in TD.
Basically, to set a style to an object we should use:
Call VisWinSetStyle( hWndObject, SS_NOTIFY, TRUE ) ! Some SS messages are processed now
This means we have to pass the window handle of the background text to set it's SS_NOTIFY style.
Starting from TD 6.2, background text object names can be used to pass as window handle. But in older TD versions, the template names can not be used.
To get the window handle of the object we could do this:
Set hWndObject = VisWinGetHandle( hWndForm, "Left Click Me", TYPE_BkgdText )
Which means: TD will search for a background text "Left Click Me" on the current form.
This way we are able to get the window handle of the background text object.
Now we have the window handle, we do this:
Set hWndObject = VisWinGetHandle( hWndForm, "Left Click Me", TYPE_BkgdText ) Call VisWinSetStyle( hWndObject, SS_NOTIFY, TRUE ) ! Some SS messages are processed now
By setting the SS_NOTIFY style, the object processes WM messages like other objects. So WM_MOUSEMOVE, WM_LBUTTONUP etc etc.
Now the most difficult issue: how can we trap the WM messages on the text object to be able to react on it?
As we all know, background text objects do not have a message actions section. So even when an object processes messages, we are unable to code the message actions at the object level. See image below
Normally we would place "On WM_LBUTTONUP" in the message actions and perform our needed actions when the message is fired.
All TD versions (even TD 6.2) do not support message actions on these objects.
Fortunately, we are able to receive those messages in our code by subclassing the object.
Subclassing means we eavesdrop on the objects messages and relay or resend these messages to another object. The other object is
then used in the TD code to react on the messages received on the other object.
Subclassing is made available by the subclasser library (created by Christian Schubert). It is very easy to use this custom feature and will enable us to process messages on objects which in fact are not supported by TD to process messages.
Here an example:
Set hWndObject = VisWinGetHandle( hWndForm, "Left Click Me", TYPE_BkgdText ) Call VisWinSetStyle( hWndObject, SS_NOTIFY, TRUE ) ! Some SS messages are processed now ! Call RegSubclass( hWndObject, WM_LBUTTONUP, hWndForm, PAM_BKGD_LBUTTONUP, SUBCLASS_FLAG_AFTER )
The first two lines are to enable message processing on the background text object.
The last line actually subclasses the WM_LBUTTONUP message on the background text object and resends it to our form window.
What we do here is to eavesdrop on any WM_LBUTTONUP message received on the object and send it as PAM_BKGD_LBUTTONUP message to the form.
Now we can code "On PAM_BKGD_LBUTTONUP" at the form message actions and do our processing we need.
We can subclass multiple messages from the same object. We just have to call the RegSubclass function for each needed messages to relay.
For instance WM_MOUSEMOVE, WM_RBUTTONUP etc etc.
Nice, but not yet completely finished.
The last issue is: now we receive PAM messages (which are in fact the relayed WM messages from the text object), how do we know WHICH object has relayed the message. Normally we have the message actions section underneath the object itself, but now the form receives the messages and the message
itself does not give us any clue which object the message belongs to. In short, which text object has been clicked on?
With use of some WinApi functions, we can determine which object was clicked.
At the point of clicking, the mouse cursor is located at the exact position within the text object boundaries.
So, if we could determine which object is placed at that location, we know which object was clicked.
This is how to do that:
Call GetCursorPos( nX, nY ) Set hWndBackgroundObject = WindowFromPoint( nX, nY )
The first line gets the X and Y screen coordinate where the mouse cursor is pointing.
The second line calls a WinApi function to give us the window handle of the object which contains this coordinate.
And this will be the text object we clicked on.
To be sure the object is in fact a background text object, we could check this by
If SalGetType( hWndBackgroundObject ) = TYPE_BkgdText ! Yes, it is a background text object
Now we have everything in place to code our stuff for background texts.
The sample shows how to implement above solution. The background text objects have these features:
- Left click
- Right click (e.g. to show a popup menu)
- Hover over effect (move mouse over text to highlight them)
- Move texts over the form by dragging them with the move to a new location
As explained, there are some differences between older and newer TD versions (having to set the system variable, accessing the background text objects by template name etc).
You will find 3 sources:
- Sample for TD 1.5 - TD 4.2
- Sample for TD 5.1 - TD 6.1
- Sample for TD 6.2 and up
Here you can download the sample: