Jump to content
Sign in to follow this  
JohnBailey

Activate sorting using GUICtrlRegisterListViewSort without mouse

Recommended Posts

JohnBailey

#330184

Primarily, I'm trying to figure out how to do the sort on initialization of the GUI. I'm not asking for you to write the script (because I don't want you to). I want to learn this, but I'm stuck!

#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

$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)
$lvi1   = GUICtrlCreateListViewItem("ABC|666|10.05.2004", $lv)
GUICtrlSetImage(-1, "shell32.dll", 7)

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
   sort() ;<--- just an idea
WEnd

Func sort()
    $bSet = 0
    $nCurCol = $nCol
    GUICtrlSendMsg($lv, $LVM_SETSELECTEDCOLUMN, 0, 0)
    DllCall("user32.dll", "int", "InvalidateRect", "hwnd", GUICtrlGetHandle($lv), "int", 0, "int", 1)
    LVSort($lv,4,6,0)
    $bSet = 0
    $nCurCol = $nCol
    GUICtrlSendMsg($lv, $LVM_SETSELECTEDCOLUMN, 0, 0)
    DllCall("user32.dll", "int", "InvalidateRect", "hwnd", GUICtrlGetHandle($lv), "int", 0, "int", 1)
    LVSort($lv,6,4,0)
EndFunc


; 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
Edited by JohnBailey

A decision is a powerful thing

Share this post


Link to post
Share on other sites
Holger

You can send an "LVN_COLUMNCLICK" notification within a "WM_NOTIFY" message directly to the GUI.

http://msdn2.microsoft.com/en-us/library/ms930204.aspx

You have to build a NMLISTVIEW-struct and fill in the members with the proper values.

If you need any further detailed help just post it.

Share this post


Link to post
Share on other sites
JohnBailey

