Sign in to follow this  
Followers 0
crystalburner

Guilistview (Gary Frost!)

16 posts in this topic

Hi

A while ago i was told if i wanted some of my list items to be coloured i had to use listview.

I'm adding the listview items to the list like this

$item1=GuiCtrlCreateListViewItem($listitems[7] & ' #1' &  '|'  & $listitems[1] & ' ' & $listitems[2] & ' ' & $listitems[3] & '|' & $filelist[$pos][6]& '|' & $filelist[$pos][7] & '|' & $filelist[$pos][1] & '|' & $filelist[$pos][2] & '|' & $filelist[$pos][3] & '|' & $filelist[$pos][4] & '|' & $filelist[$pos][5] & '|' & $pos,$invoicelist)
GUICtrlSetColor($item1,0x0000ff)

This process is repeated a few times until i have several list items different colours

No problem

BUT!

When you sort the listview by clicking a column, the items move around in the list fine, but they dont take their colours, instead it looks like im colouring positions in the list view and not the items themselves.

I think Gary Frost is my man here?

C

Share this post


Link to post
Share on other sites



; *******************************************************
; Example 1 - sorting 3 column's different
; *******************************************************

#include <GUIConstants.au3>

;Global Const $LVFI_PARAM           = 0x0001
;Global Const $LVIF_TEXT                = 0x0001
;Global Const $LVM_FIRST                = 0x1000
Global Const $LVM_GETITEM           = $LVM_FIRST + 5
Global Const $LVM_FINDITEM          = $LVM_FIRST + 13
;Global Const $LVM_SETSELECTEDCOLUMN    = $LVM_FIRST + 140

Dim $nCurCol    = -1
Dim $nSortDir   = 1
Dim $bSet       = 0
Dim $nCol       = -1

$hGUI   = GUICreate("Test", 300, 200)

$lv     = GUICtrlCreateListView("Column1|Col2|Col3", 10, 10, 280, 180)
GUICtrlRegisterListViewSort(-1, "LVSort") ; Register the function "SortLV" for the sorting callback

$lvi1   = GUICtrlCreateListViewItem("ABC|666|10.05.2004", $lv)
GUICtrlSetImage(-1, "shell32.dll", 7)
GUICtrlSetColor(-1,0x0000ff) 
$lvi2   = GUICtrlCreateListViewItem("DEF|444|11.05.2005", $lv)
GUICtrlSetImage(-1, "shell32.dll", 12)
GUICtrlSetColor(-1,0xff0000) 
$lvi3   = GUICtrlCreateListViewItem("CDE|444|12.05.2004", $lv)
GUICtrlSetImage(-1, "shell32.dll", 3)

GUISetState()

While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $GUI_EVENT_CLOSE
            ExitLoop
            
        Case $lv
            $bSet = 0
            $nCurCol = $nCol
            GUICtrlSendMsg($lv, $LVM_SETSELECTEDCOLUMN, GUICtrlGetState($lv), 0)
            DllCall("user32.dll", "int", "InvalidateRect", "hwnd", GUICtrlGetHandle($lv), "int", 0, "int", 1)
    EndSwitch
WEnd

Exit


; Our sorting callback funtion
Func LVSort($hWnd, $nItem1, $nItem2, $nColumn)
    Local $nSort
    
    ; Switch the sorting direction
    If $nColumn = $nCurCol Then
        If Not $bSet Then
            $nSortDir = $nSortDir * -1
            $bSet = 1
        EndIf
    Else
        $nSortDir = 1
    EndIf
    $nCol = $nColumn
        
    $val1   = GetSubItemText($lv, $nItem1, $nColumn)
    $val2   = GetSubItemText($lv, $nItem2, $nColumn)
    
    ; If it is the 3rd colum (column starts with 0) then compare the dates
    If $nColumn = 2 Then
        $val1 = StringRight($val1, 4) & StringMid($val1, 4, 2) & StringLeft($val1, 2)
        $val2 = StringRight($val2, 4) & StringMid($val2, 4, 2) & StringLeft($val2, 2)
    EndIf
        
    $nResult = 0        ; No change of item1 and item2 positions
    
    If $val1 < $val2 Then
        $nResult = -1   ; Put item2 before item1
    ElseIf  $val1 > $val2 Then
        $nResult = 1    ; Put item2 behind item1
    EndIf

    $nResult = $nResult * $nSortDir
    
    Return $nResult
EndFunc


