Sign in to follow this  
Followers 0
Zaxon

Triggering an initial column click

7 posts in this topic

I'm using GUICtrlRegisterListViewSort to take care of listview sorting, which is working well.

Now, I want to initially sort the listview when the script is first run. However, I'm unable to simulate a click on a column heading to cause the fist sort.

Here is a simple, sample script which let's you know when the registered listview sort callback function has been activated. It works properly if you click on a column, but I'm not able to simulate the click.

#include <GUIConstants.au3>

Global Const $LVN_FIRST = -100 ; correct?
Global Const $LVN_COLUMNCLICK = $LVN_FIRST - 8 ; correct?


$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)
$lvi2   = GUICtrlCreateListViewItem("DEF|444|11.05.2005", $lv)
GUICtrlSetImage(-1, "shell32.dll", 12)
$lvi3   = GUICtrlCreateListViewItem("CDE|444|12.05.2004", $lv)
GUICtrlSetImage(-1, "shell32.dll", 3)

GUISetState()

; trigger an initial sort on the table
GUICtrlSendMsg($lv, $LVN_COLUMNCLICK, 1, 0) ; <= doesn't work

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

Exit


; Our sorting callback funtion
Func LVSort($hWnd, $nItem1, $nItem2, $nColumn)
    msgbox(0,"","Hey! I'm sorting column: "&$nColumn)
    exit
EndFunc

It should be quite simple, I'd expect, for someone to correct the script. I've shown an "almost working" example, which I've constructed from the fruits of my research. Can you fill in the last change to make this work?

Share this post


Link to post
Share on other sites



Can someone confirm I'm on the right track? This message slipped back to page 5 within the first 24 hours, so perhaps there are those who know the answer, but my post has slipped under the radar.

Share this post


Link to post
Share on other sites

GUICtrlSendMsg($lv, $LVN_COLUMNCLICK, 1, 0) ; <= doesn't work

LVN_COLUMNCLICK is a notification not a message to send

this should work for you

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

#include <GUIConstants.au3>

Global Const $LVFI_PARAM = 0x0001
Global Const $LVM_GETITEM = $LVM_FIRST + 5
Global Const $LVM_FINDITEM = $LVM_FIRST + 13

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
$lvi1 = GUICtrlCreateListViewItem("ABC|666|10.05.2004", $lv)
GUICtrlSetImage(-1, "shell32.dll", 7)
$lvi2 = GUICtrlCreateListViewItem("DEF|444|11.05.2005", $lv)
GUICtrlSetImage(-1, "shell32.dll", 12)
$lvi3 = GUICtrlCreateListViewItem("CDE|444|12.05.2004", $lv)
GUICtrlSetImage(-1, "shell32.dll", 3)

GUISetState()
GUICtrlSetStyle($lv, BitOR($LVS_SHOWSELALWAYS, $LVS_SINGLESEL, $LVS_REPORT)) ; turn off sorting
GUICtrlRegisterListViewSort($lv, "LVSort") ; Register the function "SortLV" for the sorting callback
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

LVN_COLUMNCLICK is a notification not a message to send

Ah! That explains why I wasn't getting anywhere.

this should work for you

; *******************************************************
; Example 1 - sorting 3 column's different
; *******************************************************
Ah! I've already got that part covered. But thanks anyway.

The part I'm missing, and I'm sure you'll be able to help me out seeing that you've got a good knowledge of the area, is to programatically initially sort the columns. That's step 3 from the sequence below. So the sequence goes like this:

1. Create the ListView

2. Populate the listview

3. Cause an initial sort on a column of the code's choice by GUICtrlSendMsg (simulating someone clicking on a column) <= this part is needed

4. Hang around and process any sort requests that come through.

So I'm wanting the code to initially sort the listview before handling over the listview to the user.

Share this post


Link to post
Share on other sites

OK. This is turning out to be a very long wait for a solution - it's about 12 days since I first asked the question.

Should I assume that not many people are familiar with sending messages to GUI objects?

Share this post


Link to post
Share on other sites

OK. This is turning out to be a very long wait for a solution - it's about 12 days since I first asked the question.

Should I assume that not many people are familiar with sending messages to GUI objects?

Do what you will with your assumptions... a better one would be "Most of us have full time jobs, families, friends, projects, etc..."

Get the latest beta, include GuiListView.au3, and slap this above your message loop:

Dim $B_DESCENDING[_GUICtrlListViewGetSubItemsCount ($lv) ]
_GUICtrlListViewSort($lv,  $B_DESCENDING, 1)

[font="Tahoma"]"Tougher than the toughies and smarter than the smarties"[/font]

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

Get the latest beta, include GuiListView.au3, and slap this above your message loop:

Dim $B_DESCENDING[_GUICtrlListViewGetSubItemsCount ($lv) ]
_GUICtrlListViewSort($lv,  $B_DESCENDING, 1)
I'm familiar with that sorting UDF. In fact, my present application code was based on that function, but a few beta's ago that function was slowed down and is now unuseable for me. It takes 8 seconds to sort a very modest listview. No user is prepared to wait 8 seconds just to display one list view. I created a minimalistic test script that did nothing but create a listview and sort it, and it came in at about 6.5 seconds. There's another script in the scripts and scraps section that claims to be 20x faster, that comes in at about 6.5 seconds.

However, sorting via the registered function takes about .5 seconds. So you can see why I'm insisting on making use of that functionality. All I need to do is to programmatically trigger that sort. Presently I don't know how to do that: hence the purpose of this thread. But I'm sure it's simple, and there are a few people on this forum who I'm sure know how to do that.

My alternate strategy is to presort the data in an array and then populate the listview from that. Much quicker than _GUICtrlListViewSort I'm sure. But seeing that I've already got the code in to cater for the registered sort, I thought I would hang out for the "programmatic click" functionality to show up.

Edited by Zaxon

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