How to Implement ToolTips Help in Visual Basic Applications

Last reviewed: June 21, 1995
Article 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 combo box
                      DisplayHelp "Edit Box of 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 reference words: 3.00 Tool Tips
KBCategory: kbui kbprg kbcode
KBSubcategory: APrgWindow


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: June 21, 1995
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.