ListView edit

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • John Lauwers

    ListView edit

    I know you can edit the first column of the listview control, is there a way
    to edit the second and/or the other columns?

    greets John


  • Randy Birch

    #2
    Re: ListView edit

    No, not using the control as provided. Only the main column provides
    in-place editing. You can, however, duplicate this functionality using
    another text box you position over the subitems on clicking. Give this a
    try --- toss all this into a form's genearal declarations section after
    you've added only a listview and textbox (both with the default names).

    Option Explicit

    Private Type LVITEM
    mask As Long
    iItem As Long
    iSubItem As Long
    state As Long
    stateMask As Long
    pszText As String
    cchTextMax As Long
    iImage As Long
    lParam As Long
    iIndent As Long
    End Type

    Private bDoingSetup As Boolean
    Private dirty As Boolean
    Private itmClicked As ListItem
    Private dwLastSubitemEd ited As Long

    Private Const LVM_FIRST = &H1000
    Private Const LVM_GETCOLUMNWI DTH = (LVM_FIRST + 29)
    Private Const LVM_GETTOPINDEX = (LVM_FIRST + 39)
    Private Const LVM_GETSUBITEMR ECT = (LVM_FIRST + 56)
    Private Const LVM_SUBITEMHITT EST = (LVM_FIRST + 57)
    Private Const LVHT_ONITEMICON = &H2
    Private Const LVHT_ONITEMLABE L = &H4
    Private Const LVHT_ONITEMSTAT EICON = &H8
    Private Const LVHT_ONITEM = (LVHT_ONITEMICO N Or _
    LVHT_ONITEMLABE L Or _
    LVHT_ONITEMSTAT EICON)
    Private Const LVIR_LABEL = 2

    Private Type POINTAPI
    x As Long
    y As Long
    End Type

    Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
    End Type

    Private Type LVHITTESTINFO
    pt As POINTAPI
    flags As Long
    iItem As Long
    iSubItem As Long
    End Type

    Private Declare Function ScreenToClient Lib "user32" _
    (ByVal hwnd As Long, lpPoint As POINTAPI) As Long

    Private Declare Function SendMessage Lib "user32" _
    Alias "SendMessag eA" _
    (ByVal hwnd As Long, _
    ByVal wMsg As Long, _
    ByVal wParam As Long, _
    lParam As Any) As Long

    Private Sub Form_Load()

    Dim itmx As ListItem
    Dim cnt As Long

    With ListView1
    .ColumnHeaders. Add , , "col 1"
    .ColumnHeaders. Add , , "col 2"
    .ColumnHeaders. Add , , "col 3"
    .ColumnHeaders. Add , , "col 4"

    For cnt = 1 To 20
    Set itmx = .ListItems.Add( , , "Item " & CStr(cnt))
    itmx.SubItems(1 ) = "subitem 1," & CStr(cnt)
    itmx.SubItems(2 ) = "subitem 2," & CStr(cnt)
    itmx.SubItems(3 ) = "subitem 3," & CStr(cnt)
    Next

    .SortKey = 0
    .Sorted = False
    .View = lvwReport
    .GridLines = True
    .FullRowSelect = True
    .LabelEdit = lvwManual

    End With

    Text1.Visible = False

    End Sub

    Private Sub ListView1_Colum nClick(ByVal ColumnHeader As ColumnHeader)

    'hide the text box
    Text1.Visible = False

    'sort the items
    ListView1.SortK ey = ColumnHeader.In dex - 1
    ListView1.SortO rder = Abs(Not ListView1.SortO rder = 1)
    ListView1.Sorte d = True

    End Sub

    Private Sub ListView1_Mouse Down(Button As Integer, _
    Shift As Integer, _
    x As Single, _
    y As Single)

    'this routine:
    '1. sets the last change if the dirty flag is set
    '2. sets a flag to prevent setting the dirty flag
    '3. determines the item or subitem clicked
    '4. calc's the position for the text box
    '5. moves and shows the text box
    '6. clears the dirty flag
    '7. clears the DoingSetup flag

    Dim HTI As LVHITTESTINFO
    Dim fpx As Single
    Dim fpy As Single
    Dim fpw As Single
    Dim fph As Single
    Dim rc As RECT
    Dim topindex As Long

    'prevent the textbox change event from
    'registering as dirty when the text is
    'assigned to the textbox
    bDoingSetup = True

    'if a pending dirty flag is set, update the
    'last edited item before moving on
    If dirty And dwLastSubitemEd ited > 0 Then
    itmClicked.SubI tems(dwLastSubi temEdited) = Text1.Text
    End If

    'hide the textbox
    Text1.Visible = False

    'get the position of the click
    With HTI
    .pt.x = (x / Screen.TwipsPer PixelX)
    .pt.y = (y / Screen.TwipsPer PixelY)
    .flags = LVHT_ONITEM
    End With

    'find out which subitem was clicked
    Call SendMessage(Lis tView1.hwnd, _
    LVM_SUBITEMHITT EST, _
    0, HTI)

    'if on an item (HTI.iItem <> -1) and
    'the click occurred on the subitem
    'column of interest (HTI.iSubItem = 2 -
    'which is column 3 (0-based)) move and
    'show the textbox
    If HTI.iItem <> -1 And HTI.iSubItem > 0 Then

    'prevent the listview label editing
    'from occurring if the control has
    'full row select set
    ListView1.Label Edit = lvwManual

    'determine the bounding rectangle
    'of the subitem column
    rc.Left = LVIR_LABEL
    rc.Top = HTI.iSubItem
    Call SendMessage(Lis tView1.hwnd, _
    LVM_GETSUBITEMR ECT, _
    HTI.iItem, _
    rc)

    'we need to keep track of which
    'item was clicked so the item can
    'be updated later
    'position the text box
    Set itmClicked = ListView1.ListI tems(HTI.iItem + 1)
    itmClicked.Sele cted = True

    'get the current top index
    topindex = SendMessage(Lis tView1.hwnd, _
    LVM_GETTOPINDEX , _
    0&, _
    ByVal 0&)

    'establish the bounding rect for
    'the subitem in VB terms (the x
    'and y coordinates, and the height
    'and width of the item
    fpx = ListView1.Left + _
    (rc.Left * Screen.TwipsPer PixelX) + 80

    fpy = ListView1.Top + _
    (HTI.iItem + 1 - topindex) + _
    (rc.Top * Screen.TwipsPer PixelY)

    'a hard-coded height for the text box
    fph = 120

    'get the column width for the subitem
    fpw = SendMessage(Lis tView1.hwnd, _
    LVM_GETCOLUMNWI DTH, _
    HTI.iSubItem, _
    ByVal 0&)

    'calc the required width of
    'the textbox to fit in the column
    fpw = (fpw * Screen.TwipsPer PixelX) - 40

    'assign the current subitem
    'value to the textbox
    With Text1

    .Text = itmClicked.SubI tems(HTI.iSubIt em)

    dwLastSubitemEd ited = HTI.iSubItem

    'position it over the subitem, make
    'visible and assure the text box
    'appears overtop the listview
    .Move fpx, fpy, fpw, fph
    .Visible = True
    .ZOrder 0
    .SetFocus

    End With

    'clear the setup flag to allow the
    'textbox change event to set the
    '"dirty" flag, and clear that flag
    'in preparation for editing
    bDoingSetup = False
    dirty = False

    End If

    End Sub


    Private Sub ListView1_Mouse Up(Button As Integer, _
    Shift As Integer, _
    x As Single, _
    y As Single)

    'if showing the text box, set
    'focus to it and select any
    'text in the control
    If Text1.Visible = True Then

    With Text1
    .SetFocus
    .SelStart = 0
    .SelLength = Len(.Text)
    End With

    End If

    End Sub

    Private Sub Text1_Change()

    If Not bDoingSetup Then
    dirty = True
    End If

    End Sub


    Private Sub Text1_LostFocus ()

    If dirty And dwLastSubitemEd ited > 0 Then
    itmClicked.SubI tems(dwLastSubi temEdited) = Text1.Text
    dirty = False
    End If

    End Sub





    --

    Randy Birch
    MVP Visual Basic

    Please respond only to the newsgroups so all can benefit.


    "John Lauwers" <nobody@fictief .com> wrote in message
    news:3fdf0f89$0 $284$ba620e4c@r eader1.news.sky net.be...
    : I know you can edit the first column of the listview control, is there a
    way
    : to edit the second and/or the other columns?
    :
    : greets John
    :
    :


    Comment

    • John Lauwers

      #3
      Re: ListView edit

      Thanks Randy

      Greets John

      "Randy Birch" <rgb_removethis @mvps.org> schreef in bericht
      news:u_MDb.5612 2$ea%.17542@new s01.bloor.is.ne t.cable.rogers. com...[color=blue]
      > No, not using the control as provided. Only the main column provides
      > in-place editing. You can, however, duplicate this functionality using
      > another text box you position over the subitems on clicking. Give this a
      > try --- toss all this into a form's genearal declarations section after
      > you've added only a listview and textbox (both with the default names).
      >
      > Option Explicit
      >
      > Private Type LVITEM
      > mask As Long
      > iItem As Long
      > iSubItem As Long
      > state As Long
      > stateMask As Long
      > pszText As String
      > cchTextMax As Long
      > iImage As Long
      > lParam As Long
      > iIndent As Long
      > End Type
      >
      > Private bDoingSetup As Boolean
      > Private dirty As Boolean
      > Private itmClicked As ListItem
      > Private dwLastSubitemEd ited As Long
      >
      > Private Const LVM_FIRST = &H1000
      > Private Const LVM_GETCOLUMNWI DTH = (LVM_FIRST + 29)
      > Private Const LVM_GETTOPINDEX = (LVM_FIRST + 39)
      > Private Const LVM_GETSUBITEMR ECT = (LVM_FIRST + 56)
      > Private Const LVM_SUBITEMHITT EST = (LVM_FIRST + 57)
      > Private Const LVHT_ONITEMICON = &H2
      > Private Const LVHT_ONITEMLABE L = &H4
      > Private Const LVHT_ONITEMSTAT EICON = &H8
      > Private Const LVHT_ONITEM = (LVHT_ONITEMICO N Or _
      > LVHT_ONITEMLABE L Or _
      > LVHT_ONITEMSTAT EICON)
      > Private Const LVIR_LABEL = 2
      >
      > Private Type POINTAPI
      > x As Long
      > y As Long
      > End Type
      >
      > Private Type RECT
      > Left As Long
      > Top As Long
      > Right As Long
      > Bottom As Long
      > End Type
      >
      > Private Type LVHITTESTINFO
      > pt As POINTAPI
      > flags As Long
      > iItem As Long
      > iSubItem As Long
      > End Type
      >
      > Private Declare Function ScreenToClient Lib "user32" _
      > (ByVal hwnd As Long, lpPoint As POINTAPI) As Long
      >
      > Private Declare Function SendMessage Lib "user32" _
      > Alias "SendMessag eA" _
      > (ByVal hwnd As Long, _
      > ByVal wMsg As Long, _
      > ByVal wParam As Long, _
      > lParam As Any) As Long
      >
      > Private Sub Form_Load()
      >
      > Dim itmx As ListItem
      > Dim cnt As Long
      >
      > With ListView1
      > .ColumnHeaders. Add , , "col 1"
      > .ColumnHeaders. Add , , "col 2"
      > .ColumnHeaders. Add , , "col 3"
      > .ColumnHeaders. Add , , "col 4"
      >
      > For cnt = 1 To 20
      > Set itmx = .ListItems.Add( , , "Item " & CStr(cnt))
      > itmx.SubItems(1 ) = "subitem 1," & CStr(cnt)
      > itmx.SubItems(2 ) = "subitem 2," & CStr(cnt)
      > itmx.SubItems(3 ) = "subitem 3," & CStr(cnt)
      > Next
      >
      > .SortKey = 0
      > .Sorted = False
      > .View = lvwReport
      > .GridLines = True
      > .FullRowSelect = True
      > .LabelEdit = lvwManual
      >
      > End With
      >
      > Text1.Visible = False
      >
      > End Sub
      >
      > Private Sub ListView1_Colum nClick(ByVal ColumnHeader As ColumnHeader)
      >
      > 'hide the text box
      > Text1.Visible = False
      >
      > 'sort the items
      > ListView1.SortK ey = ColumnHeader.In dex - 1
      > ListView1.SortO rder = Abs(Not ListView1.SortO rder = 1)
      > ListView1.Sorte d = True
      >
      > End Sub
      >
      > Private Sub ListView1_Mouse Down(Button As Integer, _
      > Shift As Integer, _
      > x As Single, _
      > y As Single)
      >
      > 'this routine:
      > '1. sets the last change if the dirty flag is set
      > '2. sets a flag to prevent setting the dirty flag
      > '3. determines the item or subitem clicked
      > '4. calc's the position for the text box
      > '5. moves and shows the text box
      > '6. clears the dirty flag
      > '7. clears the DoingSetup flag
      >
      > Dim HTI As LVHITTESTINFO
      > Dim fpx As Single
      > Dim fpy As Single
      > Dim fpw As Single
      > Dim fph As Single
      > Dim rc As RECT
      > Dim topindex As Long
      >
      > 'prevent the textbox change event from
      > 'registering as dirty when the text is
      > 'assigned to the textbox
      > bDoingSetup = True
      >
      > 'if a pending dirty flag is set, update the
      > 'last edited item before moving on
      > If dirty And dwLastSubitemEd ited > 0 Then
      > itmClicked.SubI tems(dwLastSubi temEdited) = Text1.Text
      > End If
      >
      > 'hide the textbox
      > Text1.Visible = False
      >
      > 'get the position of the click
      > With HTI
      > .pt.x = (x / Screen.TwipsPer PixelX)
      > .pt.y = (y / Screen.TwipsPer PixelY)
      > .flags = LVHT_ONITEM
      > End With
      >
      > 'find out which subitem was clicked
      > Call SendMessage(Lis tView1.hwnd, _
      > LVM_SUBITEMHITT EST, _
      > 0, HTI)
      >
      > 'if on an item (HTI.iItem <> -1) and
      > 'the click occurred on the subitem
      > 'column of interest (HTI.iSubItem = 2 -
      > 'which is column 3 (0-based)) move and
      > 'show the textbox
      > If HTI.iItem <> -1 And HTI.iSubItem > 0 Then
      >
      > 'prevent the listview label editing
      > 'from occurring if the control has
      > 'full row select set
      > ListView1.Label Edit = lvwManual
      >
      > 'determine the bounding rectangle
      > 'of the subitem column
      > rc.Left = LVIR_LABEL
      > rc.Top = HTI.iSubItem
      > Call SendMessage(Lis tView1.hwnd, _
      > LVM_GETSUBITEMR ECT, _
      > HTI.iItem, _
      > rc)
      >
      > 'we need to keep track of which
      > 'item was clicked so the item can
      > 'be updated later
      > 'position the text box
      > Set itmClicked = ListView1.ListI tems(HTI.iItem + 1)
      > itmClicked.Sele cted = True
      >
      > 'get the current top index
      > topindex = SendMessage(Lis tView1.hwnd, _
      > LVM_GETTOPINDEX , _
      > 0&, _
      > ByVal 0&)
      >
      > 'establish the bounding rect for
      > 'the subitem in VB terms (the x
      > 'and y coordinates, and the height
      > 'and width of the item
      > fpx = ListView1.Left + _
      > (rc.Left * Screen.TwipsPer PixelX) + 80
      >
      > fpy = ListView1.Top + _
      > (HTI.iItem + 1 - topindex) + _
      > (rc.Top * Screen.TwipsPer PixelY)
      >
      > 'a hard-coded height for the text box
      > fph = 120
      >
      > 'get the column width for the subitem
      > fpw = SendMessage(Lis tView1.hwnd, _
      > LVM_GETCOLUMNWI DTH, _
      > HTI.iSubItem, _
      > ByVal 0&)
      >
      > 'calc the required width of
      > 'the textbox to fit in the column
      > fpw = (fpw * Screen.TwipsPer PixelX) - 40
      >
      > 'assign the current subitem
      > 'value to the textbox
      > With Text1
      >
      > .Text = itmClicked.SubI tems(HTI.iSubIt em)
      >
      > dwLastSubitemEd ited = HTI.iSubItem
      >
      > 'position it over the subitem, make
      > 'visible and assure the text box
      > 'appears overtop the listview
      > .Move fpx, fpy, fpw, fph
      > .Visible = True
      > .ZOrder 0
      > .SetFocus
      >
      > End With
      >
      > 'clear the setup flag to allow the
      > 'textbox change event to set the
      > '"dirty" flag, and clear that flag
      > 'in preparation for editing
      > bDoingSetup = False
      > dirty = False
      >
      > End If
      >
      > End Sub
      >
      >
      > Private Sub ListView1_Mouse Up(Button As Integer, _
      > Shift As Integer, _
      > x As Single, _
      > y As Single)
      >
      > 'if showing the text box, set
      > 'focus to it and select any
      > 'text in the control
      > If Text1.Visible = True Then
      >
      > With Text1
      > .SetFocus
      > .SelStart = 0
      > .SelLength = Len(.Text)
      > End With
      >
      > End If
      >
      > End Sub
      >
      > Private Sub Text1_Change()
      >
      > If Not bDoingSetup Then
      > dirty = True
      > End If
      >
      > End Sub
      >
      >
      > Private Sub Text1_LostFocus ()
      >
      > If dirty And dwLastSubitemEd ited > 0 Then
      > itmClicked.SubI tems(dwLastSubi temEdited) = Text1.Text
      > dirty = False
      > End If
      >
      > End Sub
      >
      >
      >
      >
      >
      > --
      >
      > Randy Birch
      > MVP Visual Basic
      > http://www.mvps.org/vbnet/
      > Please respond only to the newsgroups so all can benefit.
      >
      >
      > "John Lauwers" <nobody@fictief .com> wrote in message
      > news:3fdf0f89$0 $284$ba620e4c@r eader1.news.sky net.be...
      > : I know you can edit the first column of the listview control, is there a
      > way
      > : to edit the second and/or the other columns?
      > :
      > : greets John
      > :
      > :
      >
      >[/color]


      Comment

      Working...