; Retrieve the text of a listview item in a specified column
Func GetSubItemText($nCtrlID, $nItemID, $nColumn)
    Local $stLvfi       = DllStructCreate("uint;ptr;int;int[2];int")
    DllStructSetData($stLvfi, 1, $LVFI_PARAM)
    DllStructSetData($stLvfi, 3, $nItemID)

    Local $stBuffer     = DllStructCreate("char[260]")
    
    $nIndex = GUICtrlSendMsg($nCtrlID, $LVM_FINDITEM, -1, DllStructGetPtr($stLvfi));
    
    Local $stLvi        = DllStructCreate("uint;int;int;uint;uint;ptr;int;int;int;int")
    
    DllStructSetData($stLvi, 1, $LVIF_TEXT)
    DllStructSetData($stLvi, 2, $nIndex)
    DllStructSetData($stLvi, 3, $nColumn)
    DllStructSetData($stLvi, 6, DllStructGetPtr($stBuffer))
    DllStructSetData($stLvi, 7, 260)

    GUICtrlSendMsg($nCtrlID, $LVM_GETITEM, 0, DllStructGetPtr($stLvi));

    $sItemText  = DllStructGetData($stBuffer, 1)

    $stLvi      = 0
    $stLvfi     = 0
    $stBuffer   = 0
    
    Return $sItemText
EndFunc


SciTE for AutoItDirections for Submitting Standard UDFs

 

Don't argue with an idiot; people watching may not be able to tell the difference.

 

Share this post


Link to post
Share on other sites

Ok i'll play thanks!

Am i right in saying there is no substitute for this

$ret1 = _GUICtrlListFindString ($invoicelist, '778')

in listview?

to get the index of a line with certain text?

Share this post


Link to post
Share on other sites

Ok i'll play thanks!

Am i right in saying there is no substitute for this

$ret1 = _GUICtrlListFindString ($invoicelist, '778')

in listview?

to get the index of a line with certain text?

Not one written, maybe LVM_FINDITEM if your want to do it programitically

If I get time if someone doesn't beat me to it i'll look at making one.


SciTE for AutoItDirections for Submitting Standard UDFs

 

Don't argue with an idiot; people watching may not be able to tell the difference.

 

Share this post


Link to post
Share on other sites

Quick and dirty

; *******************************************************
; Example 1 - sorting 3 column's different
; *******************************************************

#include <GUIConstants.au3>
#include <GuiListView.au3>

;Global Const $LVFI_PARAM           = 0x0001
;Global Const $LVIF_TEXT                = 0x0001
;Global Const $LVM_FIRST                = 0x1000
Global Const $LVM_GETITEM = $LVM_FIRST + 5
Global Const $LVM_FINDITEM = $LVM_FIRST + 13
;Global Const $LVM_SETSELECTEDCOLUMN    = $LVM_FIRST + 140

Global Const $LVFI_PARTIAL = 0x8
Global Const $LVFI_STRING = 0x2
Global Const $LVFI_WRAP = 0x20

Global Const $VK_LEFT = 0x25
Global Const $VK_RIGHT = 0x27
Global Const $VK_UP = 0x26
Global Const $VK_DOWN = 0x28
Global Const $VK_END = 0x23
Global Const $VK_PRIOR = 0x21
Global Const $VK_NEXT = 0x22

Dim $nCurCol = -1
Dim $nSortDir = 1
Dim $bSet = 0
Dim $nCol = -1

$hGUI = GUICreate("Test", 300, 400)

$lv = GUICtrlCreateListView("Column1|Col2|Col3", 10, 10, 280, 180)
GUICtrlRegisterListViewSort(-1, "LVSort") ; Register the function "SortLV" for the sorting callback

$lvi1 = GUICtrlCreateListViewItem("ABC|666|10.05.2004", $lv)
GUICtrlSetImage(-1, "shell32.dll", 7)
GUICtrlSetColor(-1, 0x0000ff)
$lvi2 = GUICtrlCreateListViewItem("DEF|444|11.05.2005", $lv)
GUICtrlSetImage(-1, "shell32.dll", 12)
GUICtrlSetColor(-1, 0xff0000)
$lvi3 = GUICtrlCreateListViewItem("CDE|444|12.05.2004", $lv)
GUICtrlSetImage(-1, "shell32.dll", 3)
$input = GUICtrlCreateInput("", 10, 200, 90, 20)
$btn = GUICtrlCreateButton("Find", 100, 200, 50, 20)
GUISetState()

