Older Version
Newer Version
RodBird
Nov 25, 2015
==Trapping a Double Click in a Listview=====Demo===Demo by Eldron Gill ([[user:eaglesoar]])=== //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.EachEach column has its own column header.TheThe listview is far more complex than the ordinary listbox.WhileWhile the listbox is easily populated from its associated array, the listview requires each item to be individually assigned.ThisThis assignment is accomplished with a rather complicated series of structs and API calls.// [[image:LVIllustration.png]] //A listview demo is included in Alyce Watson's ([[user:Alyce]]) **[[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.EldronEldron 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,Fortunately, Dennis McKinney ([[user:DennisMcK]]) offers the free **[[http://syberden.net/libertybelle/|msghook.dll]]** designed specifically for this purpose.HereHere is Eldron's modification of Alyce's listview demo to allow selection by a double left mouse click.AsAs stated in the code, **[[http://syberden.net/libertybelle/|msghook.dll]]** must be accessible within the program folder.// //It should be mentioned that Eldron sought and received permission from both Alyce and Dennis before submitting this demo.OurOur thanks to all three for this collaboration and sharing of resources and knowledge.// [[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 longstruct msg,_ hndl as ulong,_ 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 ulong,_ 'parent window handle _GWL_HINSTANCE As long,_'flag to retrieve instance handle hInstance As ulong '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 ulong,_ ' parent hWnd 0 as long,_ hInstance as ulong,_ ' 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 ulong, _ 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 ulong, _ 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 ulong, _ 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 ulong, _ 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 ulong, _ 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 ulong, _ 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 ulong, _ 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 #MsgHookhMsgProc = hwnd(#1.GetMsgHookCallback) calldll #MsgHook, "TrapMsgFor",hwndLV as ulong, ret asbooleanlong calldll #MsgHook, "WatchMsg", hwndLV as ulong, _WM_LBUTTONDBLCLK as long, ret asbooleanlong hMsgProc = hwnd(#1.GetMsgHookCallback) calldll #user32, "GetWindowLongA",hMsgProc as ulong,_GWL_ID as short,callbackID as long calldll #MsgHook, "CreateGetMsgProcHook", hwndParent as ulong, callbackID as long, _ hMsgProc as ulong, hHook as ulongwait [choice] 'determine user selectioncalldll #MsgHook, "GetMsg", msg as struct, ret as void 'get number of items in list:CallDLL #user32, "SendMessageA", _ hwndLV As ulong, _ 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 ulong, _ 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 ulong, _ LVM.SETITEMSTATE As long, _ -1 As long, _ 'change applies to all items LVITEM As struct, _ r As long CallDLL #user32, "SendMessageA", _ hwndLV As ulong, _ 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 ulong, _ 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 ulong, _ 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 ulong, _ 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 ulong, _ 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 ulong, _ 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 ulong, ret as void close #MsgHook calldll #user32, "DestroyWindow", _ hwndLV as ulong, 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]]