HOWTO: Implement ToolTips Help in Visual Basic Applications

ID: Q111495

The information in this article applies to:

- Standard and Professional Editions of Microsoft Visual Basic for

  Windows, versions 2.0 and 3.0

SUMMARY

This article shows by example how to implement the toolbar "ToolTips" help in a Visual Basic application in a manner similar to the way "ToolTips" help system is implemented in Microsoft Word version 6.0 for Windows and Microsoft Excel version 5.0.

MORE INFORMATION

The following example implements a "ToolTips" help system by taking advantage of the GetCursorPos() and WindowFromPoint() Windows API functions. The GetCursorPos() function returns the current location of the mouse cursor and the WindowFromPoint() function returns the hWnd (window handle) of the control or form at a particular location on the screen.

Important Note: Modifications Required If Using Image Controls

IMPORTANT NOTE: Most toolbars in Visual Basic are made by using a container control (picture box) with individual image controls acting as buttons placed inside the container. The Image control, however, is a "light" control; it does not have an hWnd property. Because of this, the WindowFromPoint() Windows API function will not be able to detect which image control the cursor is over. It will give the hWnd of the image control's parent, in this case the container.

Therefore, if you are using image controls as your toolbar buttons (or some other control that doesn't have an hWnd property), you need to modify this program. Have it detect when the mouse cursor is over the parent container. Then calculate which image control the cursor is over by comparing the x and y coordinate returned by GetCursorPos, which is relative to the screen, to the coordinates of the image controls, which are relative to the parent container.

How to Use the GetCursorPos() and WindowFromPoint() Windows API functions

By using a timer, you can call the GetCursorPos() and WindowFromPoint() API functions to find out if the mouse cursor is located over a control for which you want to display a help window.

The help window is displayed by using an auto sizing label control on a separate form. By locating the form relative to the cursor, changing the label's caption, and resizing the form, you can display the ToolTips help. Then you can use the ShowWindow() Windows API function to display the help form without giving it the focus. By using ShowWindow(), you can keep the main form?s title bar from flashing when focus changes. In contrast, the Show method would cause the title bar to flash.

Step-by-Step Example

1. Start a new project in Visual Basic. Form1 is created by default.

2. Place the following controls on Form1:

   Timer (Timer1)
   Text Box (Text1)
   List Box (List1)
   Combo Box (Combo1)    'See NOTE below
   Check Box (Check1)
   Picture Box (Picture1)
   Option Button (Option1)
   Command Button (Command1)
   Vertical Scroll Bar (vScroll1)
   Horizontal Scroll Bar (hScroll1)

   NOTE: The combo box is a special case. The edit box portion of the combo
   box is a child window of the combo box, so it has a different window
   handle. Therefore, you must make call the GetWindow() Windows API
   function, with the GW_CHILD parameter, in order to get the hWnd of this
   edit box.

3. Add the following code to the Form_Load event of Form1:

      Sub Form_Load ()
   
         ' Set timer for 1 second, and enable it.
         Timer1.Interval = 1000
         Timer1.Enabled = True
   
      End Sub

4. Add the following code to the timer event of Timer1:

      Sub Timer1_Timer ()
         Dim curhWnd As Integer      'Current hWnd
         Dim p As POINTAPI
         Static LasthWnd As Integer  'Hold previous hWnd
   
         ' Make sure the program has the input focus:
         If GetActiveWindow() = Form1.hWnd Then
            ' Initialize point structure:
            Call GetCursorPos(p)
            ' Which window is the mouse cursor over?
            curhWnd = WindowFromPoint(p.y, p.x)
   
            ' Same as last window? If so, don't need to redraw:
            If curhWnd <> LasthWnd Then
               ' Store the current hWnd:
               LasthWnd = curhWnd
               ' Decrease timer interval to 5 ms (could choose 1 ms):
               Timer1.Interval = 5
               ' Which control is the cursor over?
               Select Case curhWnd
                  Case Command1.hWnd
                     DisplayHelp "Command Button"
                  Case Text1.hWnd
                     DisplayHelp "Text Box"
                  Case List1.hWnd
                     DisplayHelp "List Box"
                  Case Picture1.hWnd
                     DisplayHelp "Picture Box"
                  Case Check1.hWnd
                     DisplayHelp "Check Box"
                  Case Option1.hWnd
                     DisplayHelp "Option Box"
                  Case Combo1.hWnd
                     DisplayHelp "Drop Down Combo Box"
                  Case GetWindow(Combo1.hWnd, GW_CHILD)  'Edit box of
                     DisplayHelp "Edit Box of Combo Box" 'combo box
                  Case hScroll1.hWnd
                     DisplayHelp "hScroll Bar"
                  Case vScroll1.hWnd
                     DisplayHelp "vScroll Bar"
                  Case frmHelp.hWnd
                     ' If it moves onto the help window, hide it:
                     frmHelp.Hide
                  Case Else
                     ' Cursor is over the form or something else, so
                     ' change interval back to 1 sec delay:
                     DisplayHelp ""
                     Timer1.Interval = 1000
               End Select
            End If
         End If
      End Sub

5. Create a new module. From the File menu, choose New Module (ALT, F, M).
   Module1 is created by default.

6. Add the following declarations to the General Declarations section of
   Module1:

    Global Const SW_SHOWNOACTIVATE = 4
    Global Const GW_CHILD = 5         ' Needed for edit portion of
                                      ' combo box
    Type POINTAPI       ' Stores location of cursor
       x As Integer
       y As Integer
    End Type

    Declare Sub GetCursorPos Lib "User" (lpPoint As POINTAPI)
    Declare Function GetActiveWindow Lib "User" () As Integer
    ' Enter each of the following Declare statements on one, single line:
    Declare Function WindowFromPoint Lib "user" (ByVal lpPointY As Integer,
       ByVal lpPointX As Integer) As Integer
    Declare Function GetWindow Lib "User" (ByVal hWnd As Integer,
       ByVal wCmd As Integer) As Integer
    Declare Function ShowWindow Lib "User" (ByVal hWnd As Integer,
       ByVal nCmdShow As Integer) As Integer

7. Add the following Sub procedure to Module1:

   Sub DisplayHelp (Help$)
      Dim lpPoint As POINTAPI ' Cursor Point variable
      Dim ret As Integer      ' Return value of ShowWindow()
                              ' API function
      Rem Display Help String
      Rem
      Rem This Function displays the Help$ if Help$ <> "".
      Rem if Help$ = "" then the Help String is removed.
      Rem
      Rem FUNCTION REQUIREMENTS:
      Rem     GetCursorPos()    Windows API function
      Rem     frmHelp           Name of the Help form
      Rem

      If Len(Help$) <> 0 Then  ' Double check help$

         ' Make sure help form is invisible:
         frmHelp.Hide

         ' Change caption of label:
         frmHelp.Label1.Caption = Help$

         ' Get the cursor position so you can calculate where
         ' to place the help form:
         Call GetCursorPos(lpPoint)

         ' Offset the form from the cursor by 18 and 2 pixels (values
         ' chosen to simulate the look of Microsoft Word version 6.0)
         frmHelp.Top = (lpPoint.y + 18) * Screen.TwipsPerPixelY
         frmHelp.Left = (lpPoint.x - 2) * Screen.TwipsPerPixelY

         ' Adjust width of form to label + 4  because 2 are needed
         ' for each pixel of the border and 2 are needed to center
         ' the label (the label is inset by 1 pixel on the form).
         ' Also, adjust height of form to height of label + 2
         ' because 2 ar needed for each pixel of the border:
         frmHelp.Width = frmHelp.Label1.Width + (4 * Screen.TwipsPerPixelX)
         frmHelp.Height = frmHelp.Label1.Height + 2 * Screen.TwipsPerPixelY

         ' Make sure form is on top:
         frmHelp.ZOrder

         ' Show form without the focus:
         ret = ShowWindow(frmHelp.hWnd, SW_SHOWNOACTIVATE)
      Else
         ' Hide the form:
         frmHelp.Hide
      End If
   End Sub

8. Create another form by choosing New Form from the File menu (ALT, F, F).
   Form2 is created by default. Change the following properties of Form2:

   Name = frmHelp
   BorderStyle = 1 - Fixed Single
   ControlBox = False
   MinButton = False
   MaxButton = False

9. Add a label control (Label1) to the frmHelp form and set AutoSize=True.

10. Add the following code the to Form_Load event of the frmHelp form:

      Sub Form_Load ()
   
         ' Get rid of the forms Caption so title bar does not display:
         Me.Caption = ""
   
         ' Give the form and label a light yellow background:
         Me.BackColor = &H80FFFF
         Label1.BackColor = &H80FFFF
   
         ' Inset label by 1 pixel:
         Label1.Left = 1 * Screen.TwipsPerPixelX
         Label1.Top = 0
   
      End Sub

11. Start the program by pressing the F5 key. Then place the cursor over
    one of the controls to display the help window.

Additional query words: Tool Tips Keywords : kbui kbVBp kbVBp300 kbvbp200

Last Reviewed: June 1, 1999