While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $GUI_EVENT_CLOSE
            ExitLoop

        Case $lv
            $bSet = 0
            $nCurCol = $nCol
            GUICtrlSendMsg($lv, $LVM_SETSELECTEDCOLUMN, GUICtrlGetState($lv), 0)
            DllCall("user32.dll", "int", "InvalidateRect", "hwnd", GUICtrlGetHandle($lv), "int", 0, "int", 1)
            
        Case $btn
            If StringLen(GUICtrlRead($input)) Then
                MsgBox(0, "Find Item", _
                        _GUICtrlListViewFindItem($lv, GUICtrlRead($input), _
                        _GUICtrlListViewGetSelectedIndices($lv), BitOR($LVFI_PARTIAL, $LVFI_WRAP)))
            EndIf
    EndSwitch
WEnd

Exit


; Our sorting callback funtion
Func LVSort($hWnd, $nItem1, $nItem2, $nColumn)
    Local $nSort

    ; Switch the sorting direction
    If $nColumn = $nCurCol Then
        If Not $bSet Then
            $nSortDir = $nSortDir * - 1
            $bSet = 1
        EndIf
    Else
        $nSortDir = 1
    EndIf
    $nCol = $nColumn

    $val1 = GetSubItemText($lv, $nItem1, $nColumn)
    $val2 = GetSubItemText($lv, $nItem2, $nColumn)

    ; If it is the 3rd colum (column starts with 0) then compare the dates
    If $nColumn = 2 Then
        $val1 = StringRight($val1, 4) & StringMid($val1, 4, 2) & StringLeft($val1, 2)
        $val2 = StringRight($val2, 4) & StringMid($val2, 4, 2) & StringLeft($val2, 2)
    EndIf

    $nResult = 0        ; No change of item1 and item2 positions

    If $val1 < $val2 Then
        $nResult = -1   ; Put item2 before item1
    ElseIf $val1 > $val2 Then
        $nResult = 1    ; Put item2 behind item1
    EndIf

    $nResult = $nResult * $nSortDir

    Return $nResult
EndFunc   ;==>LVSort


; Retrieve the text of a listview item in a specified column
Func GetSubItemText($nCtrlID, $nItemID, $nColumn)
    Local $stLvfi = DllStructCreate("uint;ptr;int;int[2];int")
    DllStructSetData($stLvfi, 1, $LVFI_PARAM)
    DllStructSetData($stLvfi, 3, $nItemID)

    Local $stBuffer = DllStructCreate("char[260]")

    $nIndex = GUICtrlSendMsg($nCtrlID, $LVM_FINDITEM, -1, DllStructGetPtr($stLvfi));

    Local $stLvi = DllStructCreate("uint;int;int;uint;uint;ptr;int;int;int;int")

    DllStructSetData($stLvi, 1, $LVIF_TEXT)
    DllStructSetData($stLvi, 2, $nIndex)
    DllStructSetData($stLvi, 3, $nColumn)
    DllStructSetData($stLvi, 6, DllStructGetPtr($stBuffer))
    DllStructSetData($stLvi, 7, 260)

    GUICtrlSendMsg($nCtrlID, $LVM_GETITEM, 0, DllStructGetPtr($stLvi));

    $sItemText = DllStructGetData($stBuffer, 1)

    $stLvi = 0
    $stLvfi = 0
    $stBuffer = 0

    Return $sItemText
EndFunc   ;==>GetSubItemText

;===============================================================================
;
; Description:          _GUICtrlListViewEnsureVisible
; Parameter(s):     $h_listview     - controlID
;                           $s_Text         - Text to search for
;                           $i_Start            - Index of the item to begin the search with or -1 to start from the beginning.
;                                                   The specified item is itself excluded from the search. (Optional: Default -1)
;                           $v_SearchType   - Type of search to perform (See Notes)
;                           $v_direction    - Virtual key code that specifies the direction to search (See Notes)
; Requirement:          None
; Return Value(s):  Returns index if successful, or -1 otherwise
; User CallTip:     _GUICtrlListViewFindItem($h_listview, $s_Text[, $i_Start = -1[, $v_SearchType = 0x8[, $v_direction = 0x28]]]) Searches for a list-view item (required: <GuiListView.au3>)
; Author(s):            Gary Frost (custompcs at charter dot net)
; Note(s):
;   $v_SearchType:
;       $LVFI_PARTIAL (Default)
;           Checks to see if the item text begins with the string pointed to by the psz member.
;           This value implies use of $LVFI_STRING.
;       $LVFI_STRING
;           Searches based on the item text.
;           Unless additional values are specified, the item text of the matching item must exactly
;           match the string pointed to by the psz member. However, the search is case-insensitive.
;       $LVFI_WRAP
;           Continues the search at the beginning if no match is found
;
;   $v_direction
;       $VK_LEFT
;       $VK_RIGHT
;       $VK_UP
;       $VK_DOWN
;       $VK_HOME
;       $VK_END
;===============================================================================
Func _GUICtrlListViewFindItem($h_listview, $s_Text, $i_Start = -1, $v_SearchType = 0x8, $v_direction = 0x28)
    $s_struct = DllStructCreate("char[" & StringLen($s_Text) + 1 & "]")
    DllStructSetData($s_struct, 1, $s_Text)
    $struct = DllStructCreate("uint;ptr;int;int[2];int")
    If @error Then Return SetError($LV_ERR, $LV_ERR, $LV_ERR)
    DllStructSetData($struct, 1, $v_SearchType)
    DllStructSetData($struct, 2, DllStructGetPtr($s_struct))
    DllStructSetData($struct, 6, $v_direction)

    If IsHWnd($h_listview) Then
        Local $a_ret = DllCall("user32.dll", "int", "SendMessage", "hwnd", $h_listview, "int", $LVM_FINDITEM, "int", $i_Start, "ptr", DllStructGetPtr($struct))
        Return $a_ret[0]
    Else
        Return GUICtrlSendMsg($h_listview, $LVM_FINDITEM, $i_Start, DllStructGetPtr($struct))
    EndIf
