ListView_AnyEdit


Description:
This is a straightforward enough sample, if just complicated. It allows the user to edit any of the "cells" in a ListView's report mode. It does this by simply determining what area of the list view they've clicked on, the placing a textbox over that. See the sample code to see how to integrate it with a project. Note: The text box should have its border set to None, and be set to invisible.
 
Code:
Option Explicit

Public Sub ListView_AnyEdit(x As Single, liSel As ListItem, nSelCol _
   As Long, sSelText As Long, lvCtrl As ListView, txtCtrl As TextBox)
'x        = [in] x value for the column
'liSel    = [out] Selected ListView Item
'nSelCol  = [out] Selected column number
'             (1 = List Item, 2 = Sub Item #1, ...)
'sSelText = [out] Text of selected column
'lvCtrl   = [in] ListView control
'txtCtrl  = [in] TextBox control

    Dim lvi As ListItem
    Set lvi = lvCtrl.SelectedItem
    If lvi Is Nothing Then
        Exit Sub
    End If
    
    txtCtrl.Top = lvi.Top + lvCtrl.Top
    txtCtrl.Left = lvi.Left + lvCtrl.Left
    
    txtCtrl.Width = lvi.Width
    txtCtrl.Height = lvi.Height

    Dim nSelCol As Long
    Dim i As Long
    Dim nCurCol As Long
    Dim nNextCol As Long
    Dim bFound As Boolean
    
    m_X = m_X - lvi.Left
    
    nSelCol = 1
    For i = 1 To lvCtrl.ColumnHeaders.Count
        nNextCol = nNextCol + lvCtrl.ColumnHeaders.Item(i).Width
        If m_X >= nCurCol And m_X <= nNextCol Then
            nSelCol = i
            bFound = True
            Exit For
        End If
        nCurCol = nNextCol
    Next
    
    If bFound Then
        txtCtrl.Left = txtCtrl.Left + nCurCol
        txtCtrl.Width = nNextCol - nCurCol
        
        Set m_liSel = lvi
        m_nSelCol = nSelCol
        
    Else
        Exit Sub
    End If
    
    txtCtrl.Left = txtCtrl.Left + 105
    txtCtrl.Top = txtCtrl.Top + 45
    
    txtCtrl.Height = txtCtrl.Height - 45
    
    If txtCtrl.Left < lvCtrl.Left Then
        If txtCtrl.Width - (lvCtrl.Left - txtCtrl.Left) < 0 Then
            Exit Sub
        Else
            txtCtrl.Width = txtCtrl.Width - (lvCtrl.Left - _
                            txtCtrl.Left)
            txtCtrl.Left = lvCtrl.Left
        End If
    End If
    
    If txtCtrl.Width + txtCtrl.Left > lvCtrl.Width + lvCtrl.Left Then
        If txtCtrl.Width - ((txtCtrl.Width + txtCtrl.Left) - _
          (lvCtrl.Width + lvCtrl.Left)) < 0 Then
          
            Exit Sub
            
        Else
        
            txtCtrl.Width = txtCtrl.Width - ((txtCtrl.Width + _
               txtCtrl.Left) - (lvCtrl.Width + lvCtrl.Left))
            
        End If
    End If

    If m_nSelCol = 1 Then
        txtCtrl.Text = lvi.Text
    Else
        txtCtrl.Text = lvi.SubItems(m_nSelCol - 1)
    End If

    m_sSelText = txtCtrl.Text

    txtCtrl.Visible = True
    txtCtrl.SelStart = 0
    txtCtrl.SelLength = Len(txtCtrl.Text)
    txtCtrl.SetFocus
    
End Sub

 
Sample Usage:
 
'Form code for demo.  Needs a ListView and a TextBox

Option Explicit

Private m_X As Single
Private m_liSel As ListItem
Private m_nSelCol As Long
Private m_sSelText As String

Private Sub ListView1_DblClick()

    ListView_AnyEdit m_X, m_liSel, m_nSelCol, m_sSelText, _
                     ListView1, Text1

End Sub

Private Sub ListView1_MouseUp(Button As Integer, Shift As Integer, _
   x As Single, y As Single)
    
    m_X = x

End Sub

Private Sub Text1_KeyPress(KeyAscii As Integer)

    If KeyAscii = 13 Then
        Text1_LostFocus
        KeyAscii = 0
    ElseIf KeyAscii = 27 Then
        Text1.Text = m_sSelText
        KeyAscii = 0
        Text1_LostFocus
    End If

End Sub

Private Sub Text1_LostFocus()

    If m_nSelCol = 1 Then
        m_liSel.Text = Text1.Text
    Else
        m_liSel.SubItems(m_nSelCol - 1) = Text1.Text
    End If

    Text1.Visible = False

End Sub