Doug Steele tries to address commonly asked questions from Access developers. This month is looking at how to simulate XP Cue Banners.
See the other half of this Access Answers article here more Dragging Around.
Internet controls such as search boxes have something called “cue prompting” that can help indicate what the user should be entering. Is there some way I can still do something like this in Access?
For those of you who aren’t familiar with Cue Banners, the following screenshots should demonstrate. As you can see in Figure 2, there’s a faint cue text message in each control that’s intended to tell the user what should go into that field.
Figure 2 Figure 3
Once the user moves to a specific field, the cue text disappears to allow the user to key in the appropriate information (see Figure 3). After text has been entered into a control, it looks normal (see Figure 4).
Not everyone (myself included) runs XP, but that doesn’t mean that we can’t use this neat feature. XP uses the EM_SETCUEBANNER method of the SendMessage API, so that the control itself retains the ability to redisplay the cue text prompt as required. What I’m going to demonstrate is a VBA-only solution that uses the control’s Tag property to store the cue text for the control. I’m going to use each control’s HelpContextID property to hold the Boolean flag that will allow me to determine whether the cue text should be displayed or not. This will work for most applications, as long as control-sensitive context Help hasn’t been implemented.
If your application uses the Tag property of the control and/or the HelpContextID for other purposes, you’ll need to implement a different mechanism to store the prompt string and flags. (One way is to use Boolean and String arrays, while another would be to store the information in a table, with the Form and Control names as the key.)
Note that this technique is only applicable to unbound text boxes, rich text boxes, and combo boxes in Access. Due to how it’s implemented, it will only work with combo boxes that have their LimitToList property set to False. I’m going to use the GotFocus, LostFocus, and Change events associated with the controls to implement this technique (as well as the form’s Load event to initialize things).
To enable a control to mimic the Cue Banners, you need to link the cue text that should be displayed to the control and display it, in a shadow color:
Public Sub SetupCueControl(ctl As Control, _ sCue As String) On Error GoTo Err_SetupCueControl With ctl .SetFocus .Tag = sCue .Text = sCue .ForeColor = vbButtonShadow .HelpContextId = True End With End Sub
As you can see, I’m assigning the cue text to the control’s edit box, as well as to its Tag property. I’m also setting the text’s color to whatever color vbButtonShadow represents (thus respecting the user’s settings, rather than hard-coding a value). Finally, I’m setting the control’s HelpContextID to True, to indicate that it doesn’t have a “real” value. (I’ll change it to False once a value gets entered.)
Whenever an enabled control gets focus, it’s necessary to determine whether the current content of the control is the cue text or “real” text:
Public Sub CheckCuePromptOnFocus(ctl As Control) With ctl If .HelpContextId = True Then .Text = "" Else .SelStart = 0 .SelLength = Len(.Text) .HelpContextId = False End If .ForeColor = vbWindowText End With End Sub
What this code does is check the value of the control’s HelpContextID property. As explained earlier, the HelpContextID will be True if the control is currently showing the cue text, and False otherwise. If the control is showing the cue text, the code blanks it out; otherwise, it highlights the entire string. In either case, it changes the color of the text to whatever vbWindowText is.
If the control raises a Change event, check whether the text is now different from the cue text. If it is, set the HelpContextID property to False:
Public Sub CheckCuePromptChange(ctl As Control) ctl.HelpContextId = (Trim$(ctl.Text) = ctl.Tag) End Sub
Finally, when an enabled control loses focus, I check whether or not a value has been entered into the control. If not, I reset the control’s value to whatever was stored in the control’s Tag property (and change the ForeColor property back). Otherwise, I leave the control showing what was entered into it:
Public Sub CheckCuePromptBlur(ctl As Control) On Error GoTo Err_CheckCuePromptBlur With ctl If Len(Trim$(.Text)) = 0 Then .Text = .Tag .ForeColor = vbButtonShadow .HelpContextId = True End If End With End Sub
Once you have those four procedures defined, put them in a module so that you can use them from any form. Here are examples of how you invoke those procedures for the control. In the form’s Load event, call SetupCueControl:
Private Sub Form_Load() SetupCueControl Me.txtName, "Enter your name" End Sub Then, add code to the control's Change, GotFocus, and LostFocus events: Private Sub txtName_Change() CheckCuePromptChange Me.txtName End Sub Private Sub txtName_GotFocus() CheckCuePromptOnFocus Me.txtName End Sub Private Sub txtName_LostFocus() CheckCuePromptBlur Me.txtName End Sub
For this technique to work properly, you need to ensure that there’s some control on the form that doesn’t use Cue Banners to which you can set focus when the form first opens (remember, if focus is on a control set up to display Cue Banners, the cue text message disappears).
As well, recognize that you’ll need to change how you detect whether a particular control has received a value. No longer can you simply check whether Len(Me.txtName) = 0 to determine whether a name has been keyed in. Instead, you’ll need to check Me.HelpContextID = True, or Trim$(Me.txtName) = Me.txtName.Tag.
(Thanks to Randy Birch, Microsoft Visual Basic MVP, for the initial code upon which this tip is based!)
Note from Garry Robinson :
In the 2007 Contacts template, Microsoft put @;[Black]”Search Contacts” in the Format property of the text box. This has the same effect as the above.