Add an event to a listview

BlitzMax Forums/MaxGUI Module/Add an event to a listview

andre72(Posted 2007) [#1]
Hi,

based on the code by Ziltch I use a MultiColumn Listview.
I like to make it possible to sort the columns when the header is clicked.
But how to add an event to a listview and where can I found what value LVN_COLUMNCLICK has ...?

Strict

' Listbox Item edit Text and Drag 'n Drop example.
' Ziltch 29 August 2006.
' You can use this code if you credit Ziltch!
Const LBS_DISABLENOSCROLL = 4096
Const LBS_EXTENDEDSEL = $800
Const LBS_HASSTRINGS = 64
Const LBS_MULTICOLUMN = 512
Const LBS_MULTIPLESEL = 8
Const LBS_NODATA = $2000
Const LBS_NOINTEGRALHEIGHT = 256
Const LBS_NOREDRAW = 4
Const LBS_NOSEL = $4000
Const LBS_NOTIFY = 1
Const LBS_OWNERDRAWFIXED = 16
Const LBS_OWNERDRAWVARIABLE = 32
Const LBS_SORT = 2
Const LBS_STANDARD = $a00003
Const LBS_USETABSTOPS = 128
Const LBS_WANTKEYBOARDINPUT = $400

Const LVM_FIRST = $1000
Const LVM_GETCOLUMNA = (LVM_FIRST+25)
Const LVM_GETCOLUMNW = (LVM_FIRST+95)
Const LVM_SETCOLUMNA = (LVM_FIRST+26)
Const LVM_SETCOLUMNW = (LVM_FIRST+96)
Const LVM_INSERTCOLUMNA = (LVM_FIRST+27)
Const LVM_INSERTCOLUMNW = (LVM_FIRST+97)
Const LVM_DELETECOLUMN = (LVM_FIRST+28)
Const LVM_GETCOLUMNWIDTH = (LVM_FIRST+29)
Const LVM_GETITEMA = (LVM_FIRST+5)
Const LVM_GETITEMW = (LVM_FIRST+75)
Const LVM_SETITEMA = (LVM_FIRST+6)
Const LVM_SETITEMW = (LVM_FIRST+76)
Const LVM_INSERTITEMA = (LVM_FIRST+7)
Const LVM_INSERTITEMW = (LVM_FIRST+77)
Const LVM_DELETEITEM = (LVM_FIRST+8)
Const LVM_DELETEALLITEMS = (LVM_FIRST+9)
Const LVM_GETCALLBACKMASK= (LVM_FIRST+10)
Const LVM_SETCALLBACKMASK= (LVM_FIRST+11)
Const LVM_SETCOLUMNWIDTH = (LVM_FIRST+30)
Const LVM_GETTEXTCOLOR = (LVM_FIRST+35)
'Const LVM_SETTEXTCOLOR = (LVM_FIRST+36)
Const LVM_GETTEXTBKCOLOR = (LVM_FIRST+37)
'Const LVM_SETTEXTBKCOLOR = (LVM_FIRST+38)
Const LVM_SORTITEMS = (LVM_FIRST+48)
Const LVM_ARRANGE =(LVM_FIRST+22)
Const LVM_EDITLABELA =(LVM_FIRST+23)
Const LVM_EDITLABELW =(LVM_FIRST+118)
Const LVM_GETEDITCONTROL =(LVM_FIRST+24)
Const LVM_CREATEDRAGIMAGE = (LVM_FIRST + 33)
Const LVM_HITTEST = (LVM_FIRST + 18)

Const LVCF_FMT =1
Const LVCF_WIDTH =2
Const LVCF_TEXT =4
Const LVCF_SUBITEM =8
' #define LVCF_IMAGE 16
' #define LVCF_ORDER =32
' #define LVCFMT_LEFT =0
Const LVCFMT_RIGHT =1
Const LVCFMT_CENTER =2
Const LVCFMT_JUSTIFYMASK =3

Const LVN_FIRST = -100
Const LVN_LAST=-199
Const LVN_ITEMCHANGING= LVN_FIRST
Const LVN_ITEMCHANGED =(LVN_FIRST-1)
Const LVN_INSERTITEM =(LVN_FIRST-2)
Const LVN_DELETEITEM =(LVN_FIRST-3)
Const LVN_DELETEALLITEMS =(LVN_FIRST-4)
Const LVN_BEGINLABELEDIT = (LVN_FIRST-5)
Const LVN_BEGINLABELEDITW= (LVN_FIRST-75)
Const LVN_ENDLABELEDIT= (LVN_FIRST-6)
Const LVN_ENDLABELEDITW =(LVN_FIRST-76)
Const LVN_COLUMNCLICK =(LVN_FIRST-8)
Const LVN_BEGINDRAG =(LVN_FIRST-9)
Const LVN_BEGINRDRAG =(LVN_FIRST-11)
Const LVN_GETDISPINFOA =(LVN_FIRST-50)
Const LVN_GETDISPINFOW =(LVN_FIRST-77)
Const LVN_SETDISPINFOA =(LVN_FIRST-51)
Const LVN_SETDISPINFOW =(LVN_FIRST-78)
Const LVN_KEYDOWN =(LVN_FIRST-55)

Const LVCF_IMAGE= 16
Const LVCF_ORDER =32
Const LVIF_TEXT = 1
Const LVIF_IMAGE =2
Const LVIF_PARAM =4
Const LVIF_STATE =8
Const LVIF_INDENT =$10
Const LVIF_GROUPID =$100
Const LVIF_COLUMNS =$200
Const LVIF_NORECOMPUTE =$800
Const LVIF_DI_SETITEM =$1000

Const LVS_ICON =0
Const LVS_REPORT =1
Const LVS_SMALLICON =2
Const LVS_LIST =3
Const LVS_TYPEMASK =3
Const LVS_SINGLESEL =4
Const LVS_SHOWSELALWAYS =8
Const LVS_SORTASCENDING =16
Const LVS_SORTDESCENDING =32
Const LVS_SHAREIMAGELISTS =64
Const LVS_NOLABELWRAP =128
Const LVS_AUTOARRANGE =256
Const LVS_EDITLABELS =512
Const LVS_NOSCROLL =$2000
Const LVS_TYPESTYLEMASK =$fc00
Const LVS_ALIGNTOP =0
Const LVS_ALIGNLEFT =$800
Const LVS_ALIGNMASK =$c00
Const LVS_OWNERDRAWFIXED =$400
Const LVS_NOCOLUMNHEADER =$4000
Const LVS_NOSORTHEADER =$8000
Const LVS_TREEVIEW = $4000
Const LVS_EX_GRIDLINES = $1
Const LVS_EX_SUBITEMIMAGES = $2
Const LVS_EX_CHECKBOXES = $4
Const LVS_EX_TRACKSELECT = $8
Const LVS_EX_HEADERDRAGDROP = $10
Const LVS_EX_FULLROWSELECT = $20 'applies to report mode only
Const LVS_EX_ONECLICKACTIVATE = $40
Const LVS_EX_TWOCLICKACTIVATE = $80
Const LVS_EX_FLATSB = $100 'cannot be cleared - Win32 & IE4 only
Const LVS_EX_REGIONAL = $200 'Win32 & IE4 only
Const LVS_EX_INFOTIP = $400

Const LVIS_FOCUSED = $1
Const LVIS_SELECTED = $2
Const LVIS_CUT = $4
Const LVIS_DROPHILITED = $8

Const LVIS_OVERLAYMASK = $F00
Const LVIS_STATEIMAGEMASK = $F000


Type LVCOLUMN
Field mask
Field fmt
Field cx
Field pszText:Byte Ptr
Field cchTextMax
Field iSubItem
EndType

Type LVITEM
Field mask
Field iItem
Field iSubItem
Field iState
Field stateMask
Field pszText:Byte Ptr
Field cchTextMax
Field iImage
Field lParam
Field iIndent
Field iGroupId
Field cColumns
Field puColumns
EndType

Type LV_HITTESTINFO
Field ptX
Field ptY
Field flags
Field iItem
EndType

Type tagLVKEYDOWN
Field hwndFrom
Field idFrom
Field code
Field wVKey:Short
Field flags
EndType

Type tagNM_LISTVIEW
Field hwndFrom
Field idFrom
Field code
Field iItem
Field iSubItem
Field uNewState
Field uOldState
Field uChanged
Field ptActionX
Field ptActionY
Field lParam:Byte Ptr
EndType

Function AddListBoxColumn(ListBox:TGadget,Column,HeadingText$,width,Style=0)
Local ListboxHwnd=QueryGadget(ListBox,QUERY_HWND)
Local col:LVCOLUMN = New LVCOLUMN
Col.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_FMT
Col.fmt = Style
Col.cx = width
col.pszText = HeadingText$.ToCString()
Local ListBoxstyle = GetWindowLongA(ListboxHwnd , GWL_STYLE)
If (ListBoxstyle & LBS_MULTICOLUMN ) <> ( LBS_MULTICOLUMN ) Then
ListBoxstyle = ListBoxstyle | LBS_MULTICOLUMN
SetWindowLongA(ListboxHwnd , GWL_STYLE, ListBoxstyle ) 'change the style so that we have headings
EndIf
SendMessageA(ListboxHwnd,LVM_INSERTCOLUMNA,Column,Int(Byte Ptr Col))
End Function

Function AddListBoxItem(ListBox:TGadget,Text$,Row,Column)
Local ListboxHwnd=QueryGadget(ListBox,QUERY_HWND)
Local ColItem:LVITEM = New LVITEM
ColItem.mask = LVIF_TEXT
ColItem.iSubItem = Column
ColItem.iItem = Row
ColItem.pszText = Text$.ToCString()
ColItem.cchTextMax = Text$.Length + 1
SendMessageA( ListboxHwnd,LVM_SETITEMA,0,Int(Byte Ptr ColItem))
ColItem=Null
End Function


Function GetListBoxItem:String(ListBox:TGadget,Row,Column)
Local ListboxHwnd=QueryGadget(ListBox,QUERY_HWND)
If ListboxHwnd Then
Local Ans$
Local TextBank:TBank=CreateBank(1024)
'Local Text:Byte[256]
Local ColItem:LVITEM = New LVITEM
ColItem.mask = LVIF_TEXT
ColItem.iSubItem = Column
ColItem.iItem = Row
ColItem.pszText = BankBuf(TextBank)
ColItem.cchTextMax = 255
SendMessageA( ListboxHwnd,LVM_GETITEMA,0,Int(Byte Ptr ColItem))
If ColItem.pszText <> Null
Ans$=Ans$.fromcstring(ColItem.pszText)
ColItem=Null
EndIf
Return Trim(Ans$)
EndIf
End Function

Function SetListBoxItem(ListBox:TGadget,Text:String,Row,Column=0)
Local ListboxHwnd=QueryGadget(ListBox,QUERY_HWND)
If Column=0 Then
ListBox.items[Row].Text = Text
DebugLog "ListBox:TGadget text "+Text
EndIf
If ListboxHwnd Then
Local ColItem:LVITEM = New LVITEM
ColItem.mask = LVIF_TEXT
ColItem.iSubItem = Column
ColItem.iItem = Row
ColItem.pszText = Text.Tocstring()
ColItem.cchTextMax = Len(Text)
Return SendMessageA( ListboxHwnd,LVM_SETITEMA,0,Int(Byte Ptr ColItem))
EndIf
End Function

Function ListBoxHeading(ListBox:TGadget,Column,Text$,width=0)
Local ListboxHwnd=QueryGadget(ListBox,QUERY_HWND)
Local col:LVCOLUMN = New LVCOLUMN
If width = 0 Then
Col.mask = LVCF_TEXT| LVCF_FMT
Else
Col.mask = LVCF_TEXT| LVCF_FMT | LVCF_WIDTH
col.cx = width
EndIf
col.pszText = Text$.ToCString()
Local ListBoxstyle = GetWindowLongA(ListboxHwnd , GWL_STYLE)
If (ListBoxstyle & LVS_NOCOLUMNHEADER ) Then
ListBoxstyle = ListBoxstyle ~LVS_NOCOLUMNHEADER
If ListBoxstyle & LVS_EDITLABELS=0 Then ListBoxstyle = ListBoxstyle | LVS_EDITLABELS
SetWindowLongA(ListboxHwnd , GWL_STYLE, ListBoxstyle ) 'change the style so that we have headings
EndIf
SendMessageA(ListboxHwnd,LVM_SETCOLUMNA,Column,Int(Byte Ptr Col))
End Function

Function ListBoxColumnWidth(ListBox:TGadget,Column,width)
Local ListboxHwnd=QueryGadget(ListBox,QUERY_HWND)
Local col:LVCOLUMN = New LVCOLUMN
Col.mask = LVCF_WIDTH
col.cx = width
SendMessageA(ListboxHwnd,LVM_SETCOLUMNA,Column,Int(Byte Ptr Col))
End Function

Function ListBoxGadgetMultiSelect(ListBox:TGadget)
Local ListboxHwnd = QueryGadget(ListBox,QUERY_HWND)
Local ListBoxstyle = GetWindowLongA(ListboxHwnd , GWL_STYLE)
If (ListBoxstyle & LVS_SINGLESEL) = LVS_SINGLESEL Then
Return SetWindowLongA(ListboxHwnd , GWL_STYLE, ListBoxstyle ~ LVS_SINGLESEL ) 'change the style
EndIf
End Function

Global ExplorerWindow:TGadget = CreateWindow("Pic Explorer Window", 100, 100, 700, 470, Null, WINDOW_TITLEBAR | WINDOW_CLIENTCOORDS | WINDOW_STATUS)

Local Explorer:TGadget = CreateListBox(2,2,537,394,ExplorerWindow)

ListBoxHeading(Explorer, 0, "Row1")
AddListBoxColumn(Explorer, 1, "Row2", 40, 0)
AddListBoxColumn(Explorer, 2, "Row3", 110, 0)
AddListBoxColumn(Explorer, 3, "Row4", 110, 0)
AddListBoxColumn(Explorer, 4, "Row5", 89, 0)

AddGadgetItem (Explorer, "Test", 0, 0, "Hurz")
AddListBoxItem(Explorer, "Test2", 0, 1)
AddListBoxItem(Explorer, "Test3", 0, 2)

Repeat
WaitEvent()

Local Gadget:TGadget = TGadget(EventSource())

Select EventID()
Case EVENT_WINDOWCLOSE
Exit
Default
DebugLog(EventID())
End Select
Forever


Ziltch(Posted 2007) [#2]
Have a look at the code here;
http://www.blitzbasic.com/Community/posts.php?topic=62706

It detects the column headers being clicked with this code;



I hope this helps


andre72(Posted 2007) [#3]
Thanks Zitch it do - as I see I need just to have a better look to your source ...

This works fine but is it also possible to add an eventhook to so you can get it like BM events in a main loop?


Ziltch(Posted 2007) [#4]
I do not think you can use an eventhook to get WM_NOTIFY messages.

I guess you could create you own event and use emitevent inside NewListProc when NotifyMess.code = HDN_ITEMCLICKW.

At least we can use winprocs in Blitmax, to overcome some missing features.