LCF-AT Posted August 4, 2016 Posted August 4, 2016 Hi guys, I have again a little question and need some input from others.This time I would like ask how you do handle dynamic controls. Example: Just imagine you do create a tab control and each tab does show new controls like a listview / box and more and you can also delete and move tabs to other positions etc.The question I have is how to store all handles of all controls what does belong to one and same tab?Lets say you create a tab control with 5 tabs and 5 Listview controls then you can store all LV handles in a free section from first tab till last tab in a row.Now if you do move a tab to other position like in browser then you can also move the handles into free section to new position.Also if you delete a tab then you can also delete the LV handle from free section and move all following handle postions 4 bytes up.All almost ok so far.But what is if you have a lot more to handle?How to store all the infos which belongs to one tab correctly and smart?As I said its just a question and wanted to know how you do handle such issues then I think my handling is not so smart. greetz
0xNOP Posted August 4, 2016 Posted August 4, 2016 (edited) I think you can use a mixture of dynamic multi-dimensional arrays, this way you can set them, retrieve them, and I also heard you can adjust them accordingly with some memory allocation later on at runtime so it fits perfectly for the job. You could do a 4x4 Multi-Dimensional Array, like so: then: You can say: a[0] // Will store our LV Handlers. a[1] //Tab 1 / Row Position ... ? / Data ... ? Edited August 4, 2016 by 0xNOP 1
LCF-AT Posted August 4, 2016 Author Posted August 4, 2016 Hi again, thanks for the info.Its still tricky.The only thing what I could maybe do its to create a static struct to store all handles of one tab into a section. Section: -------------------------------- 00000000 | TabIndex 00000004 | Handle1 00000008 | Handle2 0000000C | Handle3 00000010 | 00000000 00000014 | TabIndex 00000018 | Handle4 0000001C | Handle5 00000020 | Handle6 00000024 | Handle7 00000028 | FFFFFFFF etc Maybe in blocks of 14 bytes lenght to store max the tab index at top of block + max 4 handles below.Hhmmmm.Its also not so smart or?If I exchange first tab with second tab then I also need first to backup both blocks and exchange them into store section or just only the tabindex value.What is if I delete one tab....then I also need to move all below one block higher.So anyhow there comes no better idea in my head how to handle this. greetz 1
LCF-AT Posted April 22, 2017 Author Posted April 22, 2017 Hi again, so I have another question about building any smart arrays.I am still fighting to create something simple and good working way to handle the entire stuff. Example: Almost same as I did post above.I have LVs with Tabs (tab x does show LV x) and 5 rows in each LV and dynamic entrys in the LV etc.Now I have that problem... lets say I have 5 entrys in LV 1. LV 1 -------------------------- A | B | Count -------------------------- 1 | NY | 1000 2 | IL | 1001 3 | NH | 2222 4 | BE | 3001 5 | UR | 5555 -------------------------- Thats the example content of my LV 1.I also can change the positions of all lines (line 1 to line 2 or 3 etc).All clear & ok so far.Now the problem I have...I do select any line in this LV (maybe line 1) and I do start now a new thread (thread does count all seconds since the thread was startet and does add each second into the count row of the line I have selected).Now right before I do start the thread I have to send also the info into this thread which line I have selected (in this case LV 1 handle and line 1 in the LV).All ok so far.The problem now is that the value of the selected line I did send with into the thread is a static information. Thread has info about the LV handle which keeps same & if LV keeps alive if it wasnt deleted.The line info (line 1 position) instead can be changed by the user if the user does change the line positions in the LV itself. Again: I do select line 1 and start a thread to count elapsed time seconds into the count row of line 1.Now the thread does run and also has the into about LV handle and the line 1 to fill the new datas into the count row of line 1 = working so far.Now the thread is running and now lets say I wanna change the line position 1 with the line 5 during the thread is running.Now I have changed line 1 with line 5 BUT my working thread dosent know that I did change the line.So the question is how to tell my thread that line 1 is now on line 5 to fill another count infos into line 5 and no more into line 1.You know what I mean right?So i want prevent filling count datas into any wrong line.So how can I check this and update the line info into my thread BEFORE the thread does write new infos into line x?So that the tricky part for me to handle that anyhow without to disable line movings in the LV itself. The question is how to handle this on any good and possible simple way without to make any mistakes and to prevent sending datas into wrong lines.So has anyone of you any ideas how it could be handled nice & correctly? Are there maybe other methods I could use and dont know yet?Maybe something like to mark a selected with one thread (make it fix / lock anyhow) so that it will also send automatically the datas into the right line also if I have changed the position of this line in the LV?So you can also change the row positions from left to right or else without to have that problems sending the datas into right row you know so maybe there is also something like this for line positions too or? Maybe anyone has some ideas to handle that problem I have with that LV positions etc.Some help would be very nice again of course just to bring me on the right direction. Thank you
fearless Posted April 22, 2017 Posted April 22, 2017 (edited) well each LVITEM / LV_ITEM (https://msdn.microsoft.com/en-us/library/windows/desktop/bb774760(v=vs.85).aspx) does also have an lParam field which you can use for storing a unique index, then it shouldn't matter if the listitem moves position as its original designated index (iItem) is always what it was when it was created and stored as lParam. you could set or get lParam something like this: ListViewSetItemParam PROC PUBLIC hListview:DWORD, nItemIndex:DWORD, ParamValue:DWORD LOCAL LVItem:LV_ITEM mov LVItem.imask,LVIF_PARAM mov eax, nItemIndex mov LVItem.iItem, eax mov LVItem.iSubItem,0 mov eax, ParamValue push eax pop LVItem.lParam invoke SendMessage, hListview, LVM_SETITEM, 0, Addr LVItem ret ListViewSetItemParam ENDP ListViewGetItemParam PROC PUBLIC hListview:DWORD, nItemIndex:DWORD LOCAL LVItem:LV_ITEM mov LVItem.imask,LVIF_PARAM mov eax, nItemIndex mov LVItem.iItem, eax mov LVItem.iSubItem,0 invoke SendMessage, hListview, LVM_GETITEM, nItemIndex, Addr LVItem .iF eax == TRUE mov eax, LVItem.lParam .ELSE mov eax, -1 .ENDIF ret ListViewGetItemParam ENDP Edited April 22, 2017 by fearless add code for set/get lparam 1
LCF-AT Posted April 22, 2017 Author Posted April 22, 2017 Hi again, could you explain it a little more?So before I start any thread I do read the selected line of LV & handle of LV.Thats the 2 infos I have and send them also in the thread where it does fill new results into line 2. So do you mean I should use the ListViewSetItemParam (hListview = handle & nItemIndex = selected line & what do I set in ParamValue into?) and in my thread I do use ListViewGetItemParam before I write something into LV?Hhmmm,somehow I dont get it yet. greetz
fearless Posted April 23, 2017 Posted April 23, 2017 It depends on how your setting the information in the listview. But ordinarily if you have the listitem's index you can use that to set text for the item or subitems. So if you have already got that info then should be ok, if not then you can send a parameter to the thread, like a special block of data that holds some useful information: SOMEDATA STRUCT hListview DD 0 ; handle to listview iItem DD 0 ; item index no SOMEDATA ENDS when you use LVM_INSERTITEM or similar it returns index of new item or -1 if unsuccessful. You can store that in the lParam of the listitem, but only if required, otherwise you can store other info in this field So really depends on the code works and how exactly the information is relayed back and forth i suppose.
LCF-AT Posted April 23, 2017 Author Posted April 23, 2017 Hi again, still dont get it. Once again.I have a LV with some lines into and some rows.If I start the thread I read the selected line position & handle of LV and this data I send with in my thread.Now if the thread does run it does write new datas into the line x row y.If I change the position of line x with the mouse to other position then the thread will of course write new datas into wrong line now. checkoIN.p_loc = Selected line info I did read before I did start the thread TIMEBUFF = Time Data info I do read in the thread checkoIN.p_hwnd = Handle of LV I did read before starting the thread mov lvis.imask, LVIF_TEXT mov ecx, checkoIN.p_loc mov lvis.iItem, ecx mov lvis.iSubItem, 4 lea ecx, TIMEBUFF mov lvis.pszText, ecx mov lvis.cchTextMax, sizeof TIMEBUFF invoke SendMessage,checkoIN.p_hwnd, LVM_SETITEM, 0, addr lvis I only use SETITEM to set actually infos into right location x and subitem 4.Thats all. Now before I do write go on infos into location x I need to know whether location x is still same or not to prevent writing new infos into wrong location.So how could LPARAM help or the ListViewSetItemParam & ListViewGetItemParam procs? greetz
fearless Posted April 23, 2017 Posted April 23, 2017 Depends on how the listitems are being moved, as in is the listview being generated anew each time by deleting all listitems and added them again. If the index of positions is changing then its harder to define what the original item is or was. In some cases it might be easier to sort all the data out in an array before it is added to the listview, and use the lParam value as a way of tracking the offset into the array. otherwise you can loop through all listview items and read the lParam value and see if that == original item that was sent to the thread. Requires the lParam of the original item to have been sent to the thread. So its just using lParam as a master index, but that only works in certain circumstances and depends on how the listitems are added/deleted/moved etc - in some cases it might not be appropriate to use this, so the other suggestion of using an array to map all the data might be handier. 1
LCF-AT Posted April 23, 2017 Author Posted April 23, 2017 Hi again, so I have checked this again and using Param isnt good in my case so its already used for sorting process where it does set Param index same as LV count lines.So if I sort a row then all entrys get also a Param.If I dont sort then no Param is used but if I now set a custom Param at the line I have selected then it will keep on this line also if I move the lines to other position via drag / drop.In this case I also would need to move the Param too during a position move.Also if this would work then I should first check where the set Param value x is to find in my LV in my thread and I couldnt just use the Param value x to update any text entry. Before thread starts: I get selected line x = 3 example.Now set a Param value of 111 for this line My thread: Has info about Line 3 and handle.Now I need to search for Param value 111 in entire LV which belongs to handle I did send with.If it was found then I also have the right line x and then I could use it to send new text into.But as I said if I do a sort then the Param does change to 2 = no more 111 into. Maybe I need to disable sort function so long the thread is working or I need to find any other way & solution. greetz
LCF-AT Posted April 24, 2017 Author Posted April 24, 2017 Hi again, ok I tried something else now.So I did just add another row into my LVs where I do set a counter into and before I start any thread I do increase the counter one time for each thread and in the thread itself I just check first all entrys at the counter row to find the counter value I did set before starting the thread and if found then I use this iItem.So in this case I dont need to store any location position anymore.So on first tests it does work. I selected line 1 Now I inc a static variable Then I set R x into selected line at row C Now I start the thread with the info R x only In the thread I search for R x in entire LV and if found = item value If nothing was found = failed = line no more present = terminate thread If found then I can write / update new text in the right location LV 1 -------------------------- A | B | Count | C -------------------------- 1 | NY | 1000 | R 1 2 | IL | 1001 | 3 | NH | 2222 | 4 | BE | 3001 | 5 | UR | 5555 | -------------------------- LV 1 -------------------------- A | B | Count | C -------------------------- 1 | UR | 5555 | 2 | IL | 1001 | 3 | NH | 2222 | 4 | BE | 3001 | 5 | NY | 1000 | R 1 -------------------------- Ok,it seems to work so far.Maybe not so great that I have to use a new visible LV row but with that I can also live. Just hope that this method not makes any trouble later or so. greetz
fearless Posted April 24, 2017 Posted April 24, 2017 you could still use lParam - you just need to allocate a block of memory to it for the value for sorting and the thread/index information so like a structure of memory could be SOMEEXTRADATA STRUCT dwMasterIndexThreadThing DD 0 dwOriginallParamValue DD 0 SOMEEXTRADATA ENDS each lParam can be an addr of a SOMEEXTRADATA structure memory sized block then in the compare function of LVM_SORTITEMS you take the lParam1 value which is an addr of a SOMEEXTRADATA block of mem, fetch original lParam to compare against vs lParam1's SOMEEXTRADATA.dwOriginallParamValue so something like: CompareListItemsProc USES ebx lParam1:DWORD, lParam2:DWORD, wParam:DWORD LOCAL dwOriginallParam1:DWORD LOCAL dwOriginalParam2:DWORD mov ebx, lParam1 mov eax, [ebx].SOMEEXTRADATA.dwOriginallParamValue mov dwOriginallParam1, eax mov ebx, lParam2 mov eax, [ebx].SOMEEXTRADATA.dwOriginallParamValue mov dwOriginallParam2, eax .IF eax == dwOriginallParam1 ; return whatever LVM_SORTITEMS proc says to return for lParam1 == lParam2 .ELSEIF eax > dwOriginallParam1 ; return whatever LVM_SORTITEMS proc says to return for lParam1 < lParam2 .ELSEIF eax < dwOriginallParam1 ; return whatever LVM_SORTITEMS proc says to return for lParam1 > lParam2 .ENDIF ret CompareListItemsProc ENDP
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now