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
- Start a new project in Visual Basic. Form1 is created by default.
- 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.
- 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
- 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
- Create a new module. From the File menu, choose New Module (ALT, F, M).
Module1 is created by default.
- 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
- 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
- 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
- Add a label control (Label1) to the frmHelp form and set AutoSize=True.
- 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
- Start the program by pressing the F5 key. Then place the cursor over
one of the controls to display the help window.