Jump to content
AGsol

ListView Column Header Click

Recommended Posts

AGsol

Hi All

I don't normally post on here because I can usually find the answer using the search or work it out, but for some reason today I'm having a brain freeze and hoping someone can quickly help.

I'm creating a GUI front end to an SQL Database, but I want the user to be able to click the list view column header and it activate something (ie another SQL script). My problem is identifying each individual column header? the below example works for the global ListView but not sure how to check which header was clicked?

#include <ButtonConstants.au3>
#include <GUIConstants.au3>
#include <GuiConstantsEx.au3>
#include <GuiListView.au3>
#include <GuiMenu.au3>
#include <Array.au3>
#include <WindowsConstants.au3>

Local $ExportGui, $FindGui, $FileExport, $Hostname, $Model, $Site, $ScrappedBy, $aInfo
Local $iExWindowStyle = BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE)


Opt("GUIOnEventMode", 1)
$Main = GUICreate("SQL Reporter", 800, 275, 193, 115)
 $Menu = GuiCtrlCreateMenu("File")
$exititem = GUICtrlCreateMenuitem ("Exit",$Menu)
GUICtrlSetOnEvent(-1, "Cancel")
$Menu2 = GuiCtrlCreateMenu("View")
$Refreshitem = GUICtrlCreateMenuitem ("Refresh List",$Menu2)
GUICtrlSetOnEvent(-1, "Refresh")
GUISetOnEvent($GUI_EVENT_CLOSE, "SpecialEvents")
GUISetOnEvent($GUI_EVENT_MINIMIZE, "SpecialEvents")
GUISetOnEvent($GUI_EVENT_RESTORE, "SpecialEvents")
$ListView1 = GUICtrlCreateListView("Name1|Name2|Name3|Name4|Name5", 30, 5, 740, 200, -1, $iExWindowStyle)
GUICtrlSetOnEvent($ListView1, "columnscript")
$ExportSQL = GUICtrlCreateButton("&Scrap", 30, 220, 60, 30, 0)
GUICtrlSetOnEvent(-1, "Add")
$AddSQL = GUICtrlCreateButton("&Find", 90, 220, 60, 30, 0)
GUICtrlSetOnEvent(-1, "Find")
$DeleteSQL = GUICtrlCreateButton("&Export", 150, 220, 60, 30, 0)
GUICtrlSetOnEvent(-1, "Export")

$conn = ObjCreate("ADODB.Connection")
$conn.Properties("Prompt") = 2; 1=PromptAlways, 2=PromptComplete
$ConString = "DRIVER={SQL Server};SERVER=SERVERNAME;DATABASE=DATABASENAME;UID=autoit;PWD=autoit;"
$conn.Open($ConString)
$query = ObjCreate("ADODB.RecordSet")
$query.Open("USE Autoit SELECT DISTINCT Name1, Name2, Name3, Name4, Name5 WHERE NOT Name1 = '0' GROUP BY Name1", $conn)
$Txt = ""
$Txt = $Txt & $query.GetString(2, -1, @TAB, @CR, "Null")
$Display2 = StringSplit($Txt, @CRLF)
For $x = 1 to $Display2[0]
    If $Display2[$x] = "" Then
        Else
        $Display = StringSplit($Display2[$x], @TAB)
        $ListView1_0 = GUICtrlCreateListViewItem($Display[1] & "|" & $Display[2] & "|" & $Display[3] & "|" & $Display[4] & "|" & $Display[5], $ListView1)
    EndIf
Next
$conn.close

GUISetState(@SW_SHOW)

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

Func Cancel()
    Exit
EndFunc

Func Add()
EndFunc

Func Find()
EndFunc

Func Find2()
EndFunc

Func FindCancel()
EndFunc

Func Export()
EndFunc

Func Export2()
EndFunc

Func ExportCancel()
EndFunc

Func Browse()
EndFunc

Func Delete()
EndFunc

Func Refresh()
EndFunc

Func columnscript()
EndFunc


Func SpecialEvents()
    Select
        Case @GUI_CTRLID = $GUI_EVENT_CLOSE
            Exit
        Case @GUI_CTRLID = $GUI_EVENT_MINIMIZE
        Case @GUI_CTRLID = $GUI_EVENT_RESTORE
    EndSelect
EndFunc

Regards,

Ian

Share this post


Link to post
Share on other sites
Melba23

AGsol,

You need to look for the $LVN_COLUMNCLICK code within the WM_NOTIFY message. :graduated:

Add:

GUIRegisterMsg($WM_NOTIFY, "_WM_NOTIFY")

after the GUISetState(@SW_SHOW) line and then use this handler function:

Func _WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg, $wParam
    Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    Switch HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
        Case $ListView1_Handle
            Switch DllStructGetData($tNMHDR, "Code")
                Case $LVN_COLUMNCLICK ; A column was clicked
                    Local $tInfo = DllStructCreate($tagNMLISTVIEW, $lParam)
                    Local $iCol = DllStructGetData($tInfo, "SubItem")
                    ConsoleWrite("Column clicked: " & $iCol & @CRLF)
            EndSwitch
    EndSwitch
    Return $__LISTVIEWCONSTANT_GUI_RUNDEFMSG

EndFunc   ;==>_WM_NOTIFY

If you are unsure about GUIRegisterMsg and Windows message handlers, I recommend the GUIRegisterMsg tutorial in the Wiki. :D

Please ask if you have any questions. :(

M23

  • Like 1

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
PsaltyDS

You are already getting notification when a column header is clicked. Modified demo so it can be run without the SQL:

#include <ButtonConstants.au3>
#include <GUIConstants.au3>
#include <GuiConstantsEx.au3>
#include <GuiListView.au3>
#include <GuiMenu.au3>
#include <Array.au3>
#include <WindowsConstants.au3>

Local $ExportGui, $FindGui, $FileExport, $Hostname, $Model, $Site, $ScrappedBy, $aInfo
Local $iExWindowStyle = BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE)

Opt("GUIOnEventMode", 1)
$Main = GUICreate("SQL Reporter", 800, 275, 193, 115)
$Menu = GUICtrlCreateMenu("File")
$exititem = GUICtrlCreateMenuItem("Exit", $Menu)
GUICtrlSetOnEvent(-1, "Cancel")
$Menu2 = GUICtrlCreateMenu("View")
$Refreshitem = GUICtrlCreateMenuItem("Refresh List", $Menu2)
GUICtrlSetOnEvent(-1, "Refresh")
GUISetOnEvent($GUI_EVENT_CLOSE, "SpecialEvents")
GUISetOnEvent($GUI_EVENT_MINIMIZE, "SpecialEvents")
GUISetOnEvent($GUI_EVENT_RESTORE, "SpecialEvents")
$ListView1 = GUICtrlCreateListView("Name1|Name2|Name3|Name4|Name5", 30, 5, 740, 200, -1, $iExWindowStyle)
GUICtrlSetOnEvent($ListView1, "columnscript")
$ExportSQL = GUICtrlCreateButton("&Scrap", 30, 220, 60, 30, 0)
GUICtrlSetOnEvent(-1, "Add")
$AddSQL = GUICtrlCreateButton("&Find", 90, 220, 60, 30, 0)
GUICtrlSetOnEvent(-1, "Find")
$DeleteSQL = GUICtrlCreateButton("&Export", 150, 220, 60, 30, 0)
GUICtrlSetOnEvent(-1, "Export")

For $x = 1 To 5
    Global $Display[6] = ["", "Display 1 - " & $x, "Display 2 - " & $x, "Display 3 - " & $x, "Display 4 - " & $x, "Display 5 - " & $x]
    $ListView1_0 = GUICtrlCreateListViewItem($Display[1] & "|" & $Display[2] & "|" & $Display[3] & "|" & $Display[4] & "|" & $Display[5], $ListView1)
Next

GUISetState(@SW_SHOW)

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

Func Cancel()
    Exit
EndFunc   ;==>Cancel

Func Add()
    ConsoleWrite("DEBUG:  Add()" & @LF)
EndFunc   ;==>Add

Func Find()
    ConsoleWrite("DEBUG:  Find()" & @LF)
EndFunc   ;==>Find

Func Find2()
    ConsoleWrite("DEBUG:  Find2()" & @LF)
EndFunc   ;==>Find2

Func FindCancel()
    ConsoleWrite("DEBUG:  FindCancel()" & @LF)
EndFunc   ;==>FindCancel

Func Export()
    ConsoleWrite("DEBUG:  Export()" & @LF)
EndFunc   ;==>Export

Func Export2()
    ConsoleWrite("DEBUG:  Export2()" & @LF)
EndFunc   ;==>Export2

Func ExportCancel()
    ConsoleWrite("DEBUG:  ExportCancel()" & @LF)
EndFunc   ;==>ExportCancel

