Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Listview

14 réponses
Avatar
tking
Hello,

Par exemple, après un tri dans un listview, visuellement l'élément
numéro 1 se retrouve en 4iem position.

Alors l'élément numéro 1 visible dans la liste n'est pas l'élément
stocké dans listview1.listitems.item(1), qui est en 4.

Du coup, l'index de la liste visible n'est pas le même que celle de la
listview.

Est-il possible de réorganiser le listview en mémoire pour le faire
correspondre à la liste visible ?


Merci et bon dimanche.

10 réponses

1 2
Avatar
Jacques93
Bonjour tking,
tking a écrit :
Hello,

Par exemple, après un tri dans un listview, visuellement l'élément
numéro 1 se retrouve en 4iem position.

Alors l'élément numéro 1 visible dans la liste n'est pas l'élément
stocké dans listview1.listitems.item(1), qui est en 4.

Du coup, l'index de la liste visible n'est pas le même que celle de la
listview.

Est-il possible de réorganiser le listview en mémoire pour le faire
correspondre à la liste visible ?





Pas tout compris, fais tu un tri des données en dehors du listview ?
Utilises tu les propriétés :

.Sorted = True
.SortKey = NumeroDeColonne
.SortOrder = lvwAscending

--
Cordialement,

Jacques.
Avatar
tking
Jacques93 a exposé le 11/11/2007 :
Bonjour tking,
tking a écrit :
Hello,

Par exemple, après un tri dans un listview, visuellement l'élément numéro 1
se retrouve en 4iem position.

Alors l'élément numéro 1 visible dans la liste n'est pas l'élément stocké
dans listview1.listitems.item(1), qui est en 4.

Du coup, l'index de la liste visible n'est pas le même que celle de la
listview.

Est-il possible de réorganiser le listview en mémoire pour le faire
correspondre à la liste visible ?





Pas tout compris, fais tu un tri des données en dehors du listview ?
Utilises tu les propriétés :

.Sorted = True
.SortKey = NumeroDeColonne
.SortOrder = lvwAscending



En fait, la liste se compose ainsi

1 - antoine
2 - françois
3 - pierre
4 - marie

Donc si j'appelle l'item 1 avec listview.item j'ai antoine, 2 françois
...

Je fais un tri, résultat à l'écran

3 - pierre
4 - marie
2 - françois
1 - marie

Si j'appelle l'item 1 j'ai comme réponse antoine, ou 2 françois... 4
marie.

Est-ce normal ?

Pour le tri j'utilise un module ext. car par défaut le listview ne fait
pas le tri par date et dans ma liste il y a des dates.



================================

Option Explicit

'Structures
Public vu1, vu2, icon_ As Integer
Public f2_height As Long
Public Asce As Boolean
Public Asce1 As Boolean
Public indice As Integer
Public Type POINT
X As Long
Y As Long
End Type

Public Type LV_FINDINFO
flags As Long
psz As String
lParam As Long
Pt As POINT
vkDirection As Long
End Type

Public Type LV_ITEM
mask As Long
iItem As Long
iSubItem As Long
State As Long
stateMask As Long
pszText As Long
cchTextMax As Long
iImage As Long
lParam As Long
iIndent As Long
End Type

'Constants
Private Const LVFI_PARAM = 1
Private Const LVIF_TEXT = &H1

Private Const LVM_FIRST = &H1000
Private Const LVM_FINDITEM = LVM_FIRST + 13
Private Const LVM_GETITEMTEXT = LVM_FIRST + 45
Public Const LVM_SORTITEMS = LVM_FIRST + 48

'API declarations.
Declare Function GetWindowsDirectory Lib "kernel32" Alias
"GetWindowsDirectoryA" ( _
ByVal lpBuffer As String, _
ByVal nSize As Long) As Long

Declare Function SendMessage_b Lib "user32" Alias "SendMessageA" (
_
ByVal hWnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long

'Trier des dates

'CompareDates: This is the sorting routine that gets passed to
the
'ListView control to provide the comparison test for date values.

Public Function CompareDates(ByVal lngParam1 As Long, _
ByVal lngParam2 As Long, _
ByVal hWnd As Long) As Long

Dim strName1 As String
Dim strName2 As String
Dim dDate1 As Date
Dim dDate2 As Date

'Obtain the item names and dates corresponding to the
'input parameters

ListView_GetItemData lngParam1, hWnd, strName1, dDate1
ListView_GetItemData lngParam2, hWnd, strName2, dDate2

'Compare the dates
'Return 0 ==> Less Than
' 1 ==> Equal
' 2 ==> Greater Than
If Asce = False Then
If dDate1 < dDate2 Then
CompareDates = 0
ElseIf dDate1 = dDate2 Then
CompareDates = 1
Else
CompareDates = 2
End If
Else
If dDate1 > dDate2 Then
CompareDates = 0
ElseIf dDate1 = dDate2 Then
CompareDates = 1
Else
CompareDates = 2
End If

End If
End Function
'Module Functions and Procedures



'GetItemData - Given Retrieves pour date

Public Sub ListView_GetItemData(lngParam As Long, _
hWnd As Long, _
strName As String, _
dDate As Date)
Dim objFind As LV_FINDINFO
Dim lngIndex As Long
Dim objItem As LV_ITEM
Dim baBuffer(32) As Byte
Dim lngLength As Long
Dim nn
'
' Convert the input parameter to an index in the list view
'
objFind.flags = LVFI_PARAM
objFind.lParam = lngParam
lngIndex = SendMessage_b(hWnd, LVM_FINDITEM, -1,
VarPtr(objFind))

'
' Obtain the name of the specified list view item
'
'objItem.mask = LVIF_TEXT
'objItem.iSubItem = 3
'objItem.pszText = VarPtr(baBuffer(0))
'objItem.cchTextMax = UBound(baBuffer)
'lngLength = SendMessage(hWnd, LVM_GETITEMTEXT, lngIndex, _
VarPtr(objItem))
' strName = Left$(StrConv(baBuffer, vbUnicode), lngLength)
'nn = MsgBox(strName, vbDefaultButton1)
'
' Obtain the modification date of the specified list view item
'
objItem.mask = LVIF_TEXT
objItem.iSubItem = indice ' 1
objItem.pszText = VarPtr(baBuffer(0))
objItem.cchTextMax = UBound(baBuffer)
lngLength = SendMessage_b(hWnd, LVM_GETITEMTEXT, lngIndex, _
VarPtr(objItem))



If lngLength > 0 Then
dDate = CDate(Left$(StrConv(baBuffer, vbUnicode), lngLength))
End If

End Sub

'GetListItem - This is a modified version of ListView_GetItemData
' It takes an index into the list as a parameter and returns
' the appropriate values in the strName and dDate parameters.
' pour date
Public Sub ListView_GetListItem(lngIndex As Long, _
hWnd As Long, _
strName As String, _
dDate As Date)
Dim objItem As LV_ITEM
Dim baBuffer(32) As Byte
Dim lngLength As Long

'
' Obtain the name of the specified list view item
'
objItem.mask = LVIF_TEXT
objItem.iSubItem = 0
objItem.pszText = VarPtr(baBuffer(0))
objItem.cchTextMax = UBound(baBuffer)
lngLength = SendMessage_b(hWnd, LVM_GETITEMTEXT, lngIndex, _
VarPtr(objItem))
strName = Left$(StrConv(baBuffer, vbUnicode), lngLength)

'
' Obtain the modification date of the specified list view item
'
objItem.mask = LVIF_TEXT
objItem.iSubItem = 3
objItem.pszText = VarPtr(baBuffer(0))
objItem.cchTextMax = UBound(baBuffer)
lngLength = SendMessage_b(hWnd, LVM_GETITEMTEXT, lngIndex, _
VarPtr(objItem))
If lngLength > 0 Then
dDate = CDate(Left$(StrConv(baBuffer, vbUnicode), lngLength))
End If

End Sub



'Trier des valeurs numériques

Public Function CompareValeurs(ByVal lngParam1 As Long, _
ByVal lngParam2 As Long, _
ByVal hWnd As Long) As Long

Dim strName1 As String
Dim strName2 As String

'Dim strTaille1 As String
'Dim strTaille2 As String

Dim LTaille1 As Long
Dim lTaille2 As Long

'Obtain the item names and dates corresponding to the
'input parameters

ListView_GetItemDataN lngParam1, hWnd, strName1, LTaille1
ListView_GetItemDataN lngParam2, hWnd, strName2, lTaille2

'Compare the dates
'Return 0 ==> Less Than
' 1 ==> Equal
' 2 ==> Greater Than
If Asce1 = False Then
If LTaille1 < lTaille2 Then
CompareValeurs = 0
ElseIf LTaille1 = lTaille2 Then
CompareValeurs = 1
Else
CompareValeurs = 2
End If
Else
If LTaille1 > lTaille2 Then
CompareValeurs = 0
ElseIf LTaille1 = lTaille2 Then
CompareValeurs = 1
Else
CompareValeurs = 2
End If

End If
End Function
' pour valeur numérique

Public Sub ListView_GetItemDataN(lngParam As Long, _
hWnd As Long, _
strName As String, _
dTaille As Long)
Dim objFind As LV_FINDINFO
Dim lngIndex As Long
Dim objItem As LV_ITEM
Dim baBuffer(32) As Byte
Dim lngLength As Long
Dim temp As String
'
' Convert the input parameter to an index in the list view
'
objFind.flags = LVFI_PARAM
objFind.lParam = lngParam
lngIndex = SendMessage_b(hWnd, LVM_FINDITEM, -1,
VarPtr(objFind))

'
' Obtain the name of the specified list view item
'
objItem.mask = LVIF_TEXT
objItem.iSubItem = 0
objItem.pszText = VarPtr(baBuffer(0))
objItem.cchTextMax = UBound(baBuffer)
lngLength = SendMessage_b(hWnd, LVM_GETITEMTEXT, lngIndex, _
VarPtr(objItem))
strName = Left$(StrConv(baBuffer, vbUnicode), lngLength)

'
' Obtain the modification taille of the specified list view
item
'
objItem.mask = LVIF_TEXT
objItem.iSubItem = 2
objItem.pszText = VarPtr(baBuffer(0))
objItem.cchTextMax = UBound(baBuffer)
lngLength = SendMessage_b(hWnd, LVM_GETITEMTEXT, lngIndex, _
VarPtr(objItem))
If lngLength > 0 Then
temp = Left$(StrConv(baBuffer, vbUnicode), lngLength - 2)
temp = Format(temp, "##########")

dTaille = Val(temp)
End If

End Sub

'GetListItem - This is a modified version of ListView_GetItemData
' It takes an index into the list as a parameter and returns
' the appropriate values in the strName and dDate parameters.
'

Public Sub ListView_GetListItemN(lngIndex As Long, _
hWnd As Long, _
strName As String, _
dTaille As Long)
Dim objItem As LV_ITEM
Dim baBuffer(32) As Byte
Dim lngLength As Long
Dim temp As String
'
' Obtain the name of the specified list view item
'
objItem.mask = LVIF_TEXT
objItem.iSubItem = 0 ' ex 0
objItem.pszText = VarPtr(baBuffer(0))
objItem.cchTextMax = UBound(baBuffer)
lngLength = SendMessage_b(hWnd, LVM_GETITEMTEXT, lngIndex, _
VarPtr(objItem))
strName = Left$(StrConv(baBuffer, vbUnicode), lngLength)

'
' Obtain the modification taille of the specified list view
item
'
objItem.mask = LVIF_TEXT
objItem.iSubItem = 2
objItem.pszText = VarPtr(baBuffer(0))
objItem.cchTextMax = UBound(baBuffer)
lngLength = SendMessage_b(hWnd, LVM_GETITEMTEXT, lngIndex, _
VarPtr(objItem))
If lngLength > 0 Then
temp = Left$(StrConv(baBuffer, vbUnicode), lngLength - 2)
temp = Format(temp, "##########")
dTaille = Val(temp)
End If

End Sub


Function Padl(chaine, nbr, car)
Padl = String(nbr - Len(LTrim(Trim(chaine))), car) &
LTrim(Trim(chaine))
End Function
Avatar
Jacques93
Bonjour tking,
tking a écrit :
Jacques93 a exposé le 11/11/2007 :
Bonjour tking,
tking a écrit :
Hello,

Par exemple, après un tri dans un listview, visuellement l'élément
numéro 1 se retrouve en 4iem position.

Alors l'élément numéro 1 visible dans la liste n'est pas l'élément
stocké dans listview1.listitems.item(1), qui est en 4.

Du coup, l'index de la liste visible n'est pas le même que celle de
la listview.

Est-il possible de réorganiser le listview en mémoire pour le faire
correspondre à la liste visible ?





Pas tout compris, fais tu un tri des données en dehors du listview ?
Utilises tu les propriétés :

.Sorted = True
.SortKey = NumeroDeColonne
.SortOrder = lvwAscending



En fait, la liste se compose ainsi

1 - antoine
2 - françois
3 - pierre
4 - marie

Donc si j'appelle l'item 1 avec listview.item j'ai antoine, 2 françois ...

Je fais un tri, résultat à l'écran

3 - pierre
4 - marie
2 - françois
1 - marie

Si j'appelle l'item 1 j'ai comme réponse antoine, ou 2 françois... 4
marie.

Est-ce normal ?




[Couic...]

Beuh, je dirai non !

Mets une colonne de largeur = 0 (Width = 0) pour la date (AAAAMMJJ),
elle sera donc invisible, mais il faut qu'elle soit correctement
renseignée, et fait le tri sur cette colonne avec les propriétés ad'hoc.

Donc :
.Sorted = True
.SortKey = ColoneDeLaDAte
.SortOrder = lvwAscending ou lvwDescending (au choix)

Et le contrôle Listview fera le travail, en principe ...

--
Cordialement,

Jacques.
Avatar
tking
Il se trouve que Jacques93 a formulé :

Beuh, je dirai non !

Mets une colonne de largeur = 0 (Width = 0) pour la date (AAAAMMJJ), elle
sera donc invisible, mais il faut qu'elle soit correctement renseignée, et
fait le tri sur cette colonne avec les propriétés ad'hoc.

Donc :
.Sorted = True
.SortKey = ColoneDeLaDAte
.SortOrder = lvwAscending ou lvwDescending (au choix)

Et le contrôle Listview fera le travail, en principe ...



Dans mon cas, il y a la date et l'heure dans le même champs, ça donne
cela "01/10/2001 10:00:00" et le tri se gauffre.
Avatar
Jean-marc
tking wrote:
Il se trouve que Jacques93 a formulé :

Beuh, je dirai non !

Mets une colonne de largeur = 0 (Width = 0) pour la date (AAAAMMJJ),
elle sera donc invisible, mais il faut qu'elle soit correctement
renseignée, et fait le tri sur cette colonne avec les propriétés
ad'hoc. Donc :
.Sorted = True
.SortKey = ColoneDeLaDAte
.SortOrder = lvwAscending ou lvwDescending (au choix)

Et le contrôle Listview fera le travail, en principe ...



Dans mon cas, il y a la date et l'heure dans le même champs, ça donne
cela "01/10/2001 10:00:00" et le tri se gauffre.



En l'occurence le tri ne se "gauffre" pas. Le programmeur, lui, se
gauffre. Il faut rendre à Cesar ce qui est à Cesar.

Plus sérieusement :
Mauvais design => Changer design.

Au besoin créer un champ en plus qui ne servira qu'au tri.
On fixera la valeur du nouveau champ comme étant égale à la
date, mais au format AAAAMMDD, le seul qui garantisse des tris corrects.

--
Jean-marc Noury (jean_marc_n2)
Microsoft MVP - Visual Basic
FAQ VB: http://faq.vb.free.fr/
mailto: remove '_no_spam_' ;
Avatar
tking
Jean-marc a utilisé son clavier pour écrire :

En l'occurence le tri ne se "gauffre" pas. Le programmeur, lui, se
gauffre. Il faut rendre à Cesar ce qui est à Cesar.

Plus sérieusement :
Mauvais design => Changer design.

Au besoin créer un champ en plus qui ne servira qu'au tri.
On fixera la valeur du nouveau champ comme étant égale à la
date, mais au format AAAAMMDD, le seul qui garantisse des tris corrects.



L'explorateur de Windows utilise une listview et la colonne "Date de
modification" indique la date et l'heure sous le format le plus
lisible.

Ceci dit j'ai trouvé la solution pour le tri mais il y a ce bug décrit
en premier qui arrive parfois.
Avatar
Jacques93
Bonjour,
Jean-marc a écrit :
tking wrote:


[...]
En l'occurence le tri ne se "gauffre" pas. Le programmeur, lui, se
gauffre. Il faut rendre à Cesar ce qui est à Cesar.




A propos de gaufre : ne pas oublier de manger

Signé : Averell

Burp !!!

Désolé
--
Cordialement,

Jacques.
Avatar
Jacques93
Bonjour tking,
tking a écrit :
Jean-marc a utilisé son clavier pour écrire :

En l'occurence le tri ne se "gauffre" pas. Le programmeur, lui, se
gauffre. Il faut rendre à Cesar ce qui est à Cesar.

Plus sérieusement :
Mauvais design => Changer design.

Au besoin créer un champ en plus qui ne servira qu'au tri.
On fixera la valeur du nouveau champ comme étant égale à la
date, mais au format AAAAMMDD, le seul qui garantisse des tris corrects.



L'explorateur de Windows utilise une listview et la colonne "Date de
modification" indique la date et l'heure sous le format le plus lisible.

Ceci dit j'ai trouvé la solution pour le tri mais il y a ce bug décrit
en premier qui arrive parfois.




Plus sérieusement, qui te dit que l'explorateur n'utilise pas de colonne
cachée, permettant un tri correct (qui implique des données au format
Année/Mois/Jour/Heure/Minute/Secondes (sans les /)). Le contrôle
ListView le permet. Tu peux l'implémenter toi même aussi, c'est un
choix. Je n'ai pas fait de tests et ait choisi en général la première
méthode (suis fainéant).

La présentation des données est un autre aspect, sur l'événement :

ListView1_ColumnClick

tu peux savoir si l'on a cliqué sur une colonne date (au format
JJ/MM/AAAA (par exemple) et forcer le tri sur la colonne cachée (au
format AAAAMMJJ), et le tri sera correct.

--
Cordialement,

Jacques.
Avatar
parci
On Sun, 11 Nov 2007 22:06:36 +0100, "Jean-marc"
wrote:

tking wrote:
Il se trouve que Jacques93 a formulé :

Beuh, je dirai non !

Mets une colonne de largeur = 0 (Width = 0) pour la date (AAAAMMJJ),
elle sera donc invisible, mais il faut qu'elle soit correctement
renseignée, et fait le tri sur cette colonne avec les propriétés
ad'hoc. Donc :
.Sorted = True
.SortKey = ColoneDeLaDAte
.SortOrder = lvwAscending ou lvwDescending (au choix)

Et le contrôle Listview fera le travail, en principe ...



