By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,184 Members | 1,558 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,184 IT Pros & Developers. It's quick & easy.

ListView edit

P: n/a
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
Jul 17 '05 #1
Share this Question
Share on Google+
2 Replies


P: n/a
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 dwLastSubitemEdited As Long

Private Const LVM_FIRST = &H1000
Private Const LVM_GETCOLUMNWIDTH = (LVM_FIRST + 29)
Private Const LVM_GETTOPINDEX = (LVM_FIRST + 39)
Private Const LVM_GETSUBITEMRECT = (LVM_FIRST + 56)
Private Const LVM_SUBITEMHITTEST = (LVM_FIRST + 57)
Private Const LVHT_ONITEMICON = &H2
Private Const LVHT_ONITEMLABEL = &H4
Private Const LVHT_ONITEMSTATEICON = &H8
Private Const LVHT_ONITEM = (LVHT_ONITEMICON Or _
LVHT_ONITEMLABEL Or _
LVHT_ONITEMSTATEICON)
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 "SendMessageA" _
(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_ColumnClick(ByVal ColumnHeader As ColumnHeader)

'hide the text box
Text1.Visible = False

'sort the items
ListView1.SortKey = ColumnHeader.Index - 1
ListView1.SortOrder = Abs(Not ListView1.SortOrder = 1)
ListView1.Sorted = True

End Sub

Private Sub ListView1_MouseDown(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 dwLastSubitemEdited > 0 Then
itmClicked.SubItems(dwLastSubitemEdited) = Text1.Text
End If

'hide the textbox
Text1.Visible = False

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

'find out which subitem was clicked
Call SendMessage(ListView1.hwnd, _
LVM_SUBITEMHITTEST, _
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.LabelEdit = lvwManual

'determine the bounding rectangle
'of the subitem column
rc.Left = LVIR_LABEL
rc.Top = HTI.iSubItem
Call SendMessage(ListView1.hwnd, _
LVM_GETSUBITEMRECT, _
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.ListItems(HTI.iItem + 1)
itmClicked.Selected = True

'get the current top index
topindex = SendMessage(ListView1.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.TwipsPerPixelX) + 80

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

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

'get the column width for the subitem
fpw = SendMessage(ListView1.hwnd, _
LVM_GETCOLUMNWIDTH, _
HTI.iSubItem, _
ByVal 0&)

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

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

.Text = itmClicked.SubItems(HTI.iSubItem)

dwLastSubitemEdited = 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_MouseUp(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 dwLastSubitemEdited > 0 Then
itmClicked.SubItems(dwLastSubitemEdited) = 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" <no****@fictief.com> wrote in message
news:3f*********************@reader1.news.skynet.b e...
: 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
:
:
Jul 17 '05 #2

P: n/a
Thanks Randy

Greets John

"Randy Birch" <rg************@mvps.org> schreef in bericht
news:u_*******************@news01.bloor.is.net.cab le.rogers.com...
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 dwLastSubitemEdited As Long

Private Const LVM_FIRST = &H1000
Private Const LVM_GETCOLUMNWIDTH = (LVM_FIRST + 29)
Private Const LVM_GETTOPINDEX = (LVM_FIRST + 39)
Private Const LVM_GETSUBITEMRECT = (LVM_FIRST + 56)
Private Const LVM_SUBITEMHITTEST = (LVM_FIRST + 57)
Private Const LVHT_ONITEMICON = &H2
Private Const LVHT_ONITEMLABEL = &H4
Private Const LVHT_ONITEMSTATEICON = &H8
Private Const LVHT_ONITEM = (LVHT_ONITEMICON Or _
LVHT_ONITEMLABEL Or _
LVHT_ONITEMSTATEICON)
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 "SendMessageA" _
(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_ColumnClick(ByVal ColumnHeader As ColumnHeader)

'hide the text box
Text1.Visible = False

'sort the items
ListView1.SortKey = ColumnHeader.Index - 1
ListView1.SortOrder = Abs(Not ListView1.SortOrder = 1)
ListView1.Sorted = True

End Sub

Private Sub ListView1_MouseDown(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 dwLastSubitemEdited > 0 Then
itmClicked.SubItems(dwLastSubitemEdited) = Text1.Text
End If

'hide the textbox
Text1.Visible = False

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

'find out which subitem was clicked
Call SendMessage(ListView1.hwnd, _
LVM_SUBITEMHITTEST, _
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.LabelEdit = lvwManual

'determine the bounding rectangle
'of the subitem column
rc.Left = LVIR_LABEL
rc.Top = HTI.iSubItem
Call SendMessage(ListView1.hwnd, _
LVM_GETSUBITEMRECT, _
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.ListItems(HTI.iItem + 1)
itmClicked.Selected = True

'get the current top index
topindex = SendMessage(ListView1.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.TwipsPerPixelX) + 80

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

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

'get the column width for the subitem
fpw = SendMessage(ListView1.hwnd, _
LVM_GETCOLUMNWIDTH, _
HTI.iSubItem, _
ByVal 0&)

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

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

.Text = itmClicked.SubItems(HTI.iSubItem)

dwLastSubitemEdited = 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_MouseUp(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 dwLastSubitemEdited > 0 Then
itmClicked.SubItems(dwLastSubitemEdited) = 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" <no****@fictief.com> wrote in message
news:3f*********************@reader1.news.skynet.b e...
: 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
:
:

Jul 17 '05 #3

This discussion thread is closed

Replies have been disabled for this discussion.