Func Browse()
    ConsoleWrite("DEBUG:  Browse()" & @LF)
EndFunc   ;==>Browse

Func Delete()
    ConsoleWrite("DEBUG:  Delete()" & @LF)
EndFunc   ;==>Delete

Func Refresh()
    ConsoleWrite("DEBUG:  Refresh()" & @LF)
EndFunc   ;==>Refresh

Func columnscript()
    ConsoleWrite("DEBUG:  columnscript()" & @LF)
EndFunc   ;==>columnscript


Func SpecialEvents()
    Switch @GUI_CtrlId
        Case $GUI_EVENT_CLOSE
            Exit
        Case $GUI_EVENT_MINIMIZE
            ConsoleWrite("DEBUG:  SpecialEvents(): $GUI_EVENT_MINIMIZE" & @LF)
        Case $GUI_EVENT_RESTORE
            ConsoleWrite("DEBUG:  SpecialEvents(): $GUI_EVENT_RESTORE" & @LF)
    EndSwitch
EndFunc   ;==>SpecialEvents

But nothing there will tell you which column was clicked. For that you need to register the WM_NOTIFY messages. For instance, run the example script from the help file under _GUICtrlListView_HitTest() and watch the "Subitem" value reported when you click on each column header.

:graduated:

Edit: Oops, Melba was posting while I was sleeping.

Edited by PsaltyDS

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites
AGsol

Thank you to you both especially Melba because I saw your reply and took action from it.

Its all working fine now, Once again this forum is the most useful forum I have ever used.

Share this post


Link to post
Share on other sites
odaylton

Using _GUICtrlListView_RegisterSortCallBack
Is there a way to know which column is ordered and its direction?
I used this

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndListView, $tInfo
    ; Local $tBuffer
    $hWndListView = $hListView
    If Not IsHWnd($hListView) Then $hWndListView = GUICtrlGetHandle($hListView)

    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hWndListView
            Switch $iCode
                Case $LVN_COLUMNCLICK ; A column was clicked
                    Local $tInfo = DllStructCreate($tagNMLISTVIEW, $lParam)
                    Local $iCol = DllStructGetData($tInfo, "SubItem")
                    ;$ListViewOrdem[0]=Indice da coluna ordenada
                    ;$ListViewOrdem[1]=1 = cressente
                    if $ListViewOrdem[0]= $iCol Then
                        $ListViewOrdem[1] *=-1
                    Else
                        $ListViewOrdem[0] = $iCol 
                    EndIf

 

where I had to create a small matrix to define the direction in parallel with CallBack.
but should the callback have this information otherwise available?

Edited by odaylton

Share this post


Link to post
Share on other sites
Melba23

odaylton,

Amend the _GUICtrlListView_SortItems function as follows:

Func _GUICtrlListView_SortItems($hWnd, $iCol)
    Local $iRet, $iIndex, $pFunction, $hHeader, $iFormat, $iDirn

    If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd)

    For $x = 1 To $__g_aListViewSortInfo[0][0]
        If $hWnd = $__g_aListViewSortInfo[$x][1] Then
            $iIndex = $x
            ExitLoop
        EndIf
    Next

    $pFunction = DllCallbackGetPtr($__g_aListViewSortInfo[$iIndex][2]) ; get pointer to call back
    $__g_aListViewSortInfo[$iIndex][3] = $iCol ; $nColumn = column clicked
    $__g_aListViewSortInfo[$iIndex][7] = 0 ; $bSet
    $__g_aListViewSortInfo[$iIndex][4] = $__g_aListViewSortInfo[$iIndex][6] ; nCurCol = $nCol
    $iRet = _SendMessage($hWnd, $LVM_SORTITEMSEX, $hWnd, $pFunction, 0, "hwnd", "ptr")
    If $iRet <> 0 Then
        If $__g_aListViewSortInfo[$iIndex][9] Then ; Use arrow in header
            $hHeader = $__g_aListViewSortInfo[$iIndex][10]
            For $x = 0 To _GUICtrlHeader_GetItemCount($hHeader) - 1
                $iFormat = _GUICtrlHeader_GetItemFormat($hHeader, $x)
                If BitAND($iFormat, $HDF_SORTDOWN) Then
                    _GUICtrlHeader_SetItemFormat($hHeader, $x, BitXOR($iFormat, $HDF_SORTDOWN))
                ElseIf BitAND($iFormat, $HDF_SORTUP) Then
                    _GUICtrlHeader_SetItemFormat($hHeader, $x, BitXOR($iFormat, $HDF_SORTUP))
                EndIf
            Next
            $iFormat = _GUICtrlHeader_GetItemFormat($hHeader, $iCol)
            If $__g_aListViewSortInfo[$iIndex][5] = 1 Then ; ascending
                _GUICtrlHeader_SetItemFormat($hHeader, $iCol, BitOR($iFormat, $HDF_SORTUP))
                $iDirn = 1 ; <<<<<<<<<<<<<<<<<<<<<<<<<<<
            Else ; descending
                _GUICtrlHeader_SetItemFormat($hHeader, $iCol, BitOR($iFormat, $HDF_SORTDOWN))
                $iDirn = 0 ; <<<<<<<<<<<<<<<<<<<<<<<<<<<
            EndIf
        EndIf
    EndIf

    SetExtended($iDirn) ; Set the sort direction in @extended <<<<<<<<<<<
    
    Return $iRet <> 0
