|
This sample provides a fully-functional usercontrol, that offers a number of unique capabilities. The premise was to offer something that could be used similar to a hyperlinked phrase or graphic on a webpage. The text or graphic should be capable of rollover processing, such that as the mouse moves enters its hotspot the link alters its appearance, and when the mouse exits the link reverts to its original state. The problem was, Classic VB offered no MouseLeave or MouseExit property we could use to restore state.
Quite a number of solutions have been proposed over the years. One very common solution is to monitor MouseMove, and watch for what's under the cursor until it's not the control of interest. That method is subject to error, as the event doesn't always fire when the mouse is moved very quickly or focus is switched to another application using Alt-Tab. If you want to take it to the next level, and use a few APIs, you can call SetCapture, then WindowFromPoint each time the MouseMove fires. Of course, this is pretty useless if the control of interest is windowless like a Label. Windows 98 introduced the TrackMouseEvent API function, which has the same limitation of only working with windowed controls.
The solution presented here avoids the window requirement, so that it supports windowless conrols (like Image and Label) as well. And, no APIs are even required, as VB's own drag-and-drop offers us the ability to create our own MouseLeave event. The trick is to call a control's Drag method, telling it to vbBeginDrag, from within its MouseMove event. At that point, the DragIcon kicks in, allowing you to use the classic pointy-finger hand if you'd like. Complete the effect by watching for the State parameter equal to vbLeave in the control's DragOver event, and telling the Drag method to vbEndDrag in response. A more complete description is offered in the August 1999 VBPJ article reference below, but here's the gist of it:
Private Sub Form_Load() ' Important: This whole technique gets ugly ' if a custom DragIcon isn't assigned! With Label1 .Caption = "http://vb.mvps.org/samples" .DragIcon = Image1.Picture '<-- !!! .Tag = Label1.Caption End With End Sub Private Sub Label1_DragOver( _ Source As Control, X As Single, Y As Single, State As Integer) ' If the control is in dragmode, you can detect ' MouseLeave easily by observing the State parameter. If State = vbLeave Then ' Thanks to Mike Bolser for this observation! With Label1 .Drag vbEndDrag .Font.Underline = False .ForeColor = vbBlack End With End If End Sub Private Sub Label1_MouseMove( _ Button As Integer, Shift As Integer, X As Single, Y As Single) ' Entering dragmode on the first MouseMove allows ' easy detection of MouseLeave. With Label1 .ForeColor = vbBlue .Font.Underline = True .Drag vbBeginDrag End With End SubWhen the user clicks while dragging, DragDrop fires. It's probably a good idea to test the Source just to be sure something really whacky isn't going on. Opening a web document is encapsulated within the HyperJump function, and is a simple matter of calling ShellExecute passing the URL with the "open" verb. Reset the Label control's inactive properties, as desired.
Private Sub Label1_DragDrop( _ Source As Control, X As Single, Y As Single) ' If the mouse is over the label, the control ' must be in drag mode. In this case, the ' DragDrop event occurs when the mouse is ' clicked by the user. Fire up the URL! If Source Is Label1 Then With Label1 Call HyperJump(.Tag) .Font.Underline = False .ForeColor = vbBlack End With End If End SubOf course, these techniques add up to a fair bit of "pure VB" code to include for what really ought to be very simple code! So I rolled the entire thing up into an OCX, and compiled that with VB6. Supporting both textual and graphical hyperlinks, this usercontrol is windowless (in hosts that support that) and features a transparent background. Maintaining a transparent background and tracking hits on the overlying text proved to be quite a challenge, as this source demonstrates. I hope you find it useful.
This sample, or the one from which it originally derived, was published (or at least peripherally mentioned) in the following article(s):
- Use a Label Control as a Hyperlink, Ask the VB Pro, VBPJ, August 1999
This sample uses the following API calls:
Module Library Function FAbout.frm shell32
user32ShellExecute
GetWindowRect
SetCursorPosHyperLabel.ctl shell32
user32ShellExecute
GetDesktopWindowMRectMask.bas gdi32
kernel32
olepro32
user32BitBlt
CreateBitmap
CreateCompatibleDC
DeleteDC
DeleteObject
GetObject
GetStockObject
SelectObject
RtlMoveMemory
OleCreatePictureIndirect
FillRect
GetDC
GetDesktopWindow
ReleaseDCDon't see what you're looking for? Here's a complete API cross-reference.
Please, enjoy and learn from this sample. Include its code within your own projects, if you wish. But, in order to insure only the most recent code is available to all, I ask that you don't share the sample by any form of mass distribution. Download HyperLabel.zip, 68Kb, Last Updated: Friday, April 16, 1999
The following resources may also be of interest: