LISTVIEW的排序方法

作者在 2008-01-14 10:56:14 发布以下内容

这种方法最方便,严重推荐

在点击数字列头的事件中,首先将数字变一下格式,将列的内容变为:format(列的内容,"000000000000"),再将listview控件的索引值设为TRUE,最后将列的内容改回来val(列的内容)。
    '在form上加listview1控件,view值设为3,加上下面一段程序
    Private Sub Form_Load()
    ListView1.ColumnHeaders.Add , , "Size"
    For i = 1 To 100
    ListView1.ListItems.Add , , Int(Rnd * 10000)
    Next
    End Sub
    
    Private Sub ListView1_ColumnClick(ByVal ColumnHeader As MSComctlLib.ColumnHeader)
    Dim i As Integer
    ListView1.SortKey = ColumnHeader.Index - 1
    
    '以下是按SIZE排序的程序
    If ColumnHeader.Text = "Size" Then
     For i = 1 To ListView1.ListItems.Count
     ListView1.ListItems(i).Text = Format(ListView1.ListItems(i).Text, "000000000000")
     Next
     If ListView1.SortOrder = lvwDescending Then
     ListView1.SortOrder = lvwAscending
     Else
     ListView1.SortOrder = lvwDescending
     End If
     ListView1.Sorted = True
     For i = 1 To ListView1.ListItems.Count
     ListView1.ListItems(i).Text = Val(ListView1.ListItems(i).Text)
     Next
    
    End If
    End Sub

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

現將LISTVIEW的排序方法整理出來共大家參考  
  排序控制加在ListView1_ColumnClick事件中,可以有3種排序方法,支持lvDate   ,       lvNumber   ,       lvBinary   ,lvAlphabetic   四種類型  
  Private   Sub   ListView1_ColumnClick(ByVal   ColumnHeader   As   ComctlLib.ColumnHeader)  
    With   ListView1  
              .SortKey   =   ColumnHeader.Index   -   1  
              .SortOrder   =   Abs(Not   .SortOrder   =   1)  
              '**********//KB   method********  
                          LVSortK   ListView1,   .SortKey,   lvDate,   .SortOrder  
              '**********//'collection   method*************  
                          LVSortC   ListView1,   .SortKey,   lvDate,   .SortOrder  
              '**************//IListView   hack   method*********************  
                          LVSortI   ListView1,   .SortKey,   lvDate,   .SortOrder  
              End   If  
        End   With  
  END   SUB  
   
  調整列寬..       Call   LVSetAllColWidths(ListView1,   LVSCW_AUTOSIZE_USEHEADER)   '可在模塊中修改參數  
   
  'LISTVIEWK控制模塊,放在標准模塊中  
   
  Option   Explicit  
   
  Private   Declare   Function   GetClientRect   Lib   "user32"   (ByVal   hWnd   As   Long,   lpRect   As   RECT)   As   Long  
  Private   Declare   Function   GetWindowRect   Lib   "user32"   (ByVal   hWnd   As   Long,   lpRect   As   RECT)   As   Long  
  Private   Declare   Function   InvalidateRect   Lib   "user32"   (ByVal   hWnd   As   Long,   lpRect   As   RECT,   ByVal   bErase   As   Long)   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   Declare   Function   SendMessageLong   Lib   "user32"   Alias   "SendMessageA"   (ByVal   hWnd   As   Long,   ByVal   wMsg   As   Long,   ByVal   wParam   As   Long,   ByVal   lParam   As   Long)   As   Long  
  Private   Declare   Sub   CopyMem   Lib   "kernel32"   Alias   "RtlMoveMemory"   (Destination   As   Any,   Source   As   Any,   ByVal   Length   As   Long)  
   
  Private   Type   POINT  
        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   Const   LVM_FIRST   As   Long   =   &H1000  
  Private   Const   LVM_GETITEM   As   Long   =   LVM_FIRST   +   5  
  Private   Const   LVM_FINDITEM   As   Long   =   LVM_FIRST   +   13  
  Private   Const   LVM_ENSUREVISIBLE   =   LVM_FIRST   +   19  
  Private   Const   LVM_SETCOLUMNWIDTH   As   Long   =   LVM_FIRST   +   30  
  Private   Const   LVM_GETTOPINDEX   =   LVM_FIRST   +   39  
  Private   Const   LVM_SETITEMSTATE   As   Long   =   LVM_FIRST   +   43  
  Private   Const   LVM_GETITEMSTATE   As   Long   =   LVM_FIRST   +   44  
  Private   Const   LVM_GETITEMTEXT   As   Long   =   LVM_FIRST   +   45  
  Private   Const   LVM_SORTITEMS   As   Long   =   LVM_FIRST   +   48  
  Private   Const   LVM_SETEXTENDEDLISTVIEWSTYLE.   As   Long   =   LVM_FIRST   +   54  
  Private   Const   LVM_GETEXTENDEDLISTVIEWSTYLE.   As   Long   =   LVM_FIRST   +   55  
  Private   Const   LVM_SETCOLUMNORDERARRAY   =   LVM_FIRST   +   58  
  Private   Const   LVM_GETCOLUMNORDERARRAY   =   LVM_FIRST   +   59  
   
  Private   Const   LVS_EX_GRIDLINES   As   Long   =   &H1  
  Private   Const   LVS_EX_SUBITEMIMAGES   As   Long   =   &H2  
  Private   Const   LVS_EX_CHECKBOXES   As   Long   =   &H4  
  Private   Const   LVS_EX_TRACKSELECT   As   Long   =   &H8  
  Private   Const   LVS_EX_HEADERDRAGDROP   As   Long   =   &H10  
  Private   Const   LVS_EX_FULLROWSELECT   As   Long   =   &H20  
   
  Private   Const   LVFI_PARAM   As   Long   =   1  
   
  Private   Const   LVIF_TEXT   As   Long   =   1  
  Private   Const   LVIF_IMAGE   As   Long   =   2  
  Private   Const   LVIF_PARAM   As   Long   =   4  
  Private   Const   LVIF_STATE   As   Long   =   8  
  Private   Const   LVIF_INDENT   As   Long   =   &H10  
  Private   Const   LVIF_NORECOMPUTE   As   Long   =   &H800  
  Private   Const   LVIS_STATEIMAGEMASK   As   Long   =   &HF000&  
   
  Private   Type   LV_ITEM  
        Mask   As   Long  
        Index   As   Long  
        SubItem   As   Long  
        State   As   Long  
        StateMask   As   Long  
        Text   As   String  
        TextMax   As   Long  
        Icon   As   Long  
        Param   As   Long  
        Indent   As   Long  
  End   Type  
   
  Private   Type   LV_FINDINFO  
        Flags   As   Long  
        pSz   As   String  
        lParam   As   Long  
        pt   As   POINT  
        vkDirection   As   Long  
  End   Type  
   
   
  '---   Array   used   to   speed   custom   sorts   ---'  
  Private   m_lvSortData()   As   LV_ITEM  
  Private   m_lvSortColl   As   Collection  
  Private   m_lvSortColumn   As   Long  
  Private   m_lvHWnd   As   Long  
  Private   m_lvSortType   As   LVItemTypes  
   
  Public   Enum   LVSCW_Styles  
        LVSCW_AUTOSIZE   =   -1  
        LVSCW_AUTOSIZE_USEHEADER   =   -2  
  End   Enum  
   
  Public   Enum   LVStylesEx  
        CheckBoxes   =   LVS_EX_CHECKBOXES  
        FullRowSelect   =   LVS_EX_FULLROWSELECT  
        GridLines   =   LVS_EX_GRIDLINES  
        HeaderDragDrop   =   LVS_EX_HEADERDRAGDROP  
        SubItemImages   =   LVS_EX_SUBITEMIMAGES  
        TrackSelect   =   LVS_EX_TRACKSELECT  
  End   Enum  
   
  Public   Enum   LVItemTypes  
        lvDate   =   0  
        lvNumber   =   1  
        lvBinary   =   2  
        lvAlphabetic   =   3  
  End   Enum  
  Public   Enum   LVSortTypes  
        lvAscending   =   0  
        lvDescending   =   1  
  End   Enum  
   
  Public   BuildLookup   As   Long  
  Public   PerformSort   As   Long  
   
  Public   Function   LVSetStyleEx(lv   As   ListView,   ByVal   NewStyle.   As   LVStylesEx,   ByVal   NewVal   As   Boolean)   As   Boolean  
        Dim   nStyle.   As   Long  
         
        nStyle.   =   SendMessage(lv.hWnd,   LVM_GETEXTENDEDLISTVIEWSTYLE,   0&,   ByVal   0&)  
         
        If   NewVal   Then  
              nStyle.   =   nStyle.   Or   NewStyle.  
        Else  
              nStyle.   =   nStyle.   Xor   NewStyle.  
        End   If  
   
        LVSetStyleEx   =   CBool(SendMessage(lv.hWnd,   LVM_SETEXTENDEDLISTVIEWSTYLE,   0&,   ByVal   nStyle))  
  End   Function  
   
  Public   Function   LVGetColOrder(lv   As   ListView)   As   Variant  
        Dim   cols()   As   Long  
        Dim   nRet   As   Long  
        With   lv  
              ReDim   cols(0   To   .ColumnHeaders.Count   -   1)   As   Long  
              nRet   =   SendMessage(.hWnd,   LVM_GETCOLUMNORDERARRAY,   .ColumnHeaders.Count,   cols(0))  
              If   nRet   Then  
                    LVGetColOrder   =   cols  
              End   If  
        End   With  
  End   Function  
   
  Public   Function   LVSetColOrder(lv   As   ListView,   cols()   As   Long)   As   Boolean  
        Dim   nRet   As   Long  
        Dim   rClient   As   RECT  
        With   lv  
              If   (UBound(cols)   +   1)   =   .ColumnHeaders.Count   Then  
                    nRet   =   SendMessage(.hWnd,   LVM_SETCOLUMNORDERARRAY,   .ColumnHeaders.Count,   cols(0))  
                    LVSetColOrder   =   CBool(nRet)  
                    Call   GetClientRect(.hWnd,   rClient)  
                    Call   InvalidateRect(.hWnd,   rClient,   True)  
              End   If  
        End   With  
  End   Function  
   
  Public   Sub   LVSetColWidth(lv   As   ListView,   ByVal   ColumnIndex   As   Long,   ByVal   Style.   As   LVSCW_Styles)  
        With   lv  
              If   .View   =   lvwReport   Then  
                    If   ColumnIndex   >=   1   And   ColumnIndex   <=   .ColumnHeaders.Count   Then  
                          Call   SendMessage(.hWnd,   LVM_SETCOLUMNWIDTH,   ColumnIndex   -   1,   ByVal   Style)  
                    End   If  
              End   If  
        End   With  
  End   Sub  
   
  Public   Sub   LVSetAllColWidths(lv   As   ListView,   ByVal   Style.   As   LVSCW_Styles)  
        Dim   ColumnIndex   As   Long  
        With   lv  
              For   ColumnIndex   =   1   To   .ColumnHeaders.Count  
                    LVSetColWidth   lv,   ColumnIndex,   Style.  
              Next   ColumnIndex  
        End   With  
  End   Sub  
   
  Public   Function   LVItemChecked(lv   As   ListView,   ByVal   Index   As   Long)   As   Boolean  
        Dim   nRet   As   Long  
        Const   MaskBit   As   Long   =   &H1000       '(2   ^   12)  
        nRet   =   SendMessage(lv.hWnd,   LVM_GETITEMSTATE,   Index   -   1,   ByVal   LVIS_STATEIMAGEMASK)  
        LVItemChecked   =   (((nRet   \   MaskBit)   -   1)   <>   0)  
  End   Function  
   
  Public   Function   LVSetItemCheck(lv   As   ListView,   ByVal   Index   As   Long,   ByVal   Value   As   Boolean)   As   Boolean  
        Dim   lvi   As   LV_ITEM  
        Index   =   Index   -   1  
        lvi.Index   =   Index  
        lvi.Mask   =   LVIF_STATE  
        lvi.StateMask   =   LVIS_STATEIMAGEMASK  
        Call   SendMessage(lv.hWnd,   LVM_GETITEM,   0&,   lvi)  
        If   Value   Then  
              lvi.State   =   (lvi.State   And   (Not   LVIS_STATEIMAGEMASK))   Or   &H2000  
        Else  
              lvi.State   =   (lvi.State   And   (Not   LVIS_STATEIMAGEMASK))   Or   &H1000  
        End   If  
        LVSetItemCheck   =   SendMessage(lv.hWnd,   LVM_SETITEMSTATE,   Index,   lvi)  
  End   Function  
   
  Public   Function   LVGetFirstVisible(lv   As   ListView)   As   Long  
        LVGetFirstVisible   =   SendMessage(lv.hWnd,   LVM_GETTOPINDEX,   0&,   ByVal   0&)  
  End   Function  
   
  Public   Function   LVEnsureVisible(lv   As   ListView,   ByVal   Index   As   Long)   As   Boolean  
        LVEnsureVisible   =   SendMessage(lv.hWnd,   LVM_ENSUREVISIBLE,   Index,   ByVal   0&)  
  End   Function  
  Public   Function   LVSortK(lv   As   ListView,   ByVal   Index   As   Long,   ByVal   ItemType   As   LVItemTypes,   ByVal   SortOrder   As   LVSortTypes)   As   Boolean  
        Dim   tmr   As   New   CStopWatch  
        With   lv  
              .Sorted   =   False  
              .SortKey   =   Index  
              .SortOrder   =   SortOrder  
        End   With  
        m_lvSortColumn   =   Index  
        m_lvSortType   =   ItemType  
        m_lvHWnd   =   lv.hWnd  
        BuildLookup   =   0  
        tmr.Reset  
        Select   Case   ItemType  
              Case   lvDate  
                    Call   SendMessageLong(lv.hWnd,   LVM_SORTITEMS,   SortOrder,   AddressOf   LVCompareDates)  
              Case   lvNumber  
                    Call   SendMessageLong(lv.hWnd,   LVM_SORTITEMS,   SortOrder,   AddressOf   LVCompareNumbers)  
        End   Select  
        PerformSort   =   tmr.Elapsed  
  End   Function  
   
  Private   Function   LVCompareDates(ByVal   lParam1   As   Long,   ByVal   lParam2   As   Long,   ByVal   SortOrder   As   Long)   As   Long  
        Static   dat1   As   Date  
        Static   dat2   As   Date  
        On   Error   Resume   Next  
        dat1   =   CDate(LVGetItemText(lParam1,   m_lvHWnd))  
        dat2   =   CDate(LVGetItemText(lParam2,   m_lvHWnd))  
        On   Error   GoTo   0  
        LVCompareDates   =   Sgn(dat1   -   dat2)  
        If   SortOrder   =   lvDescending   Then  
              LVCompareDates   =   -LVCompareDates  
        End   If  
  End   Function  
   
  Private   Function   LVCompareNumbers(ByVal   lParam1   As   Long,   ByVal   lParam2   As   Long,   ByVal   SortOrder   As   Long)   As   Long  
        Static   dat1   As   Double  
        Static   dat2   As   Double  
        On   Error   Resume   Next  
        dat1   =   CDbl(LVGetItemText(lParam1,   m_lvHWnd))  
        dat2   =   CDbl(LVGetItemText(lParam2,   m_lvHWnd))  
        On   Error   GoTo   0  
        LVCompareNumbers   =   Sgn(dat1   -   dat2)  
        If   SortOrder   =   lvDescending   Then  
              LVCompareNumbers   =   -LVCompareNumbers  
        End   If  
  End   Function  
   
  Public   Function   LVGetItemText(lParam   As   Long,   hWnd   As   Long)   As   String  
        Dim   objFind   As   LV_FINDINFO  
        Dim   Index   As   Long  
        Dim   objItem   As   LV_ITEM  
        Dim   nRet   As   Long  
        With   objFind  
              .Flags   =   LVFI_PARAM  
              .lParam   =   lParam  
        End   With  
        Index   =   SendMessage(hWnd,   LVM_FINDITEM,   -1,   objFind)  
        With   objItem  
              .Mask   =   LVIF_TEXT  
              .SubItem   =   m_lvSortColumn  
              .Text   =   Space(32)  
              .TextMax   =   Len(.Text)  
        End   With  
        nRet   =   SendMessage(hWnd,   LVM_GETITEMTEXT,   Index,   objItem)  
        If   nRet   Then  
              LVGetItemText   =   Left$(objItem.Text,   nRet)  
        End   If  
  End   Function  
  Public   Function   LVSortC(lv   As   ListView,   ByVal   Index   As   Long,   ByVal   ItemType   As   LVItemTypes,   ByVal   SortOrder   As   LVSortTypes)   As   Boolean  
        Dim   tmr   As   New   CStopWatch  
        With   lv  
              .Sorted   =   False  
              .SortKey   =   Index  
              .SortOrder   =   SortOrder  
        End   With  
        tmr.Reset  
        Call   LVPrepareSortCollection(lv,   Index,   ItemType)  
        BuildLookup   =   tmr.Elapsed  
        tmr.Reset  
        Call   SendMessageLong(lv.hWnd,   LVM_SORTITEMS,   SortOrder,   AddressOf   LVCompare)  
        PerformSort   =   tmr.Elapsed  
        Set   m_lvSortColl   =   Nothing  
  End   Function  
   
  Private   Function   LVCompare(ByVal   lParam1   As   Long,   ByVal   lParam2   As   Long,   ByVal   SortOrder   As   Long)   As   Long  
        With   m_lvSortColl  
              LVCompare   =   Sgn(.Item("k"   &   lParam1)   -   .Item("k"   &   lParam2))  
        End   With  
        If   SortOrder   =   lvDescending   Then  
              LVCompare   =   -LVCompare  
        End   If  
  End   Function  
   
  Private   Function   LVPrepareSortCollection(lv   As   ListView,   ByVal   SubItemIndex   As   Long,   ByVal   ItemType   As   LVItemTypes)   As   Boolean  
        Dim   i   As   Long,   n   As   Long  
        Dim   lvi   As   LV_ITEM  
        Dim   dat   As   Date  
        Set   m_lvSortColl   =   New   Collection  
        With   lvi  
              .Mask   =   LVIF_TEXT   Or   LVIF_PARAM  
              .SubItem   =   SubItemIndex  
              .TextMax   =   256  
              .Text   =   Space(256)  
              If   ItemType   =   lvDate   Then  
                    For   i   =   1   To   lv.ListItems.Count  
                          .Index   =   i   -   1  
                          Call   SendMessage(lv.hWnd,   LVM_GETITEM,   0&,   lvi)  
                          n   =   InStr(.Text,   vbNullChar)  
                          If   n   >   1   Then  
                                On   Error   Resume   Next  
                                      dat   =   CDate(Left$(.Text,   n   -   1))  
                                On   Error   GoTo   0  
                                m_lvSortColl.Add   dat,   "k"   &   .Param  
                          Else  
                                m_lvSortColl.Add   0,   "k"   &   .Param  
                          End   If  
                    Next   i  
              ElseIf   ItemType   =   lvNumber   Then  
                    For   i   =   1   To   lv.ListItems.Count  
                          .Index   =   i   -   1  
                          Call   SendMessage(lv.hWnd,   LVM_GETITEM,   0&,   lvi)  
                          n   =   InStr(.Text,   vbNullChar)  
                          If   n   >   1   Then  
                                m_lvSortColl.Add   CDbl(Left$(.Text,   n   -   1)),   "k"   &   .Param  
                          Else  
                                m_lvSortColl.Add   0,   "k"   &   .Param  
                          End   If  
                    Next   i  
              End   If  
        End   With  
  End   Function  
  Public   Function   LVSortI(lv   As   ListView,   ByVal   Index   As   Long,   ByVal   ItemType   As   LVItemTypes,   ByVal   SortOrder   As   LVSortTypes)   As   Boolean  
        Dim   tmr   As   New   CStopWatch  
        With   lv  
              .Sorted   =   False  
              .SortKey   =   Index  
              .SortOrder   =   SortOrder  
        End   With  
        BuildLookup   =   0  
        m_lvSortColumn   =   Index  
        m_lvSortType   =   ItemType  
        tmr.Reset  
        Call   SendMessageLong(lv.hWnd,   LVM_SORTITEMS,   SortOrder,   AddressOf   LVCompareI)  
        PerformSort   =   tmr.Elapsed  
        Set   m_lvSortColl   =   Nothing  
  End   Function  
   
  Private   Function   LVCompareI(ByVal   lParam1   As   Long,   ByVal   lParam2   As   Long,   ByVal   SortOrder   As   Long)   As   Long  
        Static   ListItem1   As   ListItem  
        Static   ListItem2   As   ListItem  
        Static   sItem1   As   String  
        Static   sItem2   As   String  
        CopyMem   ListItem1,   lParam1   +   84,   4  
        CopyMem   ListItem2,   lParam2   +   84,   4  
        If   m_lvSortColumn   =   0   Then  
              sItem1   =   ListItem1.Text  
              sItem2   =   ListItem2.Text  
        Else  
              sItem1   =   ListItem1.SubItems(m_lvSortColumn)  
              sItem2   =   ListItem2.SubItems(m_lvSortColumn)  
        End   If  
        CopyMem   ListItem1,   Nothing,   4  
        CopyMem   ListItem2,   Nothing,   4  
        On   Error   GoTo   Failure  
              Select   Case   m_lvSortType  
                    Case   lvDate  
                          LVCompareI   =   Sgn(CDate(sItem1)   -   CDate(sItem2))  
                    Case   lvNumber  
                          LVCompareI   =   Sgn(CDbl(sItem1)   -   CDbl(sItem2))  
                    Case   lvBinary  
                          LVCompareI   =   StrComp(sItem1,   sItem2,   vbBinaryCompare)  
                    Case   lvAlphabetic  
                          LVCompareI   =   StrComp(sItem1,   sItem2,   vbTextCompare)  
                    Case   Else  
                          LVCompareI   =   StrComp(sItem1,   sItem2,   vbTextCompare)  
              End   Select  
        On   Error   GoTo   0  
        If   SortOrder   =   lvDescending   Then  
              LVCompareI   =   -LVCompareI  
        End   If  
        Exit   Function  
  Failure:  
        Exit   Function  
  End   Function

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

还有一篇MSDN的

http://support.microsoft.com/kb/q170884/

VB | 阅读 4082 次
文章评论,共0条
游客请输入验证码