==Trapping a Double Click in a Listview== ===Demo by Eldron Gill=== //Editor's Note// //A [[http://msdn2.microsoft.com/en-us/library/system.windows.forms.listview.aspx|listview]] is an advanced [[http://msdn2.microsoft.com/en-us/library/system.windows.forms.listbox.aspx|listbox.]] The listview control is typically used to display members of a data collection in table format. Each column has its own column header. The listview is far more complex than the ordinary listbox. While the listbox is easily populated from its associated array, the listview requires each item to be individually assigned. This assignment is accomplished with a rather complicated series of structs and API calls.// [[image:LVIllustration.png]] //A listview demo is included in [[user:Alyce|Alyce Watson's]] [[http://www.alycesrestaurant.com/companion.htm|Liberty 4 Companion ebook.]] Alyce's demo shows how to construct a listview, add and delete items to the listview, and make a listview selection by highlighting an item and then clicking the select button. Eldron Gill takes Alyce's demo one step further by allowing selection from a double mouse click on the listview item itself.// //Capturing mouse clicks in a listview requires a callback function, not easily handled even with Liberty BASIC. Fortunately, Dennis McKinney[[user:DennisMcK|Dennis McKinney]] offers the free [[http://syberden.net/libertybelle/|msghook.dll]]designed specifically for this purpose. Here is Eldron's modification of Alyce's listview demo to allow selection by a double left mouse click. As stated in the code, [[http://syberden.net/libertybelle/|msghook.dll]] must be accessible within the program folder.// [[code format="vb"]] 'This demo requires msghook.dll by Dennis McKinney 'Get it here: http://www.syberden.net/libertybelle/dlls.htm 'Alyce Watson provided the listview code. 'http://www.alycesrestaurant.com 'listview control with double click 10/09/2006 Eldron Gill nomainwin dim info$(0,0) If fileExists(DefaultDir$, "msghook.dll") < 1 then notice ""+chr$(13)+"This demo requires msghook.dll by Dennis McKinney"+chr$(13)+_ "Download the dll from here : http://www.syberden.net/libertybelle/dlls.htm"+chr$(13)+_ "Place it in the folder with this code." End End If 'constants LVS.NOSORTHEADER = 32768 LVS.REPORT = 1 LVS.SINGLESEL = 4 LVS.SHOWSELALWAYS = 8 LVS.SORTASCENDING = 16 LVS.SORTDESCENDING = 32 LVS.NOLABELWRAP = 128 LVS.AUTOARRANGE = 256 LVS.NOSCROLL = 8192 LVS.ALIGNTOP = 0 LVS.ALIGNLEFT = 2048 LVS.NOCOLUMNHEADER = 16384 LVIF.TEXT = 1 LVIF.STATE = 8 LVIS.UNSELECTED = 0 LVIS.FOCUSED = 1 LVIS.SELECTED = 2 LVM.FIRST = 4096 LVM.SETITEM = 4102 LVM.INSERTITEM = 4103 LVM.INSERTCOLUMN = 4123 LVM.GETITEMCOUNT = 4100 LVM.GETITEMA = 4101 LVM.GETITEMTEXTA = 4141 LVM.GETITEMSTATE = 4138 LVM.SETITEMSTATE = 4139 LVM.DELETEITEM = 4104 LVM.DELETEALLITEMS = 4105 LVCF.WIDTH = 2 LVCF.TEXT = 4 'create structs Struct LVCOLUMN, _ mask As ulong, _ fmt As long, _ cx As long, _ pszText$ As ptr, _ cchTextMax As long, _ iSubItem As long, _ iImage As long, _ iOrder As long Struct LVITEM, _ mask As ulong, _ iItem As long, _ iSubItem As long, _ state As ulong, _ stateMask As ulong, _ pszText$ As ptr, _ cchTextMax As long, _ iImage As long, _ lParam As long, _ iIndent As long struct msg,_ hndl as long,_ message as long,_ wParam as long,_ lParam as long,_ LOWORDwparam as word,_ HIWORDwparam as word,_ LOWORDlparam as word,_ HIWORDlparam as word 'initialize common controls: calldll #comctl32, "InitCommonControls",re as void ' Open a window WindowWidth = 240: WindowHeight = 200 UpperLeftX = 10: UpperLeftY = 10 button #1.b, "Add",[add],UL,10,10,90,24 button #1.d, "Delete",[delete],UL,120,10,90,24 button #1.GetMsgHookCallback, "", [choice], ul, 0, 0, 0, 0 statictext #1.s, "List count: 2",10,140,100,30 open "Listview Example" for dialog as #1 print #1, "trapclose [quit]" hwndParent = hwnd(#1) ' Get window instance handle CallDLL #user32, "GetWindowLongA",_ hwndParent As long,_ 'parent window handle _GWL_HINSTANCE As long,_'flag to retrieve instance handle hInstance As long 'instance handle ' Create control style = _WS_CHILD OR _WS_VISIBLE OR LVS.NOSORTHEADER _ OR LVS.REPORT OR LVS.SINGLESEL OR LVS.SHOWSELALWAYS calldll #user32, "CreateWindowExA",_ _WS_EX_CLIENTEDGE As long,_ ' extended style "SysListView32" as ptr,_ ' class name "" as ptr,_ style as long,_ ' style 10 as long,_ ' left x 50 as long,_ ' top y 200 as long,_ ' width 80 as long,_ ' height hwndParent as long,_ ' parent hWnd 0 as long,_ hInstance as long,_ ' hInstance "" as ptr,_ hwndLV as long ' listview handle 'insert first column: LVCOLUMN.mask.struct = LVCF.WIDTH OR LVCF.TEXT LVCOLUMN.cx.struct = 90 LVCOLUMN.pszText$.struct = "Name" CallDLL #user32, "SendMessageA", _ hwndLV As long, _ LVM.INSERTCOLUMN As long, _ 0 As long, _ '0 = first column LVCOLUMN As struct, _ r As long 'insert second column: LVCOLUMN.cx.struct = 65 LVCOLUMN.pszText$.struct = "Rank" CallDLL #user32, "SendMessageA", _ hwndLV As long, _ LVM.INSERTCOLUMN As long, _ 1 As long, _ '1 = second column LVCOLUMN As struct, _ r As long 'insert text for first row, first column 'requires message to insert item LVITEM.mask.struct = LVIF.TEXT LVITEM.iItem.struct = 0 'first row LVITEM.iSubItem.struct = 0 'first column LVITEM.pszText$.struct = "Carl Gundel" CallDLL #user32, "SendMessageA", _ hwndLV As long, _ LVM.INSERTITEM As long, _ 0 As long, _ LVITEM As struct, _ r As long 'insert text for second column, first row LVITEM.iItem.struct = 0 'first row LVITEM.iSubItem.struct = 1 'second column LVITEM.pszText$.struct = "Expert" CallDLL #user32, "SendMessageA", _ hwndLV As long, _ LVM.SETITEM As long, _ ' 0 As long, _ LVITEM As struct, _ r As long 'insert second row, first column LVITEM.iItem.struct = 1 'second row LVITEM.iSubItem.struct = 0 'first column LVITEM.pszText$.struct = "Bill Gates" CallDLL #user32, "SendMessageA", _ hwndLV As long, _ LVM.INSERTITEM As long, _ 0 As long, _ LVITEM As struct, _ r As long 'add second column to second row LVITEM.iItem.struct = 1 'second row LVITEM.iSubItem.struct = 1 'second column LVITEM.pszText$.struct = "Novice" CallDLL #user32, "SendMessageA", _ hwndLV As long, _ LVM.SETITEM As long, _ ' 0 As long, _ LVITEM As struct, _ r As long 'full row select LVM.FIRST = hexdec("1000") LVM.SETEXTENDEDLISTVIEWSTYLE = LVM.FIRST + 54 LVS.EX.FULLROWSELECT = hexdec("20") CallDLL #user32, "SendMessageA", _ hwndLV As long, _ LVM.SETEXTENDEDLISTVIEWSTYLE As long, _ ' LVS.EX.FULLROWSELECT As long, _ LVS.EX.FULLROWSELECT As long, _ r As long ' if you want a grid, leave next message uncommented... CallDll #user32, "SendMessageA" , hwndLV as uLong, 4150 as Long,_ 1 As Long, 1 As Long, re as Long ' open "MsgHook" for dll as #MsgHook hMsgProc = hwnd(#1.GetMsgHookCallback) calldll #MsgHook, "TrapMsgFor",hwndLV as long, ret as boolean calldll #MsgHook, "WatchMsg", hwndLV as long, _WM_LBUTTONDBLCLK as long, ret as boolean hMsgProc = hwnd(#1.GetMsgHookCallback) calldll #user32, "GetWindowLongA",hMsgProc as long,_GWL_ID as short,callbackID as long calldll #MsgHook, "CreateGetMsgProcHook", hwndParent as long, callbackID as long, _ hMsgProc as long, hHook as long wait [choice] 'determine user selection calldll #MsgHook, "GetMsg", msg as struct, ret as void 'get number of items in list: CallDLL #user32, "SendMessageA", _ hwndLV As long, _ LVM.GETITEMCOUNT As long, _ 0 As long, _ 'always 0 0 As long, _ 'always 0 total As long for index = 0 to total-1 'check each row LVITEM.mask.struct = LVIF.TEXT OR LVIF.STATE LVITEM.iItem.struct = index 'row LVITEM.iSubItem.struct = 0 'first column LVITEM.cchTextMax.struct = 32 LVITEM.pszText$.struct = space$(32) LVITEM.stateMask.struct = LVIS.SELECTED CallDLL #user32, "SendMessageA", _ hwndLV As long, _ LVM.GETITEMA As long, _ index As long, _ 'index of row LVITEM As struct, _ r As long state = LVITEM.state.struct 'selected state of item if state and LVIS.SELECTED then txt$=winstring(LVITEM.pszText$.struct) notice "Selected: ";txt$ exit for end if next if txt$="" then notice "No selection." txt$="" wait [add] 'make sure no item is in selected state: LVITEM.stateMask.struct = LVIS.SELECTED 'bit to set LVITEM.state.struct = LVIS.UNSELECTED CallDLL #user32, "SendMessageA", _ hwndLV As long, _ LVM.SETITEMSTATE As long, _ -1 As long, _ 'change applies to all items LVITEM As struct, _ r As long CallDLL #user32, "SendMessageA", _ hwndLV As long, _ LVM.GETITEMCOUNT As long, _ 0 As long, _ 'always 0 0 As long, _ 'always 0 count As long name$="No Name" prompt "Name?";name$ if name$="" then name$="No Name" 'insert next row, first column LVITEM.mask.struct = LVIF.TEXT LVITEM.iItem.struct = count 'next row LVITEM.iSubItem.struct = 0 'first column LVITEM.pszText$.struct = name$ CallDLL #user32, "SendMessageA", _ hwndLV As long, _ LVM.INSERTITEM As long, _ 0 As long, _ LVITEM As struct, _ r As long level$="No Level" prompt "Level?";level$ if level$="" then level$="No Level" 'add second column to row LVITEM.iItem.struct = count 'next row LVITEM.iSubItem.struct = 1 'second column LVITEM.pszText$.struct = level$ CallDLL #user32, "SendMessageA", _ hwndLV As long, _ LVM.SETITEM As long, _ 0 As long, _ LVITEM As struct, _ r As long print #1.s, "List count: ";count+1 wait [delete]'get user selection and delete 'get number of items in list: CallDLL #user32, "SendMessageA", _ hwndLV As long, _ LVM.GETITEMCOUNT As long, _ 0 As long, _ 'always 0 0 As long, _ 'always 0 total As long for index = 0 to total-1 'check each row LVITEM.mask.struct = LVIF.STATE LVITEM.iItem.struct = index 'row LVITEM.iSubItem.struct = 0 'first column LVITEM.stateMask.struct = LVIS.SELECTED CallDLL #user32, "SendMessageA", _ hwndLV As long, _ LVM.GETITEMA As long, _ index As long, _ 'index of row LVITEM As struct, _ r As long state = LVITEM.state.struct 'selected state of item if state and LVIS.SELECTED then CallDLL #user32, "SendMessageA", _ hwndLV As long, _ LVM.DELETEITEM As long, _ index As long, _ LVITEM As struct, _ r As long exit for end if next print #1.s, "List count: ";total-1 wait [quit] calldll #MsgHook, "UnhookMsgHook", hHook as long, ret as void close #MsgHook calldll #user32, "DestroyWindow", _ hwndLV as long, re as long ' Close handles. close #1:end 'Function to determine if a file exists function fileExists(path$, filename$) files path$, filename$, info$() fileExists = val(info$(0, 0)) 'non zero is true end function [[code]]