EndFunc   ;==>_GUICtrlListView_SortItems

Now when you sort a column @extended will give you the direction - as in this modified Help file example:

#include <GUIConstantsEx.au3>
#include <GuiImageList.au3>
#include <GuiListView_Mod.au3> ; Standard UDF with the amended _SortItems function <<<<<<<<<<<<<<<<<<<<<<<<<<
#include <WindowsConstants.au3>

Global $g_idListView

Example()

Func Example()
    Local $hImage, $aIcons[3] = [0, 3, 6]
    Local $iExWindowStyle = BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE)
    Local $iExListViewStyle = BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_SUBITEMIMAGES, $LVS_EX_GRIDLINES, $LVS_EX_CHECKBOXES, $LVS_EX_DOUBLEBUFFER)

    GUICreate("ListView Sort", 300, 200)

    $g_idListView = GUICtrlCreateListView("Column1|Col2|Col3", 10, 10, 280, 180, -1, $iExWindowStyle)
    _GUICtrlListView_SetExtendedListViewStyle($g_idListView, $iExListViewStyle)

    ; Load images
    $hImage = _GUIImageList_Create(18, 18, 5, 3)
    _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -7)
    _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -12)
    _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -3)
    _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -4)
    _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -5)
    _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -6)
    _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -9)
    _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -10)
    _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -11)
    _GUICtrlListView_SetImageList($g_idListView, $hImage, 1)

    _AddRow($g_idListView, "ABC|000666|10.05.2004", $aIcons)
    _AddRow($g_idListView, "DEF|444|11.05.2005", $aIcons, 1)
    _AddRow($g_idListView, "CDE|555|12.05.2004", $aIcons, 2)

    GUISetState(@SW_SHOW)

    _GUICtrlListView_RegisterSortCallBack($g_idListView)

    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ExitLoop
            Case $g_idListView
                ; Kick off the sort callback
                _GUICtrlListView_SortItems($g_idListView, GUICtrlGetState($g_idListView))
                ; Look for direction in @extended <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                Switch @extended
                    Case 1
                        ConsoleWrite("Ascending" & @CRLF)
                    Case Else
                        ConsoleWrite("Descending" & @CRLF)
                EndSwitch
        EndSwitch
    WEnd

    _GUICtrlListView_UnRegisterSortCallBack($g_idListView)
    GUIDelete()
EndFunc   ;==>Example

Func _AddRow($hWnd, $sItem, $aIcons, $iPlus = 0)
    Local $aItem = StringSplit($sItem, "|")
    Local $iIndex = _GUICtrlListView_AddItem($hWnd, $aItem[1], $aIcons[0] + $iPlus, _GUICtrlListView_GetItemCount($hWnd) + 9999)
    _GUICtrlListView_SetColumnWidth($hWnd, 0, $LVSCW_AUTOSIZE_USEHEADER)

    For $x = 2 To $aItem[0]
        _GUICtrlListView_AddSubItem($hWnd, $iIndex, $aItem[$x], $x - 1, $aIcons[$x - 1] + $iPlus)
        _GUICtrlListView_SetColumnWidth($hWnd, $x - 1, $LVSCW_AUTOSIZE)
    Next
EndFunc   ;==>_AddRow

I suggest you open a feature request ticket in Trac (and lick to this thread) as this seems to be a useful addition to the UDF.

M23

  • Like 1

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
odaylton

Thanks for the help and suggestion, but I think you have more competence to become uncertain in UDF ...

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

×