0

Like the title above, I am trying to display the focus box on the subitem / cell that is clicked.

To get the subitem / cell that is clicked I use the following code:

Private Sub LV_MouseClick(sender As Object, e As MouseEventArgs) Handles LV.MouseClick
    Info = LV.HitTest(e.Location)
    ClickedColumnLV = Info.Item.SubItems.IndexOf(Info.SubItem)
    ClickedRowLV = Info.Item.Index
    If e.Button = MouseButtons.Right Then
        If LV.FocusedItem.Bounds.Contains(e.Location) Then
            CMenu.Show(Cursor.Position)
        End If
    End If
End Sub

At this point i have Row Index (ClickedRowLV) and Column Index (ClickedColumnLV) Now I'am trying show focus on that clicked subitem/cell.

How can I do that?

EDIT :

Just to make sure that I didn't click the wrong item. So I want to have a focus rect or a sign if the sub-item is clicked.

Row must be full row select but at subitem /cell there is focus rect inside or outide. For example, please see the picture : enter image description here

Espada
  • 173
  • 1
  • 10

1 Answers1

0

Not quite sure whether you mean something like:

SOQ60633347

If that is true, then you can handle the MouseDown event of the ListView control as follows:

Private Sub LV_MouseDown(sender As Object, e As MouseEventArgs) Handles LV.MouseDown
    Dim selColor = SystemColors.Highlight
    Dim item = LV.Items.Cast(Of ListViewItem).
        Where(Function(x) x.BackColor.Equals(selColor) OrElse
        x.SubItems.Cast(Of ListViewItem.ListViewSubItem).
        Any(Function(y) y.BackColor.Equals(selColor))).FirstOrDefault

    If item IsNot Nothing Then
        item.BackColor = SystemColors.Window
        item.ForeColor = SystemColors.WindowText

        For Each subItem In item.SubItems.Cast(Of ListViewItem.ListViewSubItem)
            subItem.BackColor = SystemColors.Window
            subItem.ForeColor = SystemColors.WindowText
        Next
    End If

    Dim ht = LV.HitTest(e.Location)

    If ht.SubItem IsNot Nothing Then
        ht.Item.UseItemStyleForSubItems = False
        ht.SubItem.BackColor = selColor
        ht.SubItem.ForeColor = SystemColors.Window        
    End If
End Sub

Of course this won't work if the FullRowSelect property is enabled.


Edit: Custom ListView


Following up on your comment and update, I don't know any easy way to achieve that. I think you need to create a custom ListView and override the relevant events as follows:

Imports System.Windows.Forms
Imports System.Drawing
Imports System.ComponentModel

<DesignerCategory("Code")>
Public Class ListViewEx
    Inherits ListView

    Private ht As ListViewHitTestInfo

    Sub New()
        MyBase.New
        DoubleBuffered = True
        OwnerDraw = True
        FullRowSelect = True
    End Sub

    Public Property DrawFocusRectangle As Boolean = True

    Protected Overrides Sub OnDrawColumnHeader(e As DrawListViewColumnHeaderEventArgs)
        e.DrawDefault = True
    End Sub

    Protected Overrides Sub OnDrawItem(e As DrawListViewItemEventArgs)
        If View = View.Details Then Return

        If e.Item.Selected Then
            e.Graphics.FillRectangle(Brushes.LightSteelBlue, e.Bounds)
            e.DrawFocusRectangle()
        Else
            e.DrawBackground()
        End If

        e.DrawText()
    End Sub

    Protected Overrides Sub OnDrawSubItem(e As DrawListViewSubItemEventArgs)
        Using sf As New StringFormat With {
                            .Alignment = StringAlignment.Near,
                            .LineAlignment = StringAlignment.Center,
                            .Trimming = StringTrimming.EllipsisCharacter,
                            .FormatFlags = StringFormatFlags.NoWrap
                        },
                        br = New SolidBrush(e.SubItem.ForeColor)

            Select Case e.Header.TextAlign
                Case HorizontalAlignment.Center
                    sf.Alignment = StringAlignment.Center
                Case HorizontalAlignment.Right
                    sf.Alignment = StringAlignment.Far
            End Select

            If e.Item.Selected Then
                If e.ColumnIndex = 0 OrElse FullRowSelect Then
                    e.Graphics.FillRectangle(Brushes.LightSteelBlue, e.Bounds)
                End If
            Else
                e.DrawBackground()
            End If
            e.Graphics.DrawString(e.SubItem.Text, e.SubItem.Font, br, e.Bounds, sf)
        End Using

        'Here you go...
        If DrawFocusRectangle AndAlso ht IsNot Nothing AndAlso
            e.Item.Focused AndAlso e.SubItem Is ht.SubItem Then
            Using pn As New Pen(Color.Orange, 2)
                Dim r As New Rectangle(e.Bounds.X,
                                       e.Bounds.Y,
                                       e.Header.Width - 1,
                                       e.Bounds.Height - 1)

                e.Graphics.DrawRectangle(pn, r)

                'or just draw focus rectangle ...
                'ControlPaint.DrawFocusRectangle(e.Graphics, r)
            End Using
        End If
    End Sub

    Protected Overrides Sub OnMouseDown(e As MouseEventArgs)
        MyBase.OnMouseDown(e)

        ht = HitTest(e.Location)
        Invalidate()
    End Sub

    Protected Overrides Sub OnColumnWidthChanged(e As ColumnWidthChangedEventArgs)
        MyBase.OnColumnWidthChanged(e)
        Invalidate()
    End Sub

End Class

SOQ60633347B


Related


  • Thank you, your answer is approaching, but has not fully answered my question, please see the question again, I added information there. – Espada Mar 11 '20 at 14:57
  • @Espada ahh, this is something else. I'll check it out. –  Mar 11 '20 at 15:03