EndFunc   ;==>_GUICtrlListViewFindItem

SciTE for AutoItDirections for Submitting Standard UDFs

 

Don't argue with an idiot; people watching may not be able to tell the difference.

 

Share this post


Link to post
Share on other sites

nothing ever simple is it!

anyway, i was using the listview sort exactly as in the help file and it was shite slow it took 15 seconds to sort a 15 line list.

Now im using this one you wrote mr Frost its bugger fast! Instant!

Great!

Share this post


Link to post
Share on other sites

nothing ever simple is it!

anyway, i was using the listview sort exactly as in the help file and it was shite slow it took 15 seconds to sort a 15 line list.

Now im using this one you wrote mr Frost its bugger fast! Instant!

Great!

Actually the _GUICtrlListViewSort was written by me long before the built-in function GUICtrlRegisterListViewSort was added in by Holger I believe

I've tried to get the devs to remove the old function, but they say GUICtrlRegisterListViewSort is too complex for many users and the old one is easy to use even tho it is a "Simple" sort.


SciTE for AutoItDirections for Submitting Standard UDFs

 

Don't argue with an idiot; people watching may not be able to tell the difference.

 

Share this post


Link to post
Share on other sites

How do I just run the func without actually clicking on a column header?

say to sort by column 0

Share this post


Link to post
Share on other sites

How do I just run the func without actually clicking on a column header?

say to sort by column 0

i've been playing with this as well

GUICtrlSendMsg($invoicelist, WM_LBUTTONDBLCLK, GUICtrlGetState($invoicelist), 0)

Share this post


Link to post
Share on other sites

How do I just run the func without actually clicking on a column header?

say to sort by column 0

I too would like to do this, sort it first so it is already kind of pre-sorted by the first column automatically.

Share this post


Link to post
Share on other sites

; *******************************************************
; Example 1 - sorting 3 column's different
; *******************************************************

#include <GUIConstants.au3>

;Global Const $LVFI_PARAM           = 0x0001
;Global Const $LVIF_TEXT                = 0x0001
;Global Const $LVM_FIRST                = 0x1000
Global Const $LVM_GETITEM = $LVM_FIRST + 5
Global Const $LVM_FINDITEM = $LVM_FIRST + 13
;Global Const $LVM_SETSELECTEDCOLUMN    = $LVM_FIRST + 140

Dim $nCurCol = -1
Dim $nSortDir = 1
Dim $bSet = 0
Dim $nCol = -1

$hGUI = GUICreate("Test", 300, 200)

;*********************************************************************************
$lv = GUICtrlCreateListView("Column1|Col2|Col3", 10, 10, 280, 180)
GUICtrlSetStyle($lv, $LVS_SORTASCENDING) ; sort ascending on 1st column
;*********************************************************************************
GUICtrlSendMsg($lv, $LVM_SETEXTENDEDLISTVIEWSTYLE, $LVS_EX_GRIDLINES, $LVS_EX_GRIDLINES)
GUICtrlSendMsg($lv, $LVM_SETEXTENDEDLISTVIEWSTYLE, $LVS_EX_FULLROWSELECT, $LVS_EX_FULLROWSELECT)

$lvi1 = GUICtrlCreateListViewItem("ABC|666|10.05.2004", $lv)
GUICtrlSetImage(-1, "shell32.dll", 7)
GUICtrlSetColor(-1, 0x0000ff)
$lvi2 = GUICtrlCreateListViewItem("DEF|444|11.05.2005", $lv)
GUICtrlSetImage(-1, "shell32.dll", 12)
GUICtrlSetColor(-1, 0xff0000)
$lvi3 = GUICtrlCreateListViewItem("CDE|444|12.05.2004", $lv)
GUICtrlSetImage(-1, "shell32.dll", 3)
;*********************************************************************************
GUICtrlSetStyle($lv, BitOR($LVS_SHOWSELALWAYS, $LVS_SINGLESEL, $LVS_REPORT)) ; turn off sorting
GUICtrlRegisterListViewSort($lv, "LVSort") ; Register the function "SortLV" for the sorting callback
;*********************************************************************************

GUISetState()

While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $GUI_EVENT_CLOSE
            ExitLoop

        Case $lv
            $bSet = 0
            $nCurCol = $nCol
            GUICtrlSendMsg($lv, $LVM_SETSELECTEDCOLUMN, GUICtrlGetState($lv), 0)
            DllCall("user32.dll", "int", "InvalidateRect", "hwnd", GUICtrlGetHandle($lv), "int", 0, "int", 1)
    EndSwitch
WEnd

Exit


; Our sorting callback funtion
Func LVSort($hWnd, $nItem1, $nItem2, $nColumn)
    Local $nSort

    ; Switch the sorting direction
    If $nColumn = $nCurCol Then
        If Not $bSet Then
            $nSortDir = $nSortDir * - 1
            $bSet = 1
        EndIf
    Else
        $nSortDir = 1
    EndIf
    $nCol = $nColumn

    $val1 = GetSubItemText($lv, $nItem1, $nColumn)
    $val2 = GetSubItemText($lv, $nItem2, $nColumn)

    ; If it is the 3rd colum (column starts with 0) then compare the dates
    If $nColumn = 2 Then
        $val1 = StringRight($val1, 4) & StringMid($val1, 4, 2) & StringLeft($val1, 2)
        $val2 = StringRight($val2, 4) & StringMid($val2, 4, 2) & StringLeft($val2, 2)
    EndIf

    $nResult = 0        ; No change of item1 and item2 positions

    If $val1 < $val2 Then
        $nResult = -1   ; Put item2 before item1
    ElseIf $val1 > $val2 Then
        $nResult = 1    ; Put item2 behind item1
    EndIf

    $nResult = $nResult * $nSortDir

    Return $nResult
EndFunc   ;==>LVSort


; Retrieve the text of a listview item in a specified column
Func GetSubItemText($nCtrlID, $nItemID, $nColumn)
    Local $stLvfi = DllStructCreate("uint;ptr;int;int[2];int")
    DllStructSetData($stLvfi, 1, $LVFI_PARAM)
    DllStructSetData($stLvfi, 3, $nItemID)

    Local $stBuffer = DllStructCreate("char[260]")

    $nIndex = GUICtrlSendMsg($nCtrlID, $LVM_FINDITEM, -1, DllStructGetPtr($stLvfi));

    Local $stLvi = DllStructCreate("uint;int;int;uint;uint;ptr;int;int;int;int")

    DllStructSetData($stLvi, 1, $LVIF_TEXT)
    DllStructSetData($stLvi, 2, $nIndex)
    DllStructSetData($stLvi, 3, $nColumn)
    DllStructSetData($stLvi, 6, DllStructGetPtr($stBuffer))
    DllStructSetData($stLvi, 7, 260)

    GUICtrlSendMsg($nCtrlID, $LVM_GETITEM, 0, DllStructGetPtr($stLvi));

    $sItemText = DllStructGetData($stBuffer, 1)

    $stLvi = 0
    $stLvfi = 0
    $stBuffer = 0

    Return $sItemText
EndFunc   ;==>GetSubItemText


SciTE for AutoItDirections for Submitting Standard UDFs

 

Don't argue with an idiot; people watching may not be able to tell the difference.

 

Share this post


Link to post
Share on other sites

Thanks :lmao:

Me too Gary thank you

Share this post


Link to post
Share on other sites

Me too Gary thank you

what else changed to sort it automatically other than this line

GUICtrlSetStyle($lv, $LVS_SORTASCENDING); sort ascending on 1st column

Share this post


Link to post
Share on other sites

what else changed to sort it automatically other than this line

GUICtrlSetStyle($lv, $LVS_SORTASCENDING); sort ascending on 1st column

just look for

;*********************************************************************************

SciTE for AutoItDirections for Submitting Standard UDFs

 

Don't argue with an idiot; people watching may not be able to tell the difference.

 

Share this post


Link to post
Share on other sites

bringing back this thread from the dead. someone care to explain how SetStle sorted on first column ? Basically i wanna sort on col2.

[P.S: amazing code)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0