you are my hero! :( Thank you! Wondeful idea. I look into it and begin testing, and post any more Qs I have. I'm excited now that I have a direction and I'm not just taking wild guesses. :shocked:


A decision is a powerful thing

Share this post


Link to post
Share on other sites
Zedna

I'm trying to do the same but no luck.

It's sorting OK after click on first column but _SendMessage() with WM_NOTIFY and LVN_COLUMNCLICK do nothing.

Can somebody help me with this?

Here is my small testing script for WM_NOTIFY and LVN_COLUMNCLICK

I'm trying to have sorting by first column at start.

#NoTrayIcon 
#include <GUIConstants.au3>
#include <Misc.au3>[ÛÛÝ  ÌÍÓWÑÑUUSHH    ÌÍÓWÑTÕ
È
BÛØ[ÛÛÝ    ÌÍÕÓWÓDeÒDP¤vÆö&Â6öç7Bb33c´Ådåô4ôÅTÔä4Ä4²Òdddddc@ ¢b33c´f÷&ÓU%
ÉÑ ÅÕ½ÐíQÍÐͽÉÐÅÕ½Ðì°ÐÜÔ°ÐÀÀ°´Ä°´Ä¤(ÀÌØí1¥ÍÑY¥ÜÄôU%
ÑlCreateListView("Column 1|Column 2|Column 3", 8, 8, 458, 364, BitÔ   ÌÍÓ×ÔTÔ   ÌÍÓ×ÔÒSÓTÑS ÌÍÓ×ÔÒÕÔÑSSÐVTË  ÌÍÕÔ×ÒÐ$ôÄÂÂb33cµu5õe45$ôÄÂÂb33cµu5ô$õ$DU"Â&Dõ"b33cµu5ôUô4ÄTåDTDtRÂb33c´YM}a}
!
-   =aL°ÀÌØí1YM}a}U11I=]M1
P¤¤)U%
Ñɱ
ÉÑ1¥ÍÑY¥Ý%Ñ´ ÅÕt;c1|c2|c3",$ListView1)
GUICtrlCreateListViewItem("a1|a2|a3&][ÝË  ÌÍÓÝY]ÌJBÕRPÝÜX]SÝY]Ò][J  ][ÝØ_É][ÝË ÌÍÆ7EfWs ¤uT6WE7FFR5uõ4õrÂb33c´f÷&Ó¤uT7G&Å&Vv7FW$Æ7EfWu6÷'BÀÌØí1¥ÍÑY¥ÜÄ°ÅÕ½Ðí1YM½ÉÐÅÕ½Ðì¤((ìÐÍÑÉÐ¥¹¥Ñ¥ÑͽÉÐä¥ÉÍн±Õn
;~ $struct_NMLISTVIEW = DllStructCreate("int;int;int;int;int;uiÝZ[ÝZ[Ú[Ú[Ú[    ][ÝÊBÌÍÜÝXÝÓSTÕQUÈHÝXÝÜX]J V÷C¶væC·VçC·VçC¶çC¶çC·VçC·VçC·VçC¶çC¶çC¶çBgV÷C²¤FÆÅ7G'V7E6WDF ÀÌØíÍÑÉÕÑ}951%MQY%°Ä°ÀÌØí½É´Ä¤)±±MÑÉÕÑMÑÑ ÀÌØíÍÑÉÕÑ}951%TVIEW,2,$ListView1)
DllStructSetData($struct_NMLISTVIEW,3,$LÐÓÓSSÓPÒÊBÝXÝÙ]]J  ÌÍÜÝXÝÓSTÕQUË
LJHÈ][HHLBÆÅ7G'V7E6WDFFb33c·7G'V7EôäÔÄ5EdUrÃRò7V&FVÓÓ £·âõ6VæDÖW76vRbÀÌØí½É´Ä°ÀÌØí]5}9=Q%d°ÀÌØí1¥ÍÑY¥ÜÄ°±±MÑÉÕÑÑAÑÈ ÀÌØíÍÑÉÕÑ}9LISTVIEW))
_SendMessage(GUICtrlGetHandle($ListView1), $WM_NOTIFY,  ÌÍÓÝY]ÌKÝXÝÙ]   ÌÍÜÝXÝÓSTÕQUÊJBÚ[HBIÌÍ×6rÒwVvWD×6r 6VÆV7@ 66Rb33c¶×6rÒb33c´uTôUdTåEô4Äõ4P W@ ¹M±Ð)]¹(()Õ¹1YM½ÉÐ ÀÌØí¡]¹°ÀÌØí¹%Ñ´Ä°ÀÌØí¹%Ñ´È°ÀÌØíColumn)
    If $nColumn = 0 Then ; first column
        $val1 = GetSubItem^
    ÌÍÓÝY]ÌK   ÌÍÛ][LK  ÌÍÛÛÛ[[BBIÌÍÝ[]ÝX][FWBb33c´Æ7EfWsÂb33c¶äFVÓ"Âb33c¶ä6öÇVÖâ  b33c¶å&W7VÇBÒì9¼¡¹½¥Ñ´Ä¹¥Ñ´ÈÁ½Í¥Ñ¥½¹Ì(($%%ÀÌØíٰıÐìÀÌØíÙ2 Then
            $nResult = -1  ; Put item2 before item1
        ElseIf  $val1   ÝÈ    ÌÍÝ[[BBIÌÍÛÝ[HHÈ]][LZ[][LBBQ[`  &WGW&âb33c¶å&W7VÇ@ VÇ6R²vVâ6Æ6¶VBöâ÷FW"6öÇVÖç2Fòæ÷Fæ($%IÑÕɸÀì9¼¡¹½¥Ñ´Ä¹¥Ñ´ÈÁ½Í¥Ñ¥½¹Ì(%¹%)¹Õ¹()Õ¹tSubItemText($nCtrlID, $nItemID, $nColumn)
    Local $sHHÝXÝÜX]J    ][ÝÝZ[ÜÚ[Ú[ÌNÚ[  ][ÝÊBÝ'V7E6WDFFb33c·7DÇffÂÂb33c´Åddõ$Ò¢FÆÅ7G'V7E6WDFFb33c·71Ù¤°Ì°ÀÌØí¹%ѵ%¤((1½°ÀÌØíÍÑ  ÕÈô±±MÑÉÕÑ
ÉÑ ÅÕt;char[260]")
    $nIndex = GUICtrlSendMsg($nCtrlID, $LWÑSUSKLKÝXÝÙ]  ÌÍÜÝJJBØØ[    ÌÍÜÝHÒFÆÅ7G'V7D7&VFRgV÷C·VçC¶çC¶çC·VçC·VçC·G#¶çC¶çC¶çC¶çBgV÷C²±±MÑÉÕÑMÑÑ ÀÌØíÍÑ1Ù¤°Ä°ÀÌØí1Y%}QaP¤(±±MÑÉÕÑMÑÑ #036;stLvi, 2, $nIndex)
    DllStructSetData($stLvi, 3, $nCo[[BÝXÝÙ]]J   ÌÍÜÝK
ÝXÝÙ]    ÌÍÜÝYJBFÆÅ7G'V7E6WDFFb33c·7DÇfÂrÂ#c ¢uT7G&Å6VæD×6rb33c¶ä7G&ÄBÀÌØí1Y5}Q%Q4°À°±±MÑÉÕÑÑAÑÈ ÀÌØíÍÑ1Ù¤¤¤ì((ÀÌØíÍ%ѵQáÐ= DllStructGetData($stBuffer, 1)
    $stLvi = 0
    $stLvfi = 0IÌÍÜÝYH] ÌÍÜÒ][U^[[ÂØÜÂYYÝXÝFtäÔÄ5EdUr°¢äÔE"G#°¢çBFVÓ°¢çB7V$FVÓ°¢TåBTæWu7FFS(U%9PÕ=±MÑÑì(U%9PÕ
¡¹ì(A=%9PÁÑÑ¥½¸ì(1AI4±AÉ´ì)ô95ISTVIEW, FAR* LPNMLISTVIEW;

typedef struct tagNMHDR { 
  HWND hwndFrom; 
 RSYÛNÈRSÛÙNÈHRÈØÙ
Edited by Zedna

Share this post


Link to post
Share on other sites
Holger

Just modify one(two) line(s):

DllStructSetData($struct_NMLISTVIEW,1,GUICtrlGetHandle($ListView1)); here is the handle to the control needed not the GUI window handle

Uncomment the right line:

_SendMessage($Form1, $WM_NOTIFY, $ListView1, DllStructGetPtr($struct_NMLISTVIEW))

Greets

Edited by Holger

Share this post


Link to post
Share on other sites
Zedna

Just modify one(two) line(s):

DllStructSetData($struct_NMLISTVIEW,1,GUICtrlGetHandle($ListView1)); here is the handle to the control needed not the GUI window handle

Uncomment the right line:

_SendMessage($Form1, $WM_NOTIFY, $ListView1, DllStructGetPtr($struct_NMLISTVIEW))

Greets

Thank you very much Holger!! :rolleyes:

It works like a charm now.

EDIT:

here is whole corrected working script for other peoples interested in this

#NoTrayIcon 
#include <GUIConstants.au3>
#include <Misc.au3>[ÛÛÝ  ÌÍÓWÑÑUUSHH    ÌÍÓWÑTÕ
È
BÛØ[ÛÛÝ    ÌÍÕÓWÓDeÒDP¤vÆö&Â6öç7Bb33c´Ådåô4ôÅTÔä4Ä4²Òdddddc@ ¢b33c´f÷&ÓU%
ÉÑ ÅÕ½ÐíQÍÐͽÉÐÅÕ½Ðì°ÐÜÔ°ÐÀÀ°´Ä°´Ä¤(ÀÌØí1¥ÍÑY¥ÜÄôU%
ÑlCreateListView("Column 1|Column 2|Column 3", 8, 8, 458, 364, BitÔ   ÌÍÓ×ÔTÔ   ÌÍÓ×ÔÒSÓTÑS ÌÍÓ×ÔÒÕÔÑSSÐVTË  ÌÍÕÔ×ÒÐ$ôÄÂÂb33cµu5õe45$ôÄÂÂb33cµu5ô$õ$DU"Â&Dõ"b33cµu5ôUô4ÄTåDTDtRÂb33c´YM}a}
!
-   =aL°ÀÌØí1YM}a}U11I=]M1
P¤¤)U%
Ñɱ
ÉÑ1¥ÍÑY¥Ý%Ñ´ ÅÕt;c1|c2|c3",$ListView1)
GUICtrlCreateListViewItem("a1|a2|a3&][ÝË  ÌÍÓÝY]ÌJBÕRPÝÜX]SÝY]Ò][J  ][ÝØ_É][ÝË ÌÍÆ7EfWs ¤uT6WE7FFR5uõ4õrÂb33c´f÷&Ó¤uT7G&Å&Vv7FW$Æ7EfWu6÷'BÀÌØí1¥ÍÑY¥ÜÄ°ÅÕ½Ðí1YM½ÉÐÅÕ½Ðì¤((ìÐÍÑÉÐ¥¹¥Ñ¥ÑͽÉÐä¥ÉÍн±Õn
$struct_NMLISTVIEW = DllStructCreate("hwnd;uint;uint;int;int;uiÝZ[ÝZ[Ú[Ú[Ú[    ][ÝÊBÝXÝÙ]]J   ÌÍÜÝXÝÓSTÕQUËKT7G&ÄvWDæFÆRb33c´Æ7EfWs¤FÆÅ7G'V7E6WDFFb33c·7G'V7EôäÔÄ5EdUrðÀÌØí1¥ÍÑY¥ÜĤ)±±MÑÉÕÑMÑÑ ÀÌØíÍÑÉÕÑ}951%MQY%°Ì°ÀÌØí1Y9}
=1UNCLICK)
DllStructSetData($struct_NMLISTVIEW,4,-1) ; item = -1
DllStrucÙ]]J   ÌÍÜÝXÝÓSTÕQUË
K
HÈÝX][OLÔÙ[YÜØYÙJ    ÌÍÑÜLKb33cµtÕôäõDeÂb33c´Æ7EfWsÂFÆÅ7G'V7DvWEG"b33c·7G'V7EôäÔÄ5EdUr(ÀÌØíÍÑÉÕÑ}951%MQY%ôÀ()]¡¥±Ä($ÀÌØíµÍôÕ¥Ñ5Í ¤(%M±Ð($%
e $msg = $GUI_EVENT_CLOSE
            Exit
    EndSelect
WEnd


Func LVSort(&ÌÍÚÛ   ÌÍÛ][LK  ÌÍÛ][L   ÌÍÛÛÛ[[BRY ÌÍÛÛÛ[[HFVâ²f'7B6öÇVÖà b33c·fÃÒvWE7V$FVÕFWBb33c´Æ7EfWsÂb33c¶ä´Ä°ÀÌØí¹
½±Õµ¸¤($$ÀÌØíÙ°ÈôÑMÕ%ѵQáÐ ÀÌØí1¥ÍÑY¥ÜÄ°ÀÌØí¹%em2, $nColumn)
        
        $nResult = 0       ; No change of item1 and i[LÜÚ][ÛÂBRY    ÌÍÝ[H    È  ÌÍÝ[[BBIÌÍÛÝ[HLH²WBFVÓ"&Vf÷&RFVÓ VÇ6Tbb33c·fÃfwC²b33c·fÃ"FVà b33c¹IÍÕ±ÐôÄìAÕХѴȡ¥¹¥Ñ´Ä($%¹%($$($%IÑÕɸÀÌØí¹IÍÕ±Ð(%se ; when clicked on other columns do nothing
        Return 0 ; No change of iteLH[][LÜÚ][ÛÂQ[Y[[Â[ÈÙ]ÝX][U^
    ÌÍÛÝQ   3c¶äFVÔBÂb33c¶ä6öÇVÖâ¢Æö6Âb33c·7DÇffÒFÆÅ7G'V7D7&VFRÅÕ½ÐíÕ¥¹ÐíÁÑÈí¥¹Ðí¥¹ÑlÉtí¥¹ÐÅÕ½Ðì¤(±±MÑÉÕÑMÑÑ ÀÌØíÍÑ1Ù¤°Ä°036;LVFI_PARAM)
    DllStructSetData($stLvfi, 3, $nItemID)

    LØØ[  ÌÍÜÝYHÝXÝÜX]J    ][ÝØÚÌI][ÝÊB  ÌÍÛæFWÒuT7G&Å6VæD×6rb33c¶ä7G&ÄBÂb33c´ÅdÕôdäDDTÒÂÓÂFÆÅ7G'V7DvWEÈ ÀÌØíÍÑ1Ù¤¤¤((1½°ÀÌØíÍÑ1Ù¤ô±±MÑÉÕÑ
ÉÑ ÅÕ½ÐíÕ¥¹Ðint;int;uint;uint;ptr;int;int;int;int")
    DllStructSetData($stLKK ÌÍÓQÕV
BÝXÝÙ]]J ÌÍÜÝK   ÌÍÛ[^
BFÆÅ7G'V7E6WDFFb33c·7DÇfÂ2Âb33c¶ä6öÇVÖâ¢FÆÅ7G'V7E6WDFFb3ØíÍÑ1Ù¤°Ø°±±MÑÉÕÑÑAÑÈ ÀÌØíÍÑ ÕȤ¤(±±MÑÉÕÑMÑÑ ÀÌØíÍÑ1i, 7, 260)

    GUICtrlSendMsg($nCtrlID, $LVM_GETITEM, 0, DllStruÝÙ]  ÌÍÜÝJJN   ÌÍÜÒ][U^HÝXÝÙ]]J ÌÍÜÝYfW"¢b33c·7DÇfÒ b33c·7DÇffÒ b33c·7D'VffW"Ò ¢&WGW¸ÀÌØíÍ%ѵQáÐ)¹Õ¹((Ì)ÑåÁÍÑÉÕÐÑ951%MQY%ì(95!H¡Èì( int iItem;
  int iSubItem;
  UINT uNewState;
  UINT uOldState;
  UINT uChaÙYÂÒSXÝ[ÛÂTSH[NÂHSTÕQUËTSTÕQUÎÂVFVb7G'V7BFtäÔE"²¢täBvæDg&öÓ²¢TåBDg&öÓ²¢TåB6öFS²§Ò95!Hì((
Edited by Zedna

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  

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.