Unselect listview item when hovering in listview background - vb.net

I am needing some help with a listview control that uses large icon view. I have icons in my listview control that when I hover over them, it displays a custom tooltip (not the in-built listview tooltip).
My problem is that when I hover into the background of the listview, it doesn't de-select the selected item. I would also like to cut the tooltip short (if possible) so if the tooltip is meant to be visible for 5 seconds and someone hovers into the background of the listview before this time, then the item deselects and the tooltip disappears.
My code currently looks like this:
Private Sub lsvStores_ItemMouseHover(sender As Object, e As ListViewItemMouseHoverEventArgs) Handles lsvStores.ItemMouseHover
Dim storeID As String = e.Item.Name
ShowStoreDetailsTooltip(storeID, sender, e.Item.Position.X, e.Item.Position.Y - 80)
End Sub
Private Sub lsvStores_MouseHover(sender As Object, e As EventArgs) Handles lsvStores.MouseHover
lsvStores.SelectedItems.Clear()
End Sub
Private Sub ShowStoreDetailsTooltip(ByVal Code As String, ByVal Obj As Control, ByVal XPos As
ttpStoreDetails.ToolTipTitle = StoreName
ttpStoreDetails.IsBalloon = True
ttpStoreDetails.Show(String.Empty, Obj, 0)
ttpStoreDetails.Show(tmpString, Obj, XPos, YPos, 5000)
End Sub
Any help appreciated thanks.

Using some code from this answer, we can get the item currently under the mouse cursor using ListView.GetItemAt(), then see if it's Nothing. If it is, then you'll do whatever you need to to make your Tooltip disappear.
Private _item As ListViewItem = Nothing
Private Sub lsvStores_MouseMove(sender As Object, e As MouseEventArgs) Handles lsvStores.MouseMove
Dim item As ListViewItem = lsvStores.GetItemAt(e.X, e.Y)
If item Is Nothing Then
If _item IsNot Nothing Then
_item.Selected = False
End If
_item = Nothing
ttpStoreDetails.Hide(sender)
End If
End Sub

Related

programmatically select and highlight a row of a ListView in VB.NET

I want to do something seemingly simple - programmatically select and highlight a row of a ListView in VB.NET.
VB.NET: How to dynamically select a list view item?
tells me what should to be all that is needed, but it isn't. The row is selected, but not highlighted.
http://vbcity.com/forums/t/28260.aspx
tells me about the "HideSelection" property and the .Focus() method (also referenced at Select programmatically a row of a Listview), which sounded hopeful, but the best I can get is the faint highlight mentioned, I want the full monty. I tried a Noddy example with just a ListView, in Details mode, FullRowSelection = true, HideSelection = False, one columnheader defined and then
ListView1.Items.Add("Red")
ListView1.Items.Add("Orange")
ListView1.Items.Add("Yellow")
ListView1.Items.Add("Green")
ListView1.Items(2).Selected = True
I get this
but I want this
I can simulate highlighting by adding these lines
ListView1.SelectedItems(0).BackColor = Color.CornflowerBlue
ListView1.SelectedItems(0).ForeColor = Color.White
but then how can I be sure to undo the artificial highlight if the row can be implicitly as well as explicitly deselected? Do I have to think of all the possible cases? That's too much work for what should be a simple operation. Plus, since I want to color-code my rows, there is an additional challenge that when I undo the highlight color, I have to figure out what color is appropriate at that point. Is there a better, simpler way?
You can access the Graphics object used to draw each item, and draw them yourself.
Make a new project with a Button and ListView. Paste the following code:
Form_Load to use multiple subitems
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.ListView1.OwnerDraw = True ' or else can't handle DrawItem event
ListView1.Columns.Add("ColumnHeader1")
ListView1.Columns.Add("ColumnHeader2")
ListView1.Columns.Add("ColumnHeader3")
Me.ListView1.Items.Add("Red")
Me.ListView1.Items.Add("Orange")
Me.ListView1.Items.Add("Yellow")
Me.ListView1.Items.Add("Green")
ListView1.Items(0).SubItems.Add("Strawberry")
ListView1.Items(0).SubItems.Add("Apple")
ListView1.Items(1).SubItems.Add("Pepper")
ListView1.Items(1).SubItems.Add("Apricot")
ListView1.Items(2).SubItems.Add("Plum")
ListView1.Items(2).SubItems.Add("Banana")
ListView1.Items(3).SubItems.Add("Apple")
ListView1.Items(3).SubItems.Add("Lime")
End Sub
Three handlers for the ListView's drawing related events. Code copied from this answer
Private Sub listView1_DrawColumnHeader(sender As Object, e As DrawListViewColumnHeaderEventArgs) Handles ListView1.DrawColumnHeader
e.DrawDefault = True
End Sub
Private Sub listView1_DrawSubItem(sender As Object, e As DrawListViewSubItemEventArgs) Handles ListView1.DrawSubItem
Const TEXT_OFFSET As Integer = 1
' I don't know why the text is located at 1px to the right. Maybe it's only for me.
Dim listView As ListView = DirectCast(sender, ListView)
' Check if e.Item is selected and the ListView has a focus.
If Not listView.Focused AndAlso e.Item.Selected Then
Dim rowBounds As Rectangle = e.SubItem.Bounds
Dim labelBounds As Rectangle = e.Item.GetBounds(ItemBoundsPortion.Label)
Dim leftMargin As Integer = labelBounds.Left - TEXT_OFFSET
Dim bounds As New Rectangle(rowBounds.Left + leftMargin, rowBounds.Top, If(e.ColumnIndex = 0, labelBounds.Width, (rowBounds.Width - leftMargin - TEXT_OFFSET)), rowBounds.Height)
Dim align As TextFormatFlags
Select Case listView.Columns(e.ColumnIndex).TextAlign
Case HorizontalAlignment.Right
align = TextFormatFlags.Right
Exit Select
Case HorizontalAlignment.Center
align = TextFormatFlags.HorizontalCenter
Exit Select
Case Else
align = TextFormatFlags.Left
Exit Select
End Select
TextRenderer.DrawText(e.Graphics, e.SubItem.Text, listView.Font, bounds, SystemColors.HighlightText, align Or TextFormatFlags.SingleLine Or TextFormatFlags.GlyphOverhangPadding Or TextFormatFlags.VerticalCenter Or TextFormatFlags.WordEllipsis)
Else
e.DrawDefault = True
End If
End Sub
Private Sub listView1_DrawItem(sender As Object, e As DrawListViewItemEventArgs) Handles ListView1.DrawItem
Dim listView As ListView = DirectCast(sender, ListView)
' Check if e.Item is selected and the ListView has a focus.
If Not listView.Focused AndAlso e.Item.Selected Then
Dim rowBounds As Rectangle = e.Bounds
Dim leftMargin As Integer = e.Item.GetBounds(ItemBoundsPortion.Label).Left
Dim bounds As New Rectangle(leftMargin, rowBounds.Top, rowBounds.Width - leftMargin, rowBounds.Height)
e.Graphics.FillRectangle(SystemBrushes.Highlight, bounds)
Else
e.DrawDefault = True
End If
End Sub
Button click handler to simulate item(2) selected
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Me.ListView1.Items(2).Selected = True
End Sub
This will draw the background color regardless of focus. You have a lot of control over other colors and fonts going this route too.
Here, the button has been clicked, to select item 2, while the button still has focus, and item 2 is selected.
Easiest thing,
Just allocate the LST_ItemIndex = lstList.FocusedItem.Index everytime you select a different item
and then fire the below whenever you want the highlight
If lstList.Items.Count > 0 Then
lstList.Items(LST_ItemIndex).Selected = True
lstList.Items(LST_ItemIndex).EnsureVisible()
End If

Button Array - how to pass a parameter to shared handler

I have a bit of code where i have a dynamically created array or buttons with staff pictures on them, as well as the staff's name. I've added one handler to handle any button click from any of the buttons. where i am stuck is, if you look at the code below, it all works fine, and if you click any of the buttons you get the "aha" test message. but i want the name of the staff clicked on (so btnArray(i).Text) to be passed to the handler for further processing. I tried adding a ByVal parameter to the handler but that caused an error. what's the correct way to do this? As i said, the code below works for me, i just am at a loss as to how to add the extra functionality.
Dim btnArray(staffcount) As System.Windows.Forms.Button
For i As Integer = 1 To staffcount - 1
btnArray(i) = New System.Windows.Forms.Button
btnArray(i).Visible = True
btnArray(i).Width = 80
btnArray(i).Height = 101
btnArray(i).BackgroundImage = Image.FromFile(picloc(i))
btnArray(i).BackgroundImageLayout = ImageLayout.Stretch
btnArray(i).Text = staffname(i)
Dim who As String
who = btnArray(i).Text
AddHandler btnArray(i).Click, AddressOf Me.theButton_Click
btnArray(i).ForeColor = Color.White
btnArray(i).TextAlign = ContentAlignment.BottomCenter
Dim fnt As Font
fnt = btnArray(i).Font
btnArray(i).Font = New Font(fnt.Name, 10, FontStyle.Bold)
FlowLayoutPanel1.Controls.Add(btnArray(i))
Next i
End Sub
Private Sub theButton_Click()
MsgBox("aha")
End Sub
First, correct the signature of your shared handler.
Private Sub theButton_Click(sender As Object, e As EventArgs)
End Sub
Once that is done getting the text of the button clicked is a simple matter.
Private Sub theButton_Click(sender As Object, e As EventArgs)
Dim textOfButtonClicked As String = DirectCast(sender, Button).Text
MessageBox.Show(textOfButtonClicked)
End Sub
The sender is the button that was clicked. Since signatures use objects for the sender the DirectCast 'changes' it to button and you then can access the .Text property of the button.
If there are more manipulations you want to perform on the clicked button you could do it this way
Private Sub theButton_Click(sender As Object, e As EventArgs)
Dim whBtn As Button = DirectCast(sender, Button) ' get reference to button clicked
Dim textOfButtonClicked As String = whBtn.Text
MessageBox.Show(textOfButtonClicked)
'e.g. change the color
whBtn.BackColor = Color.LightYellow
End Sub

Animate Picturebox in VB

I am new to VB and just can't figure it out how to animate a button using the MouseHover Event..
I want to create a single loop for all the buttons(picturebox) in my project that will increase the button's size when the user rests the mouse on it.
Maybe something like:
For Each Form As Form In Application.OpenForms
For Each Control As Control In Form.Controls
Tks. Any help is appreciated.
Use Inherits to create a new button (or PictureBox) class for you purpose. Here is the code.
Public Class cuteButton
Inherits System.Windows.Forms.Button
Protected Overrides Sub OnMouseHover(e As EventArgs)
'
'Wite code here to change button size or whatever.
'
MyBase.OnMouseHover(e)
End Sub
End Class
A very simple way is to use a common MouseHover event to grow your buttons (which I guess is really a Picturebox with an image in it):
Private Sub CustomButton_Grow(sender As Object, e As System.EventArgs) Handles Picturebox1.MouseHover, Picturebox2.MouseHover
'Set a maximum height to grow the buttons to.
'This can also be set for width depending on your needs!
Dim maxHeight as single = 50
If sender.Height < maxHeight then
sender.Size = New Size(sender.Width+1,sender.Height+1)
End if
End Sub
Then you can reset all buttons in a snap using the MouseLeave event. If you want that part animated as well then you can to use a global shrink routine that constantly shrink all buttons but the one in MouseHover. Good luck!
This Will Work even if you have 10,000 button or picture box ....
I am Assuming that you only have 1 form and many Buttons ,,, you have to be specific on your question
This Code will work fine with Buttons, Picturebox ,text box
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For Each cntrl As Control In Controls ' Looping for each Button as Control
If TypeOf cntrl Is Button Then
AddHandler cntrl.MouseEnter, AddressOf cntrl_MouseEnter ' Adding the event and handler
AddHandler cntrl.MouseLeave, AddressOf cntrl_MouseLeave ' Adding the event and handler
End If
Next
End Sub
'' Assuming you wanna eNlarge everytime the mouse Hover or Enter
Private Sub cntrl_MouseEnter(sender As Object, e As EventArgs)
CType(sender, Button).Size = New Point(CType(sender, Button).Size.Width + 50, CType(sender, Button).Size.Height + 50)
End Sub
'' Here it goes back normal size
Private Sub cntrl_MouseLeave(sender As Object, e As EventArgs)
CType(sender, Button).Size = New Point(CType(sender, Button).Size.Width - 50, CType(sender, Button).Size.Height - 50)
End Sub

identfying listview cell on mouseover

I am trying to identify which cell the user has their mouse over on a listview, currently I have
Private Sub ListView1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles ListView1.MouseMove
Dim cellnum As ListViewItem = ListView1.GetItemAt(e.X, e.Y)
tooltip1.SetToolTip(ListView1, thisItem.Text)
end sub
which is not functioning. How would I accomplish this
If by "cell" you mean the subitem, use HitTest to find the subitem:
Dim ht As ListViewHitTestInfo = lvex.HitTest(pt.X, pt.Y)
if ht.Item IsNot Nothing then
IndexOfSubItemAtXY = ht.Item.SubItems.IndexOf(ht.SubItem)
End if
Setting the tooltip on a MouseMove may prove problematic though. There is an ItemMouseHover where you could figure out which cell/subitem, it is over and set the tooltip accordingly/

contextmenustrip opening event determining sender

I have 30 labels. They can have any value I want.
I need to be able to assign one context menu to them all then determine which label was clicked in order to use my x variable.
Private Sub Label_Click(sender As Object, e As MouseEventArgs) Handles Label1.MouseClick, Label2.MouseClick, Label3.MouseClick, Label4.MouseClick, _
Label5.MouseClick, Label6.MouseClick, Label7.MouseClick, Label8.MouseClick, Label9.MouseClick, Label10.MouseClick, Label11.MouseClick, _
Label12.MouseClick, Label13.MouseClick, Label14.MouseClick, Label15.MouseClick, Label15.MouseClick, Label16.MouseClick, Label17.MouseClick, _
Label18.MouseClick, Label19.MouseClick, Label20.MouseClick, Label21.MouseClick, Label22.MouseClick, Label23.MouseClick, Label24.MouseClick, _
Label25.MouseClick, Label26.MouseClick, Label27.MouseClick, Label28.MouseClick, Label29.MouseClick, Label30.MouseClick
Dim x As String = sender.Text
xmlinteraction.appCall(x)
End Sub
I received awesome help the other day passing variable into contextmenustrip
But I am too new to put it all together and make it work. I understand what we are trying to do, but not all the syntax. Please help.
Jay,
Here is what I put together from the code you gave me. Is this what you were thinking? I feel like I missing something still and further clean the code. Possibly removing the case statements.
Private Sub rcmenuOption(x, y)
' x is equal to what the menu item was clicked
' Create case stament for that to call the correct xmlinteraction passing in y
Select Case x
Case "Copy Link"
copyClipboard(y)
End Select
End Sub
Private Sub rcmenuClicked(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ToolStripItemClickedEventArgs) Handles rcmenu.ItemClicked
' Get the Label clicked from the SourceControl property of the clicked ContextMenuStrip.
Dim contextMenu = DirectCast(sender, ContextMenuStrip)
Dim label = DirectCast(contextMenu.SourceControl, Label)
Dim var2 As String = label.Text
' Get the clicked menu strip and update its Text to the Label's Text.
Dim toolStripItem = e.ClickedItem
Dim var As String = toolStripItem.Text
rcmenuOption(var, var2)
End Sub
contextmenustrip opening event determining sender
OK, you have a number of Labels on a form and all of them use the same ContextMenuStrip (all the Labels have their ContextMenuStrip property set to the same ContextMenuStrip control).
When the user right clicks a Label and selects a menu item, you want that menu item's Text to change to the clicked Label's Text.
You can do this using your ContextMenuStrip ItemClicked event handler. Use the handler's sender and ToolStripItemClickedEventArgs parameters to get the Label's Text and a reference to the ToolStripItem clicked.
Private Sub ContextMenuStrip1_ItemClicked(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ToolStripItemClickedEventArgs) Handles ContextMenuStrip1.ItemClicked
' Get the Label clicked from the SourceControl property of the clicked ContextMenuStrip.
Dim contextMenu = DirectCast(sender, ContextMenuStrip)
Dim label = DirectCast(contextMenu.SourceControl, Label)
' Get the clicked menu strip and update its Text to the Label's Text.
Dim toolStripItem = e.ClickedItem
toolStripItem.Text = label.Text
End Sub