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.
I'm actually flattered that people have taken the time to post solutions, although it's true, I did expect there to be an easy solution for a simple side menu, something used in many, many programs.
Thanks again for all your help so far guys.
Sorry for replying to a old topic but you could do it like this.
Create a label array called toolLink
Change the colour to blue
then add this code to the code window
vb Code:
Private Sub toolLink_DragOver(Index As Integer, Source As Control, X As Single, Y As Single, State As Integer) On Error Resume Next If State = vbLeave Then With toolLink(Index) .Drag vbEndDrag .ForeColor = vbBlue End With End If End Sub Private Sub toolLink_MouseMove(Index As Integer, Button As Integer, Shift As Integer, X As Single, Y As Single) On Error Resume Next With toolLink(Index) .ForeColor = vbRed .Drag vbBeginDrag End With End Sub
Iv attached a copy of it.
P.S not my code found it in a project thing i downloaded, don't know who the person is but his site is www.crapsoft.org and just got rid of the rubbish.
Thanks for that, I'll take a look. Anyone see any problems with this code, it looks very small? Would it suffer the same problems that the other label-based code does as Hack mentioned in an earlier post?
It was a bit bigger and had some other things, but it didn't need them so i deleted it. But i can send you the origonal code if you want.
Does the highlight box have to stay on the form if we use this method? I really don't like that effect.
Also how can the clicked label stay red?
No you can get rid of it. Sorry forgot it was there.
Try this attatched.
Sorry for the late reply Banjo. Looks pretty good and very small. So if I use this method, I would like to have the selected link turn red on hover (like now) but stay red when selected. Is there a simple way to achieve this?
Im not sure how you could do that. Maybe on a click event or something haveand on the other labels something like thisCode:Label1.BackColor = vbRed
There is probally a better way though.Code:If Label1.BackColor = vbRed then
Label1.BackColor = vbBlue
End If
I know it's a bit late, but if you're still intrested in something like the antimalware program uses, have a look at the attachment.Quote:
Originally Posted by Vero44
The code still needs some finetuning, but I think everything works.
Thanks Jottum. It's certainly an attractive menu label but there's a lot of code in the control I don't understand. I added a second button that didn't change on mouseover or click so I imagine the code would need changing for every button to work.
I'm really trying to simplify things for my basic level of programming so not sure I can modify this. Thanks for sharing the code though. Are you (or anyone) able to mod it so I can see it work on, say, 8 labels because I might use it then?
What is involved when you have a bespoke control like this MenuLabel.ctl? Can I still compile it and get it to work in safe mode, PE mode and in Win95 to Vista or does it have any extra dependencies?
Hi,Quote:
Originally Posted by Vero44
You're welcome. The version I posted, still needed quite some work, but I wanted you to have a choise before to much effort had gone in another approach.
The version now attached is much better and you should be able to configure one Menulabe the way you want and then copy and paste exact copies of it.
Whether or not you can use it, is something only you can judge and either way is Ok with me. :)
I think - note THINK :) - it has nothing that 95 would choke on, but running attached sample on a 95 machine will give you a certain answer.
The attached version has nicer default colors, a pushed state when "boxed", a text hover color, selected button will be remembered when you "tab" to the next, focus rect is better aligned, text is better aligned, LabelImage loading is better now and more little things that just were'nt ready. I also added a transparent container, just for the heck of it. :)
There's probably more I've missed, if anyone wants to use it, just let me know what isn't right and I'll fix it.
If you are going to test it on 95, let me know if it works or not. It does run on XP and Vista, I'm developing on a Vista box and just test on XP to be sure.
Take care,
Very nice and an excellent demo Jottum.
So a few questions:
1. How do I control the size of the image or do I need to resize the image to suit?
2. How can I get the label image to be 'hoverable' as the label text is, eg change the label colour? Many users would click the icon not the text.
3. How do I add this control in to my project, simply with Project > Add User Control?
Thank you, the basis of this MenuLabel is the vbKeys link control.Quote:
Originally Posted by Vero44
Right now you would have to change the image control's size that rests on the usercontrol, but I'm thinking about adding a routine that will draw any (compatible) image you load directly onto the UC's DC. The size won't be problem anymore that way.Quote:
Originally Posted by Vero44
The easiest way would be to add more then one label image, disabled, hover and normal for instance. It is possible to do this all by code, but that would be a lot of work and results in a much larger code. I have no intentions going that way. :)Quote:
Originally Posted by Vero44
Yes, you should only have to load the MenuLabel control, unless you want to use the transparent container I've added for this sample project, you would have to add 2 files in that case.Quote:
Originally Posted by Vero44
With respect to question 2, I didn't want the icon to change, just to have the label's text colour change when hovering over the icon or clicking it.
This is possibly a bug as it works some times and not others.
I have been using the 4th label down with an icon of my own. For testing, try moving the mouse on and off the icon, sometimes it doesn't highlight. Is this the label bug Hack referred to earlier in this post?
Well, you're getting more then you're bargained for. :)Quote:
Originally Posted by Vero44
I can't reproduce that behaviour, so long as you haven't clicked a MenuLabel, the entire control responds to a mouse move and updates the hover colors.Quote:
Originally Posted by Vero44
I've got almost RSI from trying ;), but it always works as expected, which is odd while you have this problem.Quote:
Originally Posted by Vero44
Anyways, I've made some changes, the Image control is gone, the drawing is done directly onto the DC now. I've added two more images, one for the disabled state and on when you hover over the label.
They're all optional, the attached demo project uses them all. The size no longer matters, I'm using 48 x 48 images now.
There still can be issues, tho I haven't found anymore then I already did.
Let me know what you think and if the hover bug is still there.
Take care,
PSQuote:
Originally Posted by Vero44
It must have been the Image control blocking the mouse move from the UC. That's why I couldn't reproduce it, I had it already removed when I read your post.
Now that's exactly what I'm after Jottum. Will try to incorporate this into my project and test as much as possible on different O/S. Thanks for your help so far.
You're welcome, perhaps it can save you a lot of work if you compile the demo project and test that on as many OS's you can. While you do that, I can "polish" the UC, add all the missing Procedure Attributes and add proper credits to the parts of the code I didn't wrote.Quote:
Originally Posted by Vero44
I'll get on with that anyway and if no one reports any bugs, reply here again with the final version when I'm finished.
That would be cool, and post your final project in our CodeBank (source code only - no compiled code please :) )Quote:
Originally Posted by Jottum
Will do and won't do. ;)Quote:
Originally Posted by Hack