Dans mon cas, il y a la date et l'heure dans le même champs, ça donne
cela "01/10/2001 10:00:00" et le tri se gauffre.



En l'occurence le tri ne se "gauffre" pas. Le programmeur, lui, se
gauffre. Il faut rendre à Cesar ce qui est à Cesar.

Plus sérieusement :
Mauvais design => Changer design.

Au besoin créer un champ en plus qui ne servira qu'au tri.
On fixera la valeur du nouveau champ comme étant égale à la
date, mais au format AAAAMMDD, le seul qui garantisse des tris corrects.



Jean-marc,

peut-être une question de version du contrôle, parce qu'en version 5
même avec un format YYYY/MM/DD les dates ne sont pas triées
correctement par la listview. Les valeurs numériques non plus
d'aileurs.

Dans ce cas, le code de "thing" devrait fonctionner mais je ne vois
pas l'appel de la callback avec l'envoie d'un message
LVM_SORTITEMS/LVM_SORTITEMS_EX.

A voir par exemple :
http://vbnet.mvps.org/index.html?code/callback/lvsortcallback.htm
Avatar
Jacques93
Bonjour parci,
parci a écrit :
On Sun, 11 Nov 2007 22:06:36 +0100, "Jean-marc"
wrote:

tking wrote:
Il se trouve que Jacques93 a formulé :

Beuh, je dirai non !

Mets une colonne de largeur = 0 (Width = 0) pour la date (AAAAMMJJ),
elle sera donc invisible, mais il faut qu'elle soit correctement
renseignée, et fait le tri sur cette colonne avec les propriétés
ad'hoc. Donc :
.Sorted = True
.SortKey = ColoneDeLaDAte
.SortOrder = lvwAscending ou lvwDescending (au choix)

Et le contrôle Listview fera le travail, en principe ...


Dans mon cas, il y a la date et l'heure dans le même champs, ça donne
cela "01/10/2001 10:00:00" et le tri se gauffre.


En l'occurence le tri ne se "gauffre" pas. Le programmeur, lui, se
gauffre. Il faut rendre à Cesar ce qui est à Cesar.

Plus sérieusement :
Mauvais design => Changer design.

Au besoin créer un champ en plus qui ne servira qu'au tri.
On fixera la valeur du nouveau champ comme étant égale à la
date, mais au format AAAAMMDD, le seul qui garantisse des tris corrects.



Jean-marc,

peut-être une question de version du contrôle, parce qu'en version 5
même avec un format YYYY/MM/DD les dates ne sont pas triées
correctement par la listview. Les valeurs numériques non plus
d'aileurs.

Dans ce cas, le code de "thing" devrait fonctionner mais je ne vois
pas l'appel de la callback avec l'envoie d'un message
LVM_SORTITEMS/LVM_SORTITEMS_EX.

A voir par exemple :
http://vbnet.mvps.org/index.html?code/callback/lvsortcallback.htm




Essaie ce code (qui trie à l'envers). Il faut une Form, un Timer, et un
ListView bien sûr :

Option Explicit

Private Sub Form_Load()
With Me.ListView1
.View = lvwReport
.ColumnHeaders.Add , , "Visible"
.ColumnHeaders.Item(1).Width = 1800
.ColumnHeaders.Add , , "Invisible"
.ColumnHeaders.Item(2).Width = 0
.Sorted = True
.SortOrder = lvwDescending
.SortKey = 1
End With
With Me.Timer1
.Interval = 5000
.Enabled = True
End With
End Sub

Private Sub Timer1_Timer()
Dim itmX As ListItem

With Me.ListView1
Set itmX = .ListItems.Add(, , Str(Now()))
itmX.SubItems(1) = Format(Now(), "yyyymmddhhss")
.Sorted = True
.SortOrder = lvwDescending
.SortKey = 1
.Refresh
End With
End Sub

Cela me semble fonctionner en VB6, qu'en est il en VB5 ?

--
Cordialement,

Jacques.
1 2