|
Post by metro on Jan 10, 2020 23:11:10 GMT -5
I have a fine example of capturing a doubleclick in a listview using message-hook but am unable to find any documentation so show how it works I am just a the start of the journey when it comes to understanding windows messages and sub-classing.
WMLiberty is capable of solving my problem, however my limited understanding is making this difficult to enable.
Is there a chance that someone could post a solution or in fact an outline of how to of tackling the problem. It would be most helpful. the message-hook solution is on the same post above.
Thanks in advance
sorry
|
|
|
Post by metro on Jan 11, 2020 2:23:18 GMT -5
I was hoping to get this done without resorting to asking for help BUT.... I have managed to get the doublclick to function but I do not understand what I am missing when trying to put "adding" and "editing" into SUBS and FUNCTIONS that's the problem with cut n paste with limited knowledge
any help appreciated
EDIT..... Happy with the end result just need to create a popup to edit fields
A Big thank you to Brandon for the code and Brad Moore for WMLiberty
'NoMainWin Global False : False = 0 Global True : True = 1 Global currentRow : currentRow = 0 dim ITEM$(13) listViewHandle(0) = _NULL
'create structs Struct NMHDR, _ hwndFrom As ULong, _ idFrom As ULong, _ code As Long
Struct NMITEMACTIVATE, _ hdr.hwndFrom As ULong, _ hdr.idFrom As ULong, _ hdr.code As Long, _ iItem As Long, _ iSubItem As Long, _ uNewState As ULong, _ uOldState As ULong, _ uChanged As ULong, _ ptAction.x As Long, _ ptAction.y As Long, _ lParam As Long, _ uKeyFlags As ULong
Call initializeListViewConstants
ITEM$(0)="January" ITEM$(1)="February" ITEM$(2)="March" ITEM$(3)="April" ITEM$(4)="May" ITEM$(5)="June" ITEM$(6)="July" ITEM$(7)="August" ITEM$(8)="September" ITEM$(9)="October" ITEM$(10)="November" ITEM$(11)="December" WindowWidth = 830 WindowHeight = 635 Button #Example.btnAddItem, "Add Item", AddItem, UL, 5, (WindowHeight - 60) Button #Example.btnEditItem, "Edit Item", EditItem, UL, 202.5, (WindowHeight - 65) Button #Example.btnDeleteItem, "Delete Item", DeleteItem, UL, 405, (WindowHeight - 65)
Open "ListView Example" For Window As #Example Call InitCommonControls style = _WS_CHILD Or _WS_VISIBLE Or listViewConstants.LVS.NOSORTHEADER.struct _ Or listViewConstants.LVS.REPORT.struct Or listViewConstants.LVS.SHOWSELALWAYS.struct _ Or listViewConstants.LVS.SINGLESEL.struct styleEx = _WS_EX_CLIENTEDGE 'Or _WS_EX_DLGMODALFRAME 'Or listViewConstants.LVS.EX.DOUBLEBUFFER.struct
listViewHandle(0) = CreateListView(style, styleEx, Hwnd(#Example), GetWindowLong(Hwnd(#Example), _GWL_HINSTANCE), 8, 23, 805, 244) result = setListViewFullRowSelect(listViewHandle(0))
'HEADER LABELS FOR A=0 to 11 LVwidth=67 result = createNewListColumn(listViewHandle(0),A,LVwidth,ITEM$(A)) NEXT A result = listViewShowGrid(listViewHandle(0))
'created 2nd listview listViewHandle(1) = CreateListView(style, styleEx, Hwnd(#Example), GetWindowLong(Hwnd(#Example), _GWL_HINSTANCE), 5, 270, 220, 244) result = setListViewFullRowSelect(listViewHandle(1)) result = listViewShowGrid(listViewHandle(1)) result = createNewListColumn(listViewHandle(1), 0, 70, " Item 1") result = createNewListColumn(listViewHandle(1), 1, 70, " Item 2") result = createNewListColumn(listViewHandle(1), 2, 70, " Item 3") result = setListViewFullRowSelect(listViewHandle(1)) result = listViewShowGrid(listViewHandle(1))
#Example "TrapClose Quit"
Open "WMLiberty" For DLL As #wmlib hwndParent = HWnd(#Example) Callback lpfn, OnNotify( ULong, ULong, ULong, ULong ), Long Call SetWMHandler HWnd(#Example), _WM_NOTIFY, lpfn, -1 ''''changed here
While Hwnd(#Example) Scan Wend
SUB Quit handle$ result = DestroyWindow(listViewHandle(0)) result = DestroyWindow(listViewHandle(1)) Close #handle$ close #wmlib End END SUB
SUB AddItem handle$
result = AddListViewData(listViewHandle(0), currentRow, 0, ITEM$(0)) for B=1 to 11 result = EditListViewData(listViewHandle(0), currentRow, B, ITEM$(B)) next B ' result = AddListViewData(listViewHandle(0), currentRow, 0, "Data1") ' result = EditListViewData(listViewHandle(0), currentRow, 1, "Data2") ' result = EditListViewData(listViewHandle(0), currentRow, 2, "Data3") result = SelectListViewRow(listViewHandle(0), currentRow, True) currentRow = (currentRow + 1) END SUB
SUB EditItem handle$
numListViewEntries = GetListViewItemCount(listViewHandle(0)) If Not(numListViewEntries) Then Exit Sub row = GetSelectedListViewRow(listViewHandle(0)) item1$ = GetListViewText$(listViewHandle(0), row, 0) item2$ = GetListViewText$(listViewHandle(0), row, 1) item3$ = GetListViewText$(listViewHandle(0), row, 2)
result = EditListViewData(listViewHandle(0), row, 0, GetListViewText$(listViewHandle(0), row, 0) + " Edited") result = EditListViewData(listViewHandle(0), row, 1, GetListViewText$(listViewHandle(0), row, 1) + " Edited") result = EditListViewData(listViewHandle(0), row, 2, GetListViewText$(listViewHandle(0), row, 2) + " Edited")
result = SelectListViewRow(listViewHandle(0), row, True) END SUB
SUB DeleteItem handle$
numListViewEntries = GetListViewItemCount(listViewHandle(0)) If Not(numListViewEntries) Then Exit Sub row = GetSelectedListViewRow(listViewHandle(0)) result = SendMessageLVITEMStruct(listViewHandle(0), listViewConstants.LVM.DELETEITEM.struct, row) currentRow = (currentRow - 1) END SUB
SUB InitCommonControls CallDLL #comctl32, "InitCommonControls", ret As void END SUB
SUB initializeListViewConstants 'Create the structs for ListViews 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 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 LVFINDINFO, flags As ulong, _ psz As ptr, _ lParam As ulong, _ pt As ulong, _ 'point structure vkDirection As ulong
Struct listViewConstants, LVP.DBLCLK As long, _ LVS.REPORT As long, _ LVS.SINGLESEL As long, _ LVS.SHOWSELALWAYS As long, _ LVS.NOSORTHEADER As long, _ LVS.EXDOUBLEBUFFER As long, _ LVS.EX.FULLROWSELECT As long, _ LVS.EX.CHECKBOXES As long, _ LVIS.FOCUSED As long, _ LVIS.UNSELECTED As long, _ LVIS.SELECTED As long, _ LVIS.CHECKED As long, _ LVIS.UNCHECKED As long, _ LVIS.STATEIMAGEMASK As long, _ LVIF.TEXT As long, _ LVIF.STATE As long, _ LVIR.BOUNDS As long, _ LVFI.STRING As long, _ LVFI.PARTIAL As long, _ LVN.ITEMCHANGED As long, _ LVM.ENSUREVISIBLE As long, _ LVM.SETITEMSTATE As long, _ LVM.GETITEMSTATE As long, _ LVM.GETITEMTEXT As long, _ LVM.FINDITEMA As long, _ LVM.SETITEM As long, _ LVM.GETITEMCOUNT As long, _ LVM.GETITEMA As long, _ LVM.GETSUBITEMRECT As long, _ LVM.DELETEITEM As long, _ LVM.INSERTITEM As long, _ LVM.INSERTCOLUMN As long, _ LVM.SETEXTENDEDLISTVIEWSTYLE As long 'LVM_FIRST = &H1000 or 4096 listViewConstants.LVP.DBLCLK.struct = False listViewConstants.LVS.REPORT.struct = 1 listViewConstants.LVS.SINGLESEL.struct = 4 listViewConstants.LVS.SHOWSELALWAYS.struct = 8 listViewConstants.LVS.NOSORTHEADER.struct = 32768 listViewConstants.LVS.EXDOUBLEBUFFER.struct = 10000 listViewConstants.LVS.EX.FULLROWSELECT.struct = 32 listViewConstants.LVS.EX.CHECKBOXES.struct = 4 listViewConstants.LVIS.FOCUSED.struct = 1 listViewConstants.LVIS.UNSELECTED.struct = 0 listViewConstants.LVIS.SELECTED.struct = 2 listViewConstants.LVIS.CHECKED.struct = 8192 listViewConstants.LVIS.UNCHECKED.struct = 4096 listViewConstants.LVIS.STATEIMAGEMASK.struct = 61440 listViewConstants.LVIF.TEXT.struct = 1 listViewConstants.LVIF.STATE.struct = 8 listViewConstants.LVIR.BOUNDS.struct = 0 listViewConstants.LVFI.STRING.struct = 2 listViewConstants.LVFI.PARTIAL.struct = 8 listViewConstants.LVN.ITEMCHANGED.struct = -101 listViewConstants.LVM.ENSUREVISIBLE.struct = 4115 listViewConstants.LVM.SETITEMSTATE.struct = 4139 listViewConstants.LVM.GETITEMSTATE.struct = 4140 listViewConstants.LVM.GETITEMTEXT.struct = 4141 listViewConstants.LVM.FINDITEMA.struct = 4109 listViewConstants.LVM.SETITEM.struct = 4102 listViewConstants.LVM.GETITEMCOUNT.struct = 4100 listViewConstants.LVM.GETITEMA.struct = 4101 listViewConstants.LVM.GETSUBITEMRECT.struct = 4152 listViewConstants.LVM.DELETEITEM.struct = 4104 listViewConstants.LVM.INSERTITEM.struct = 4103 listViewConstants.LVM.INSERTCOLUMN.struct = 4123 listViewConstants.LVM.SETEXTENDEDLISTVIEWSTYLE.struct = 4150 END SUB
FUNCTION CreateListView(ByRef style, ByRef styleEx, ByRef hParent, ByRef hInstance, ByRef xloc, ByRef yloc, ByRef width, ByRef height) className$ = "SysListView32" + chr$(0) CallDLL #user32, "CreateWindowExA", styleEx As ulong, _ ' extended style className$ As ptr, _ ' class name "" As ptr, _ style As ulong, _ ' style xloc As long, _ ' left x yloc As long, _ ' top y width As long, _ ' width height As long, _ ' height hParent As ulong, _ ' parent hWnd _NULL As ulong, _ hInstance As ulong, _ ' hInstance _NULL As ulong, _ CreateListView As ulong 'Hwnd to ListView 'LVCF.WIDTH = 2 : LVCF.TEXT = 4 LVCOLUMN.mask.struct = LVCF.WIDTH OR LVCF.TEXT END FUNCTION
FUNCTION GetWindowLong(hWnd, index) CallDLL #user32, "GetWindowLongA", hWnd As ulong, _ index As long, _ GetWindowLong As long END FUNCTION
FUNCTION GetListViewItemCount(hWndLV) GetListViewItemCount = SendMessage(hWndLV, listViewConstants.LVM.GETITEMCOUNT.struct, 0, 0) END FUNCTION
FUNCTION createNewListColumn(hListView, columnIndex, columnWidth, headerCaption$) LVCOLUMN.cx.struct = columnWidth LVCOLUMN.pszText.struct = headerCaption$ LVCF.WIDTH = 2 : LVCF.TEXT = 4 LVCOLUMN.mask.struct = LVCF.WIDTH OR LVCF.TEXT createNewListColumn = SendMessageLVCOLUMNStruct(hListView, listViewConstants.LVM.INSERTCOLUMN.struct, columnIndex) END FUNCTION
FUNCTION AddListViewData(hWndLV, row, column, myData$) LVITEM.mask.struct = listViewConstants.LVIF.TEXT.struct LVITEM.iItem.struct = row LVITEM.iSubItem.struct = column LVITEM.pszText.struct = myData$ result = SendMessageLVITEMStruct(hWndLV, listViewConstants.LVM.INSERTITEM.struct, 0) AddListViewData = SendMessage(hWndLV, listViewConstants.LVM.GETITEMSTATE.struct, 0, 0) END FUNCTION
FUNCTION EditListViewData(hWndLV, row, column, myData$) LVITEM.mask.struct = listViewConstants.LVIF.TEXT.struct LVITEM.iItem.struct = row LVITEM.iSubItem.struct = column LVITEM.pszText.struct = myData$ EditListViewData = SendMessageLVITEMStruct(hWndLV, listViewConstants.LVM.SETITEM.struct, 0) END FUNCTION
FUNCTION SelectListViewRow(hWndLV, row, setFocus) LVITEM.iItem.struct = row LVITEM.iSubItem.struct = 0 LVITEM.mask.struct = listViewConstants.LVIF.STATE.struct LVITEM.state.struct = listViewConstants.LVIS.SELECTED.struct If setFocus = True Then LVITEM.state.struct = (LVITEM.state.struct Or listViewConstants.LVIS.FOCUSED.struct) End If 'SelectListViewRow = SetFocus(hWndLV) SelectListViewRow = SendMessage(hWndLV, listViewConstants.LVM.ENSUREVISIBLE.struct, row, False) SelectListViewRow = SendMessageLVITEMStruct(hWndLV, listViewConstants.LVM.SETITEM.struct, 0) END FUNCTION
FUNCTION setListViewFullRowSelect(hListView) setListViewFullRowSelect = SendMessage(hListView, 4150, 32, 32)'LVS_EX_FULLROWSELECT END FUNCTION
FUNCTION listViewShowGrid(hListView) listViewShowGrid = SendMessage(hListView, 4150, 1, 1)'LVS_EX_GRIDLINES END FUNCTION
FUNCTION SendMessage(hWnd, Msg, wParam, lParam) CallDLL #user32, "SendMessageA" , hWnd As ulong, _ Msg As long, _ wParam As long, _ lParam As long, _ SendMessage As long END FUNCTION
FUNCTION SendMessageLVITEMStruct(hWnd, Msg, wParam) CallDLL #user32, "SendMessageA" , hWnd As ulong, _ Msg As long, _ wParam As long, _ LVITEM As struct, _ SendMessageLVITEMStruct As long END FUNCTION
FUNCTION SendMessageLVCOLUMNStruct(hWnd, Msg, wParam) CallDLL #user32, "SendMessageA" , hWnd As ulong, _ Msg As long, _ wParam As long, _ LVCOLUMN As struct, _ SendMessageLVCOLUMNStruct As long END FUNCTION
FUNCTION DestroyWindow(hWnd) CallDLL #user32, "DestroyWindow", hWnd As ulong, _ DestroyWindow As long END FUNCTION
FUNCTION GetSelectedListViewRow(hWndLV) GetSelectedListViewRow = -1 numListViewEntries = GetListViewItemCount(hWndLV) For row = 0 To (numListViewEntries - 1) LVITEM.mask.struct = listViewConstants.LVIF.STATE.struct LVITEM.iItem.struct = row LVITEM.iSubItem.struct = 0 'first column LVITEM.stateMask.struct = listViewConstants.LVIS.SELECTED.struct result = SendMessageLVITEMStruct(hWndLV, listViewConstants.LVM.GETITEMA.struct, 0) If LVITEM.state.struct And listViewConstants.LVIS.SELECTED.struct Then GetSelectedListViewRow = row Exit Function Else If row = (numListViewEntries - 1) Then GetSelectedListViewRow = -1 Exit Function End If End If Next row END FUNCTION
FUNCTION GetListViewText$(hWndLV, row, column) LVITEM.mask.struct = listViewConstants.LVIF.TEXT.struct LVITEM.iSubItem.struct = column LVITEM.pszText.struct = Space$(_MAX_PATH) + chr$(0) LVITEM.cchTextMax.struct = Len(Winstring(LVITEM.pszText.struct)) EditListViewData = SendMessageLVITEMStruct(hWndLV, listViewConstants.LVM.GETITEMTEXT.struct, row) GetListViewText$ = Trim$(Winstring(LVITEM.pszText.struct)) END FUNCTION
Sub SetWMHandler hWnd, uMsg, lpfnCB, lSuccess CallDLL #wmlib, "SetWMHandler", _ hWnd As ULong, _ uMsg As ULong, _ lpfnCB As ULong, _ lSuccess As Long, _ r As Long End Sub
'Callback function to handle WM_NOTIFY messages Function OnNotify( hWnd, uMsg, wParam, lParam ) NMHDR.struct = lParam Select Case NMHDR.code.struct Case -3 'NM_DBLCLK NMITEMACTIVATE.struct = lParam iItem = NMITEMACTIVATE.iItem.struct If iItem < 0 Then Print "Double-clicked listview background" Else 'For some reason, placing a NOTICE here causes problems. call EditItem handle$
Print "Double-clicked item #"; iItem End If End Select End Function
|
|
|
Post by Rod on Jan 11, 2020 6:53:36 GMT -5
Well the struct does not seem to be getting filled. It sees the doubleclick and your function is called but the NMITEMACTIVATE struct is not getting info. What confuses me is that lParam is used to fill the structs twice without apparent change.
Given the doubleclick works in Brents demo perhaps it is something in the creation of the listview? Out of my depth I am afraid. You might try and wake up Brent on his Bay6 forum.
|
|
|
Post by metro on Jan 11, 2020 6:54:58 GMT -5
Well the struct does not seem to be getting filled. It sees the doubleclick and your function is called but the NMITEMACTIVATE struct is not getting info. What confuses me is that lParam is used to fill the structs twice without apparent change. Given the doubleclick works in Brents demo perhaps it is something in the creation of the listview? Out of my depth I am afraid. You might try and wake up Brent on his Bay6 forum. Yep will do , thanks Rod, out of my depth too
|
|
|
Post by Rod on Jan 11, 2020 10:47:03 GMT -5
I see how lParam is used twice, first time in the short struct to check what message we have then again in the longer struct which actually has the first struct as a header.
|
|
|
Post by Chris Iverson on Jan 11, 2020 14:59:58 GMT -5
I'm thinking something's getting screwed up in how the listview processes messages, because it works fine until you double-click one of the items. When you do, that item gets edited, but then the individual items stop responding to clicks.
If you edit the EditItem sub to comment out each of the calls that results in another SendMessage(), it works fine(although obviously won't actually do anything.)
I'm honestly not sure what's going on.
|
|
|
Post by metro on Jan 11, 2020 17:00:20 GMT -5
Thanks Rod and Chris I'll spend some more time on it today. I could have just settled for the message hook setup I have but I'm trying to implement Brandon's coding style of all subs and functions. And he appears to be happy with Just an edit button. Appreciate you both taking the time....
EDIT
A quick test this morning and I seem to think the code is working as it should but after 5 or 6 double clicks on a row (or multiple rows) it crashes with "stack overflow" more reading required........
|
|
|
Post by metro on Jan 11, 2020 18:41:12 GMT -5
Seems my problem is calling the SUB " EditItem handle$" from the last function in my code can someone smarter than me take a look at how I can call the edit SUb and exit the callback function at the same time I suspect I'm stuck within the callback ... but have limited understanding as to whether that is possible (which maybe is what Chris is eluding to)
thanks.... 'Callback function to handle WM_NOTIFY messages Function OnNotify( hWnd, uMsg, wParam, lParam ) NMHDR.struct = lParam Select Case NMHDR.code.struct Case -3 'NM_DBLCLK NMITEMACTIVATE.struct = lParam iItem = NMITEMACTIVATE.iItem.struct If iItem < 0 Then Print "Double-clicked listview background" Else 'For some reason, placing a NOTICE here causes problems. Print "Double-clicked item #"; iItem ' call EditItem handle$ THIS IS THE CULPRIT End If End Select
End Function
|
|
|
Post by Chris Iverson on Jan 11, 2020 23:57:36 GMT -5
That's kind of what I'm getting at.
In the EditItem sub, the last four lines of code are all calls that make further SendMessage() calls to the list view, some of which may result in further notifications to the main window.
If you comment those lines out, it works fine... but it obviously won't change anything, because you removed all the code that would perform the changes.
I think there's a re-entrancy problem, where the recursive calls for further messages wind up not working.
I have an idea on a possible way to work around that, and I'm testing it now.
EDIT: And the workaround idea worked.
Add a new global variable to the top, EditFlag:
Global EditFlag : EditFlag = 0
At the end of your program setup, before the Quit sub handler, you have the main message loop:
While Hwnd(#Example) Scan Wend
Add these lines after the 'scan' command, but before the 'wend' command:
if EditFlag = 1 then call EditItem handle$ EditFlag = 0 end if
Finally, in the OnNotify callback function, replace the EditItem sub call:
call EditItem handle$
With this:
EditFlag = 1
This moves the call flow around, so that it doesn't wind up going into the WMLiberty handler twice, recursively. It has your program wait to actually handle the edit click event until after it's already returned from the WMLiberty callback.
I don't know if it's a WMLiberty thing, or an LB thing, but whatever's happening is not re-entrant. That is, it can't be safely called while another call to it is being processed.
|
|
|
Post by metro on Jan 12, 2020 0:18:43 GMT -5
|
|
|
Post by metro on Jan 19, 2020 9:17:16 GMT -5
Back for a little more help I'm in the middle of a re-write if I rem out theses two lines Callback lpfn, OnNotify( ULong, ULong, ULong, ULong ), Long Call SetWMHandler HWnd(#Example), _WM_NOTIFY, lpfn, -1 ''''changed here
I can load the data from my file into the listview without hickup but with the two lines left in I get an isEmpty error part way through the loading I'm unsure why the message handler is interfering when a doubleclick is not being issued. Sorry Chris, I hate to ask again
|
|
|
Post by Rod on Jan 19, 2020 15:26:23 GMT -5
I have always found WMLiberty intensive. If you print how often the handler is called it’s a lot. Can you not start the event handler after the file is loaded?
|
|
|
Post by metro on Jan 19, 2020 16:44:58 GMT -5
I have always found WMLiberty intensive. If you print how often the handler is called it’s a lot. Can you not start the event handler after the file is loaded? Thanks Rod, I'll will have to turn it off each time the ListView is loaded...maybe
or the smart move maybe to inject the Msghook Dll and code which has never given any grief.
Thanks for taking a look.
EDIT: Thanks Rod event handler is now turned off and on again after reload. works fine
EDIT 2: throws error after multiple double clicks...back to Msghook just have to get my head around how to find the handle for the ListView as Brandon's method for creating it confuses me somewhat confusion because making CreateListView GLOBAL stops it from being seen
EDIT 3 : I have msghook working as expected how ever when I exit the program WINE crashes, I have updated the zip with the new code. may have to ditch Brandon's all SUB code and go back to BRANCH Labels
listViewHandle(0) = CreateListView(style, styleEx, Hwnd(#Example), GetWindowLong(Hwnd(#Example), _GWL_HINSTANCE), 8, 100, 805, 244) result = setListViewFullRowSelect(listViewHandle(0))
FUNCTION CreateListView(ByRef style, ByRef styleEx, ByRef hParent, ByRef hInstance, ByRef xloc, ByRef yloc, ByRef width, ByRef height) className$ = "SysListView32" + chr$(0) CallDLL #user32, "CreateWindowExA", styleEx As ulong, _ ' extended style className$ As ptr, _ ' class name "" As ptr, _ style As ulong, _ ' style xloc As long, _ ' left x yloc As long, _ ' top y width As long, _ ' width height As long, _ ' height hParent As ulong, _ ' parent hWnd _NULL As ulong, _ hInstance As ulong, _ ' hInstance _NULL As ulong, _ CreateListView As ulong 'Hwnd to ListView 'LVCF.WIDTH = 2 : LVCF.TEXT = 4 LVCOLUMN.mask.struct = LVCF.WIDTH OR LVCF.TEXT END FUNCTION
|
|
|
Post by metro on Jan 25, 2020 19:47:09 GMT -5
I have cut back the code to only show bare essentials for a list view. The program executes as I expect it should but crashes on exit.( I am using Linux+Wine) I'm hoping someone has the time to take a look. I just can't see what is causing the crash. Thanks in Advance
EDIT : Seems it's a wine issue or PlayonLinux at least there is now a working example for any one to use.
'Brandon.bas 'NoMainWin Global False : False = 0 Global True : True = 1 Global currentRow : currentRow = 0 Global EditFlag : EditFlag = 0 listViewHandle(0) = _NULL
Call initializeListViewConstants
WindowWidth = 530 WindowHeight = 335 Button #Example.btnAddItem, "Add Item", AddItem, UL, 5, (WindowHeight - 65) Button #Example.btnEditItem, "Edit Item", EditItem, UL, 202.5, (WindowHeight - 65) Button #Example.btnDeleteItem, "Delete Item", DeleteItem, UL, 405, (WindowHeight - 65) Button #Example.GetMsgHookCallback, "Edit Item" , Checkedit ,UL, 960, 45 ,100 ,25 Open "ListView Example" For Window As #Example
Call InitCommonControls style = _WS_CHILD Or _WS_VISIBLE Or listViewConstants.LVS.NOSORTHEADER.struct _ Or listViewConstants.LVS.REPORT.struct Or listViewConstants.LVS.SHOWSELALWAYS.struct _ Or listViewConstants.LVS.SINGLESEL.struct styleEx = _WS_EX_CLIENTEDGE Or _WS_EX_DLGMODALFRAME 'Or listViewConstants.LVS.EX.DOUBLEBUFFER.struct listViewHandle(0) = CreateListView(style, styleEx, Hwnd(#Example), GetWindowLong(Hwnd(#Example), _GWL_HINSTANCE), 5, 23, 505, 244) result = setListViewFullRowSelect(listViewHandle(0)) result = listViewShowGrid(listViewHandle(0)) result = createNewListColumn(listViewHandle(0), 0, 50, " Item 1") result = createNewListColumn(listViewHandle(0), 1, 100, " Item 2") result = createNewListColumn(listViewHandle(0), 2, 100, " Item 3") #Example "TrapClose Quit"
hParent=Hwnd(#Example) 'ADDED for my Understanding hLV01 = listViewHandle(0)
open "MsgHook" for dll as #MsgHook hMsgProc = hwnd(#Example.GetMsgHookCallback) calldll #MsgHook, "TrapMsgFor",hLV01 as ulong, ret as boolean calldll #MsgHook, "WatchMsg", hLV01 as ulong, _WM_LBUTTONDBLCLK as long, ret as boolean hMsgProc = hwnd(#Example.GetMsgHookCallback) calldll #user32, "GetWindowLongA",hMsgProc as ulong,_GWL_ID as short,callbackID as long calldll #MsgHook, "CreateGetMsgProcHook",hParent as ulong, callbackID as long, _ hMsgProc as ulong, hHook as ulong
'CHECK HANDLES print hLV01;" this is ListView handle hLV01" print hParent;" this is hParent Handle" print While Hwnd(#Example) Scan if EditFlag = 1 then call EditItem handle$ EditFlag = 0 end if Wend
Sub Quit handle$ ' calldll #MsgHook, "UnhookMsgHook", hHook as ulong, ret as void close #MsgHook result = DestroyWindow(listViewHandle(0)) Close #handle$ End End Sub sub Checkedit handle$ EditFlag = 1 end sub
Sub AddItem handle$ result = AddListViewData(listViewHandle(0), currentRow, 0, "Data19") result = EditListViewData(listViewHandle(0), currentRow, 1, "Data2") result = EditListViewData(listViewHandle(0), currentRow, 2, "Data3") result = SelectListViewRow(listViewHandle(0), currentRow, True) currentRow = (currentRow + 1) End Sub
Sub EditItem handle$ numListViewEntries = GetListViewItemCount(listViewHandle(0)) If Not(numListViewEntries) Then Exit Sub row = GetSelectedListViewRow(listViewHandle(0)) item1$ = GetListViewText$(listViewHandle(0), row, 0) item2$ = GetListViewText$(listViewHandle(0), row, 1) item3$ = GetListViewText$(listViewHandle(0), row, 2)
result = EditListViewData(listViewHandle(0), row, 0, GetListViewText$(listViewHandle(0), row, 0) + " Edited") result = EditListViewData(listViewHandle(0), row, 1, GetListViewText$(listViewHandle(0), row, 1) + " Edited") result = EditListViewData(listViewHandle(0), row, 2, GetListViewText$(listViewHandle(0), row, 2) + " Edited")
result = SelectListViewRow(listViewHandle(0), row, True) End Sub
Sub DeleteItem handle$ numListViewEntries = GetListViewItemCount(listViewHandle(0)) If Not(numListViewEntries) Then Exit Sub row = GetSelectedListViewRow(listViewHandle(0)) result = SendMessageLVITEMStruct(listViewHandle(0), listViewConstants.LVM.DELETEITEM.struct, row) currentRow = (currentRow - 1) End Sub
Sub InitCommonControls CallDLL #comctl32, "InitCommonControls", ret As void End Sub
Sub initializeListViewConstants 'Create the structs for ListViews
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 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 LVFINDINFO, flags As ulong, _ psz As ptr, _ lParam As ulong, _ pt As ulong, _ 'point structure vkDirection As ulong
Struct listViewConstants, LVP.DBLCLK As long, _ LVS.REPORT As long, _ LVS.SINGLESEL As long, _ LVS.SHOWSELALWAYS As long, _ LVS.NOSORTHEADER As long, _ LVS.EXDOUBLEBUFFER As long, _ LVS.EX.FULLROWSELECT As long, _ LVS.EX.CHECKBOXES As long, _ LVIS.FOCUSED As long, _ LVIS.UNSELECTED As long, _ LVIS.SELECTED As long, _ LVIS.CHECKED As long, _ LVIS.UNCHECKED As long, _ LVIS.STATEIMAGEMASK As long, _ LVIF.TEXT As long, _ LVIF.STATE As long, _ LVIR.BOUNDS As long, _ LVFI.STRING As long, _ LVFI.PARTIAL As long, _ LVN.ITEMCHANGED As long, _ LVM.ENSUREVISIBLE As long, _ LVM.SETITEMSTATE As long, _ LVM.GETITEMSTATE As long, _ LVM.GETITEMTEXT As long, _ LVM.FINDITEMA As long, _ LVM.SETITEM As long, _ LVM.GETITEMCOUNT As long, _ LVM.GETITEMA As long, _ LVM.GETSUBITEMRECT As long, _ LVM.DELETEITEM As long, _ LVM.INSERTITEM As long, _ LVM.INSERTCOLUMN As long, _ LVM.SETEXTENDEDLISTVIEWSTYLE As long
'LVM_FIRST = &H1000 or 4096 listViewConstants.LVP.DBLCLK.struct = False listViewConstants.LVS.REPORT.struct = 1 listViewConstants.LVS.SINGLESEL.struct = 4 listViewConstants.LVS.SHOWSELALWAYS.struct = 8 listViewConstants.LVS.NOSORTHEADER.struct = 32768 listViewConstants.LVS.EXDOUBLEBUFFER.struct = 10000 listViewConstants.LVS.EX.FULLROWSELECT.struct = 32 listViewConstants.LVS.EX.CHECKBOXES.struct = 4 listViewConstants.LVIS.FOCUSED.struct = 1 listViewConstants.LVIS.UNSELECTED.struct = 0 listViewConstants.LVIS.SELECTED.struct = 2 listViewConstants.LVIS.CHECKED.struct = 8192 listViewConstants.LVIS.UNCHECKED.struct = 4096 listViewConstants.LVIS.STATEIMAGEMASK.struct = 61440 listViewConstants.LVIF.TEXT.struct = 1 listViewConstants.LVIF.STATE.struct = 8 listViewConstants.LVIR.BOUNDS.struct = 0 listViewConstants.LVFI.STRING.struct = 2 listViewConstants.LVFI.PARTIAL.struct = 8 listViewConstants.LVN.ITEMCHANGED.struct = -101 listViewConstants.LVM.ENSUREVISIBLE.struct = 4115 listViewConstants.LVM.SETITEMSTATE.struct = 4139 listViewConstants.LVM.GETITEMSTATE.struct = 4140 listViewConstants.LVM.GETITEMTEXT.struct = 4141 listViewConstants.LVM.FINDITEMA.struct = 4109 listViewConstants.LVM.SETITEM.struct = 4102 listViewConstants.LVM.GETITEMCOUNT.struct = 4100 listViewConstants.LVM.GETITEMA.struct = 4101 listViewConstants.LVM.GETSUBITEMRECT.struct = 4152 listViewConstants.LVM.DELETEITEM.struct = 4104 listViewConstants.LVM.INSERTITEM.struct = 4103 listViewConstants.LVM.INSERTCOLUMN.struct = 4123 listViewConstants.LVM.SETEXTENDEDLISTVIEWSTYLE.struct = 4150 End Sub
Function CreateListView(ByRef style, ByRef styleEx, ByRef hParent, ByRef hInstance, ByRef xloc, ByRef yloc, ByRef width, ByRef height) className$ = "SysListView32" + chr$(0) CallDLL #user32, "CreateWindowExA", styleEx As ulong, _ ' extended style className$ As ptr, _ ' class name "" As ptr, _ style As ulong, _ ' style xloc As long, _ ' left x yloc As long, _ ' top y width As long, _ ' width height As long, _ ' height hParent As ulong, _ ' parent hWnd _NULL As ulong, _ hInstance As ulong, _ ' hInstance _NULL As ulong, _ CreateListView As ulong 'Hwnd to ListView
'LVCF.WIDTH = 2 : LVCF.TEXT = 4 LVCOLUMN.mask.struct = LVCF.WIDTH OR LVCF.TEXT print hParent;" hParent in the CreateListView Function" End Function
Function GetWindowLong(hWnd, index) CallDLL #user32, "GetWindowLongA", hWnd As ulong, _ index As long, _ GetWindowLong As long print GetWindowLong;" GetWindowLong" print hWnd ;" hWnd" End Function
Function GetListViewItemCount(hWndLV) GetListViewItemCount = SendMessage(hWndLV, listViewConstants.LVM.GETITEMCOUNT.struct, 0, 0) End Function
Function createNewListColumn(hListView, columnIndex, columnWidth, headerCaption$) LVCOLUMN.cx.struct = columnWidth LVCOLUMN.pszText.struct = headerCaption$ LVCF.WIDTH = 2 : LVCF.TEXT = 4 LVCOLUMN.mask.struct = LVCF.WIDTH OR LVCF.TEXT createNewListColumn = SendMessageLVCOLUMNStruct(hListView, listViewConstants.LVM.INSERTCOLUMN.struct, columnIndex) End Function
Function AddListViewData(hWndLV, row, column, myData$) LVITEM.mask.struct = listViewConstants.LVIF.TEXT.struct LVITEM.iItem.struct = row LVITEM.iSubItem.struct = column LVITEM.pszText.struct = myData$ result = SendMessageLVITEMStruct(hWndLV, listViewConstants.LVM.INSERTITEM.struct, 0) AddListViewData = SendMessage(hWndLV, listViewConstants.LVM.GETITEMSTATE.struct, 0, 0) End Function
Function EditListViewData(hWndLV, row, column, myData$) LVITEM.mask.struct = listViewConstants.LVIF.TEXT.struct LVITEM.iItem.struct = row LVITEM.iSubItem.struct = column LVITEM.pszText.struct = myData$ EditListViewData = SendMessageLVITEMStruct(hWndLV, listViewConstants.LVM.SETITEM.struct, 0) End Function
Function SelectListViewRow(hWndLV, row, setFocus) LVITEM.iItem.struct = row LVITEM.iSubItem.struct = 0 LVITEM.mask.struct = listViewConstants.LVIF.STATE.struct LVITEM.state.struct = listViewConstants.LVIS.SELECTED.struct If setFocus = True Then LVITEM.state.struct = (LVITEM.state.struct Or listViewConstants.LVIS.FOCUSED.struct) End If 'SelectListViewRow = SetFocus(hWndLV) SelectListViewRow = SendMessage(hWndLV, listViewConstants.LVM.ENSUREVISIBLE.struct, row, False) SelectListViewRow = SendMessageLVITEMStruct(hWndLV, listViewConstants.LVM.SETITEM.struct, 0) End Function
Function setListViewFullRowSelect(hListView) setListViewFullRowSelect = SendMessage(hListView, 4150, 32, 32)'LVS_EX_FULLROWSELECT End Function
Function listViewShowGrid(hListView) listViewShowGrid = SendMessage(hListView, 4150, 1, 1)'LVS_EX_GRIDLINES End Function
Function SendMessage(hWnd, Msg, wParam, lParam) CallDLL #user32, "SendMessageA" , hWnd As ulong, _ Msg As long, _ wParam As long, _ lParam As long, _ SendMessage As long End Function
Function SendMessageLVITEMStruct(hWnd, Msg, wParam) CallDLL #user32, "SendMessageA" , hWnd As ulong, _ Msg As long, _ wParam As long, _ LVITEM As struct, _ SendMessageLVITEMStruct As long End Function
Function SendMessageLVCOLUMNStruct(hWnd, Msg, wParam) CallDLL #user32, "SendMessageA" , hWnd As ulong, _ Msg As long, _ wParam As long, _ LVCOLUMN As struct, _ SendMessageLVCOLUMNStruct As long End Function
Function DestroyWindow(hWnd) CallDLL #user32, "DestroyWindow", hWnd As ulong, _ DestroyWindow As long End Function
Function GetSelectedListViewRow(hWndLV) GetSelectedListViewRow = -1
numListViewEntries = GetListViewItemCount(hWndLV) For row = 0 To (numListViewEntries - 1) LVITEM.mask.struct = listViewConstants.LVIF.STATE.struct LVITEM.iItem.struct = row LVITEM.iSubItem.struct = 0 'first column LVITEM.stateMask.struct = listViewConstants.LVIS.SELECTED.struct result = SendMessageLVITEMStruct(hWndLV, listViewConstants.LVM.GETITEMA.struct, 0) If LVITEM.state.struct And listViewConstants.LVIS.SELECTED.struct Then GetSelectedListViewRow = row Exit Function Else If row = (numListViewEntries - 1) Then GetSelectedListViewRow = -1 Exit Function End If End If Next row
End Function
Function GetListViewText$(hWndLV, row, column) LVITEM.mask.struct = listViewConstants.LVIF.TEXT.struct LVITEM.iSubItem.struct = column LVITEM.pszText.struct = Space$(_MAX_PATH) + chr$(0) LVITEM.cchTextMax.struct = Len(Winstring(LVITEM.pszText.struct)) EditListViewData = SendMessageLVITEMStruct(hWndLV, listViewConstants.LVM.GETITEMTEXT.struct, row) GetListViewText$ = Trim$(Winstring(LVITEM.pszText.struct)) End Function
|
|
Tasp
Full Member
Posts: 215
|
Post by Tasp on May 22, 2020 7:46:08 GMT -5
This too crashes out Liberty for me, unless its run in the debugger. I'm using Win10 and LB 4.5.1
When code is run the debugger it runs significantly slower, so I thought, there is the problem!
So I added a Sleep command inside the While/Wend which sorts the issue.
'CHECK HANDLES
print hLV01;" this is ListView handle hLV01"
print hParent;" this is hParent Handle"
print
While Hwnd(#Example)
Scan
call Sleep 10 'Sleep for 10 milliseconds
if EditFlag = 1 then
call EditItem handle$
EditFlag = 0
end if
Wend
Sub Sleep ms
CallDLL #kernel32, "Sleep", ms as long, ret as void
End Sub
|
|