Is there a quick and easy way to highlight a label when I move the mouse over it, for example, changing the text colour from blue to red?
Thanks in advance
Printable View
Is there a quick and easy way to highlight a label when I move the mouse over it, for example, changing the text colour from blue to red?
Thanks in advance
In the Label_MouseMove event, add:
Label1.forecolor = vbRed
and on the Form_MouseMove event, add:
If label1.forecolor = vbRed then label1.forecolor = vbBlue
That will make the forecolor blue on first hit and it will stay blue always?
Try.....
Code:Dim lngFc As Long
Dim lngBc As Long
Private Sub Form_Load()
lngFc = Me.Label1.ForeColor
lngBc = Me.Label1.BackColor
End Sub
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Me.Label1.ForeColor = lngFc
Me.Label1.BackColor = lngBc
End Sub
Private Sub Label1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Me.Label1.ForeColor = vbRed
Me.Label1.BackColor = vbBlue
End Sub
Well thanks for the replies. I now have:
This works to change a single label to red on mouseover. I do however want to be able to click any one of 6 labels (a left hand menu) and have the red colour persist when clicked. Any ideas for this? I'm trying to keep the code as tight as possible and have no reliance on external files.Code:Dim lngFc As Long
Private Sub Form_Load()
lngFc = Me.Label1.ForeColor
End Sub
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Me.Label1.ForeColor = lngFc
End Sub
Private Sub Label1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Me.Label1.ForeColor = vbRed
End Sub
Iam not sure I got your question correct. Anyway this would set the forecolor of label to red upon click.
Note: The label controls are in array. To create an array of controls, place the reqd control on the form. copy and paste. you will be prompted if you want to create a control array. Click on Yes continue pasting till you reach the reqd no.
:wave:Code:Dim lngFc As Long
Private Sub Label1_Click(Index As Integer)
Me.Label1(Index).ForeColor = vbRed
End Sub
There's a click event for the label that you'll probably be using for the menu function anyway - just add the forecolor property to it.
You'll probably want to make an array out of the 6 labels though so that you'd have label1(0) to label1(5). That way you only need one sub for all of your menu functionality and you can reset the colour of all labels in the same sub:Code:Private Sub Label1_Click()
Label1.ForeColor = vbRed
End Sub
Code:Private Sub Label1_Click(Index As Integer)
Dim i As Integer
'This will reset all labels to the default colour (black in this case)
For i = 0 To 5
Label1(0).ForeColor = vbBlack
Next i
'This will set the selected label to red
Label1(Index).ForeColor = vbRed
'Then do whatever menu functions you need
End Sub
lol or pretty much what the guy who posted at the same time as me said.
Keep in mind that if you move the mouse off the label really, really fast, it often will not revert back to its original state.
Yeah, you can guarantee correct highlight/normal states if you 'capture' the mouse on the MouseMove event (see SetCapture() on MSDN for more info).Quote:
Originally Posted by Hack
Well, you can't really do that with a label, which is why I don't like using labels.Quote:
Originally Posted by reinholdmesner
Labels do not have an hWnd property which SetCapture (and a variety of other API calls) require.
OK I'm nearer with your help but still not there. I have now got 8 labels in an array. I have:
This changes the colour to red on clicking and changes the colour back to black on the unclicked labels. My problem is now to keep the label that has been clicked as vbRed but apply the vbRed to the other labels on mouseover.Code:Private Sub lblMenu_Click(Index As Integer)
'There is an array of labels for the menu
'This will reset all labels to the default colour (black in this case)
Dim i As Integer
For i = 0 To 7 'This is for 8 labels
lblMenu(i).ForeColor = vbBlack
Next i
'The code below changes the color to red on click
Me.lblMenu(Index).ForeColor = vbRed
'end label color change code
End Sub
Any ideas?
Just reading the comments posted above about not liking labels, I was using this in an effort to keep the code size down. Is there a nicer solution that gives me less issues? I am happy to go down the button route but this will involve images and doubtless a lot more work. Are labels really that bad as a solution?
This is as simple as it gets
Code:Private Sub Label1_Click(Index As Integer)
If Label1(Index).ForeColor <> vbRed Then
Label1(Index).ForeColor = vbRed
Else
Label1(Index).ForeColor = vbBlue
End If
End Sub
Labels are fine as long as you don't need to do anything with them except display a sentence or two, but they get a bit cumbersome when you attempt to manipulate them. When that kind of need arises, I turn away from labels.
I went back to your first post and read it again.
What are you attempting to accomplish (besides the surface task of make labels change colors - what is your purpose for wanting to do this)?
I have a program that is finished on the important code that actually does file operations on a PC. It currently looks pretty poor as it uses standard VB6 buttons and option boxes. The object now is to get a nice bespoke image as a background (easily done) and a menu system on the left of the form.
The menu will contain labels like Backup, Restore, Utilities, View log, Settings, Help and Exit. There will be an icon next to each one. The menu will have a background that is part of the main form image. I am thinking that the icons could be part of the image too.
File size is important for the use of the program. It needs to run with no installation in safe mode, pe mode, etc and will run on Win 95 to Vista. It currently does this, hopefully I can get a menu system to complement it!
So, you are using Labels as menu items?
sounds like you should be using command buttons instead but i think post #14 should help you with the current layout you have right now
Yes. Is that OK for the purpose of this program?
A nice example of a similar menu item can be found in the asquared malware scanner http://www.emsisoft.com/en/
Screenshot:
http://www.emsisoft.com/en/software/antimalware/
They have a red text on mouseover and when selected a feint box appears around the selected item.
Can't get your code to work VBNubcake, it doesn't change the other menu items when a label is clicked.
Is this kind of what you are looking for?
Kind of but I would prefer to have just text highlighted, not the background, I'm sure I could modify this (eventually).
Just wondering now if I should have 8 separate commands and have each one contain its own line to release the colour on the other commands and colour itself red. Would this give me greater control over the code associated with the command button too? Each command ultimately needs to make things like frames visible.
I really want to get this right for future upgrades to the code and I bow to your experience when you say that labels can be troublesome.
Just change Backcolor to Forecolor
You can also modify that to do Bold/Not Bold, UnderLine/Not Underline, Change the Actual Font/Change the Font Back again, on and on....pretty much anything you wanted to do.
So would you go down the label route for this application?
You can't do what I did using a label. That is why I used locked textboxes.
Labels do not have an hWnd property (a handle), and therefore, those API calls will not work with them.
Instead of using labels why don't you use picture boxes and then use the SetCapture and ReleaseCapture APIs as stated in post #10? Pictureboxes are easy to print captions too just use Picture1.Print "The caption you want"
Using labels and the code from post #14 will work but it gets kind of flacky at times.
And the Picture control has an hWnd property (unlike the Image control, which like the Label, does not)
If it would be of interest, I do have a label control in the UniControls package that has MouseEnter and MouseLeave events done in a proper way. It adds one more file to your project, but it should work OK from Win95 to Vista.
The control also allows you to define padding so you can align the text in the way you want.
So with the picturebox method I would use:
3 things.Code:Picture1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
If (X < 0) Or (Y < 0) Or (X > Picture1.Width) Or (Y > Picture1.Height) Then
ReleaseCapture
'the mouse is no longer over the button, reload first image
Picture1.Picture = LoadPicture("..\FirstImage.bmp")
ElseIf GetCapture() <> Picture1.hwnd Then
SetCapture Picture1.hwnd
'the mouse is over the button, so load second image
Picture1.Picture = LoadPicture("..\SecondImage.bmp")
End If
End Sub
Firstly, there is an external image requirement, something I didn't want. Can this be built-in to the program?
Secondly, any idea if this will run in ALL Windows versions and PE?
Thirdly, how can this code be efficiently changed to use 8 pictureboxes?
@Merri - I wanted to avoid the reliance of other files as this program is currently a single standalone exe.
Would this just require a single file in the same directory?
Vero: the file is only an extra source file (a usercontrol), it would not add any redistibutable file or OCX to your project. It compiles to the exe. You can optionally compile it as a OCX, but that mostly makes it behave better in the IDE (due to the nature of user controls they may sometimes stop working when you edit source code).
Wow, I looked at the UniControls and I'll be honest, I don't know where to start. I'm not at the level of knowledge required to understand how to apply this to my project. Do you think you could explain how this can be used for a simple menu or show an example?
Here is a sample. You never need to touch the UniLabel file (except if you wish to modify how it works), you just add it into the project and you're good to go.
It has actually two files, UniLabel.ctl and UniLabel.ctx. The first is the source and the latter contains the icon you see in the IDE toolbar. Just copy these to your project's path, then include the UniLabel.ctl to your project like any form, module or class module you'd be adding in.
That's it, then you can simply drag'n'drop it like any other control.
If you want to use pictures then put them in an ImageList control or use another picture box with the image loaded at design time then copy picture form that to the one on the form but I was suggesting to use Picture1.PrintQuote:
Originally Posted by Vero44
@Merri
The sample you gave works fine but not if I make the label transparent as required. Is there a fix for this?
A dirty fix, but I made it anyway. Note that this causes tons of extra Windows message traffic as the controls capture all mouse movement involved with the form, so the more labels you have, the slower things get.
The check also isn't perfect: like you can have multiple labels on top of each other and each one of them thinks you are hovering on them.
Well it works fine in the sample program you sent earlier with transparency switched on. Multiple labels on top of each other would not be a concern but your comments about performance are. Do you think using this control would currently be more of a performance hit than using button rollover images?
I don't think it is too bad, it'll require a whole lot of them to make a computer go slow - and then a very slow computer is required. Like, I don't expect you'd get it to feel as slow as the .NET Visual Studio IDEs are. Although, the part that takes care of the message handling is SelfSub code, which isn't something I'm fully knowledgeable of. SelfSub takes care of the subclassing in the control. It may or may not be optimized to handle this kind of situatation.
A small fix in Private_WndProcContainer:Now it doesn't run the MouseEnter/MouseLeave code of the container all the time if the control BackStyle is opaque. I could also change this in an even more efficient way by disabling messages to WM_MOUSEMOVE and WM_MOUSELEAVE entirely when the control isn't transparent, but I'll leave that to the moment I have the interest to continue with the UniControls project.Code:' FIND:
If uMsg = WM_MOUSEMOVE Then
' this horribility is one reason to not use events...
CopyMemory XY(0), lParam, 4&
blnTemp = (XY(0) >= m_ContainerRC.Left And XY(0) < m_ContainerRC.Right And XY(1) >= m_ContainerRC.Top And XY(1) < m_ContainerRC.Bottom)
If m_MouseOver <> blnTemp Then
' raise event if using events
If m_UseEvents And (Not blnDesignTime) Then
If blnTemp Then
RaiseEvent MouseEnter
Else
RaiseEvent MouseLeave
End If
End If
m_MouseOver = blnTemp
End If
If Not blnMouseOver Then
' initialize TrackMouseEvent structure
TME.cbSize = Len(TME)
TME.dwFlags = TME_LEAVE
TME.hWndTrack = lng_hWnd
' see which tracking API is available, if any
If m_TrackUser32 Then
TrackMouseEventUser32 TME
ElseIf m_TrackComCtl Then
TrackMouseEventComCtl TME
End If
blnMouseOver = True
End If
' see if need to raise events...
If m_UseEvents Then
' this horribility is one reason to not use events...
XY(0) = XY(0) - m_ContainerRC.Left
XY(1) = XY(1) - m_ContainerRC.Top
' see key states
If (wParam And MK_SHIFT) = MK_SHIFT Then Shift = ulbShiftMask
If (wParam And MK_CONTROL) = MK_CONTROL Then Shift = Shift Or ulbCtrlMask
' button states
If (wParam And MK_LBUTTON) = MK_LBUTTON Then Button = ulbLeftButton
If (wParam And MK_MBUTTON) = MK_MBUTTON Then Button = Button Or ulbMiddleButton
If (wParam And MK_RBUTTON) = MK_RBUTTON Then Button = Button Or ulbRightButton
' raise the event
RaiseEvent MouseMove(Button, Shift, ScaleX(XY(0), vbPixels, m_ScaleMode), ScaleY(XY(1), vbPixels, m_ScaleMode))
End If
ElseIf uMsg = WM_MOUSELEAVE Then
blnMouseOver = False
' raise event if using events
If m_MouseOver And m_UseEvents And (Not blnDesignTime) Then RaiseEvent MouseLeave
' REPLACE WITH:
If uMsg = WM_MOUSEMOVE Then
If m_BackStyle = ulbTransparent Then
' this horribility is one reason to not use events...
CopyMemory XY(0), lParam, 4&
blnTemp = (XY(0) >= m_ContainerRC.Left And XY(0) < m_ContainerRC.Right And XY(1) >= m_ContainerRC.Top And XY(1) < m_ContainerRC.Bottom)
If m_MouseOver <> blnTemp Then
' raise event if using events
If m_UseEvents And (Not blnDesignTime) Then
If blnTemp Then
RaiseEvent MouseEnter
Else
RaiseEvent MouseLeave
End If
End If
m_MouseOver = blnTemp
End If
If Not blnMouseOver Then
' initialize TrackMouseEvent structure
TME.cbSize = Len(TME)
TME.dwFlags = TME_LEAVE
TME.hWndTrack = lng_hWnd
' see which tracking API is available, if any
If m_TrackUser32 Then
TrackMouseEventUser32 TME
ElseIf m_TrackComCtl Then
TrackMouseEventComCtl TME
End If
blnMouseOver = True
End If
' see if need to raise events...
If m_UseEvents Then
' this horribility is one reason to not use events...
XY(0) = XY(0) - m_ContainerRC.Left
XY(1) = XY(1) - m_ContainerRC.Top
' see key states
If (wParam And MK_SHIFT) = MK_SHIFT Then Shift = ulbShiftMask
If (wParam And MK_CONTROL) = MK_CONTROL Then Shift = Shift Or ulbCtrlMask
' button states
If (wParam And MK_LBUTTON) = MK_LBUTTON Then Button = ulbLeftButton
If (wParam And MK_MBUTTON) = MK_MBUTTON Then Button = Button Or ulbMiddleButton
If (wParam And MK_RBUTTON) = MK_RBUTTON Then Button = Button Or ulbRightButton
' raise the event
RaiseEvent MouseMove(Button, Shift, ScaleX(XY(0), vbPixels, m_ScaleMode), ScaleY(XY(1), vbPixels, m_ScaleMode))
End If
End If
ElseIf uMsg = WM_MOUSELEAVE Then
If m_BackStyle = ulbTransparent Then
blnMouseOver = False
' raise event if using events
If m_MouseOver And m_UseEvents And (Not blnDesignTime) Then RaiseEvent MouseLeave
m_MouseOver = False
End If
Seems like alot of trouble for the question he asked.