Jump to content
Tuts 4 You

Listview issues


LCF-AT

Recommended Posts

Hi guys,

I have again some small questions about listview re-arragne issues.So in the past I changed my LV that only a seclected lines does switch the content with the hitted line during a drag.Now i wanted to change that again so that all selected lines gets inserted to hitted line below but here I have some trouble.

Example:

Some LV entrys.
----------------------------
123
456
789
101112
----------------------------

I want the selected lines insert to hitted line exactly like the selection was.So I got it working if I move the selected lines below to a line but above its exactly else.How can I do it to make it match like I did secleted the lines?I am just getting confused again with that entire insert / delete line process.

		invoke	SendMessage,LISTVIEW,LVM_HITTEST,0,addr lvhti
		.if (lvhti.iItem!=-1)
			@@:
			invoke	SendMessage,LISTVIEW,LVM_GETNEXTITEM,-1,LVIS_SELECTED ;or LVIS_FOCUSED
			mov	iSelected,eax     ; vom select
			mov	ebx,lvhti.iItem   ; vom Hit
			mov HIT, ebx
			.if iSelected!=-1 ;|| iSelected!=ebx
			    
			    mov iNewItem, ebx  ; HIT
			    
			    invoke  RtlZeroMemory,addr lvi2,sizeof LV_ITEM
			    invoke  RtlZeroMemory,addr lvi2A,sizeof LV_ITEM			    
			    invoke	SendMessage,LISTVIEW, LVM_GETHEADER, 0, 0
			    mov	hHeader,eax
			    invoke	SendMessage,eax,HDM_GETITEMCOUNT ,0,0
			    mov	iColumnCount,eax			    
			    
			    
			    xor ebx,ebx			    
                mov     lvi2.imask,LVIF_TEXT or LVIF_IMAGE
			    mov     lvi2.cchTextMax,MAX_PATH
			    lea     eax, szBuffer
			    mov     lvi2.pszText,eax			    
			    mov	    lvi2.iSubItem,ebx
			    mov eax, iSelected
			    mov	    lvi2.iItem,eax
			    invoke SendMessage,LISTVIEW,LVM_GETITEM,0,addr lvi2			    
			    
		    			    
			    
			    mov     lvi2.imask,LVIF_TEXT or LVIF_IMAGE
			    mov     lvi2.cchTextMax,MAX_PATH
			    lea     eax, szBuffer
			    mov     lvi2.pszText,eax
			    mov	    lvi2.iSubItem,ebx
			   
			   
			    mov edx, iNewItem
			    .if iSelected <= edx
			        inc edx
			        mov iNewItem, edx
			   .endif
			    mov eax, iNewItem ; hit
			    mov	    lvi2.iItem,eax
			    invoke SendMessage, LISTVIEW, LVM_INSERTITEM, 0, addr lvi2	
			    mov iRetv, eax
			    
                nop
                nop
                xor edx, edx
                mov edx, iSelected
                .if iRetv <= edx
                    inc edx
                    inc iSelected
                .endif
                
			.if iRetv > edx
			    mov edx, iRetv
				dec edx
				mov Highlight, edx
			.elseif
                mov edx, iRetv               
				mov Highlight, edx
			.endif
 

                
                
                xor ebx,ebx
                .while (ebx<iColumnCount)
                mov     lvi2.imask,LVIF_TEXT or LVIF_IMAGE
			    mov     lvi2.cchTextMax,MAX_PATH
			    lea     eax, szBuffer
			    mov     lvi2.pszText,eax			    
			    mov	    lvi2.iSubItem,ebx
			    mov	    lvi2.iItem,0
			    invoke SendMessage, LISTVIEW, LVM_GETITEMTEXT, iSelected, addr lvi2
			    invoke SendMessage, LISTVIEW, LVM_SETITEMTEXT, iRetv, addr lvi2
			    inc	ebx
			    .endw
			    
			    invoke SendMessage, LISTVIEW, LVM_DELETEITEM, iSelected, 0
                jmp @B                          

A another problem I have is how to set the new selected highlights of the inserted items.So I cant do this on fly (endless loop).Has anyone a idea how to handle that part to have all moved items selected again after the drag?Maybe you can help again a little to make that parts working correctly.

Thanks

Link to comment

Hi guys,

I wrote a code to handle that issue more or less.I got it not finished perfect but better than nothing so far.

Now I wanted to handle another older problem I didnt fixed yet about dragging in a listview.My goal is it to show all selected lines during a drag with the listview image & text too.On internet I found a small code how it should work and after long testing I got it work so far to see all selected line images during a drag but the problem is the text now of the entrys so this is shown in white color (almost not visible) and also just the text from first entry / line and not the complete text line.In the past we talked about that text issue without to find a solution.

Now I would like to ask whether and how its possible to add the text manually after the image during a drag since windows 7 dosent show it anymore as on XP?The code I used for a multible image drag I got from here..

https://forum.powerbasic.com/forum/user-to-user-discussions/source-code/23917-multiple-drag-images-for-listview

...and if I do it so then I get this results to see....

LV1.png.2c1fac5261402ae7528bc3e0f58e7782.png

....you see its just black shadow stylish.After checking the code I found the problem at API ImageList_Draw using ILD_MASK flag = result above.If I change the flag to 0 then its transparent....

LV2.png.bea6d3a876f6e3c83fbe338bbb3aaa2a.png

.....but you also cant see the text which is white and only numbers are too see.At the API ImageList_Create I used ILC_COLOR32 flag to show icons as above and like they should also shown.If I change the flag to lower ILC_COLOR24 then I get black shadows and icons are looking bad....

LV3.png.2f28bea067b980d8a452c679df12cc17.png

...dosent look like I want.Now I just wanna ask how to do it right?I wanna have transparent icons in my LV and also during a drag + whole text of entire lines (icon 1     some text 1) without a shadow + using a visible text color and not same as LV background is.Maybe anyone can help again with that issues and or checking my code for that.I do attach the code files below (WinASM / MASM).

PS: If you drag a item and keep left mouse pressed down and you do scroll up & down and move the mouse around then you can see some paint issues.Not sure how to prevent this at the moment.Do you know?By the way,the code is just a example to check that drag issues so dont wonder if it looks a bit messy. :)

Thank you

DragDrop_listview_items3.rar

Link to comment

Hi again,

one good news.After long testing & checking I got it working to make a re-arange as I wanted but it was really a bad thing to code that (no idea why I got such problems with that).First I need to read all selected lines above the hittet line and insert them at hitted line + 1 (next line after hittet) and then I need to read all selected lines after hittet line from last selected to above till hittet line and insert them directly at hittet line + also deleting the selected lines of course.Its very confusing (for me of course) but now it works as you can see at the gif animation below. :) For setting the re-selections on the moved items I did used first number row and did set on all moved lines a * inside which I do search at the end again to re-select them.No good solution of course but at the moment I have no better clue how to handle that but its no big problem so normaly I always use a number counter row in my listviews which I then update each time after any item move.

Video_2018-01-13_193934.gif.e141c9e055f31d3a5672a200278c5a7b.gif

Only problem I still have is that icon / image / text dragging.No idea how to set the text after the image during a drag which is also visible.Maybe you have any ideas how to make that.

A other problem was that paint issue during a drag + using the mousewheel.Only way to prevent that was to send a WM_MOUSEMOVE message after WM_MOUSEWHEEL but also in this case I dont see the drag image/s anymore just after a wheel and only get it back after another mouse move.Its also no good solution of course but maybe you have also a hint for that too.

greetz

Link to comment

Hi guys,

still fighting with that smudge painting issues during a dragging.It looks pretty bad and I dont find a way to do any paint update without to get any flickering. :(

Video_2018-01-16_152934.gif.bbd4bb39e2d9fc3d3bcc23e92863ad8d.gif

So what can I do to prevent that bad smudge issues if it scrolls up & down?Just wanna show the icons on same way if I not scroll.Has anyone of you any listview / drag example app in any language where it works correctly without painting issues or flickering during dragging?

greetz

Link to comment

Hi again,

short another question.I would like to create a autoscrolling during a drag starting from the last / prelast hittet line below or top.On MSDN I find a message called LVM_GETCOUNTPERPAGE to get the result of all visible items at the moment.Now I have that result and the hittet item.The question is now how to find out whether the hittet line is the last / prelast from below or top?

1
2
3
---------- middle point
4
5 <--- selected / drag start down = should start to scroll down because its prelast visible line
6
------------------------- above visible area
7
8
9
10
....

How can I calc this out now?I have the result of 6 from LVM_ISITEMVISIBLE and result of hittet item index of 4.

greetz

Link to comment

Hi again,

found a listview with drag / drop example on this site too.

https://www.developer.com/net/cplus/article.php/628271/A-Drag-and-Drop-List-Control.htm

But also this example file you can download there does also flicker like hell and if you scroll during a drag then you see the same problems like I post above.Smudge all over also during mousemove and drag image not to see anymore during a mousewheel on drag.This example file is in cpp so maybe anyone of you can check that and find out how to prevent this stupid smudge / flicker trash.I cant beleive that there is no solution out there for that problem.Is nobody around who has some experiences with listviews with drag drop etc?

greetz

Link to comment

Hi,

still found no solution.At the moment I use now ImageList_DragShowNolock True & false to show drag image during mousemove and not during any scrolling or key scrollers etc.Looks so now...

Video_2018-01-18_204635.gif.e9e4495012e5c5dc60bd16cc7ca9a5ea.gif

...not perfect as I wanted but better than before with that whole smudge & flickering issues.

greetz

Link to comment
  • 3 years later...

Hi guys,

I have a small question about listview and handling of WM_NOTIFY / NM_CLICK.So NM_CLICK seems to work when I let the left mouse button up.All normal so far but I get a problem when I do use the select mode with the mouse (pressing left mouse button and move now and then let up).In this case the NM_CLICK gets also triggered with enabled mouse selection.Hhmm!

Example: I have a listview with 6 column and in the last one (6) I do catch NM_CLICK message to toggle On/Off a image.All working so far.Now I do move the last column to let side to make it smaller and to see the rest of the listview (Outside) where I can use the mouse to enable a selection mode.I do now select any lines comming from outside to last column and let the left mouse up and now NM_CLICK gets triggered and does toggle the image and this I wanna prevent but how?Below a image of selection from outside to inside of last column....

L1_2021-04-12_005241.png.f39357330fdc1b6d030766502896b0b6.png

...now if I let the left mouse button up I get this....

L2_2021-04-12_005241.png.8e6d4a4ce5ec8174cc299004af835f30.png

....it does toggle the image ON by hitting NM_CLICK.The question now is how to check on NM_CLICK message whether the left mouse button press down was done outside of the LV?Remember,  I don't did subclass this listview and I can not catch WM_LBUTTONDOWN.So is there any other method to catch the outside click in the listview?Some kind of outside mousemove etc.Or can I check anyhow on NM_CLICK whether the selection mode of mouse is in use at this moment?You know what I mean right?Maybe you have an idea how to handle that.

greetz

Link to comment
19 hours ago, LCF-AT said:

You know what I mean right?

Hell, no! That description was horrible. 
To be able to help you, one needs to see the code that's not working and know exactly what you're doing and what you're trying to achieve. As always, I shall refer to the classics: https://www.chiark.greenend.org.uk/~sgtatham/bugs.html#showmehow
  

Given the description, I can only try to *guess* what you meant, what you did and what you need. So, I guess that this might solve your problem:
1) LVN_MARQUEEBEGIN will notify you that listview selection is starting. When you get this notification, you set some global flag;
2) Now when you get NM_CLICK notification, you check your global flag. If flag was set, you know this notification can be ignored. If flag was not set, you process it as a mouse click. And remember to reset the flag.

Attached is an example program from MASM32 package which implements this mechanism. You can play with it and see if it does what you want. All my changes in the code are marked with "kao".

lv_test.zip

  • Thanks 1
Link to comment

Hi kao,

a come on, I made some beautiful pics to show and see that problem right. :)

Thank you for checking out my problem and sending the solution for it.I tried it out and it seems to work 1A now. :) I did't remember that LVN_MARQUEEBEGIN notification anymore and I was just checking my Win32 Programmer Reference where its not included.All in all problem solved so far.Thank you again kao.By the way, this selection start (bounding box (marquee)) can only just begun from that outside listview location (see image 1 I made) after the created columns right?Or is it also possible to do this inside too by enabling some specific styles?No or?Normaly I am just using that LVS_SINGLESEL style or not like in images above.Just asking you know.

greetz

Link to comment

Hi again,

I have another question about WM_NOTIFY message.So MSDN said I should check lparams NMHDR structure and check hwndFrom or idFrom member to see which control has send a notify.So that means I have to notice / remember each handle of a control what it is.Is there a method to check at WM_NOTIFY what control it is (listview / treeview etc)?

I'am also asking because I found that on MSDN too...NM_CUSTOMDRAW code

https://docs.microsoft.com/en-us/windows/win32/controls/nm-customdraw

NM_CUSTOMDRAW

#ifdef LIST_VIEW_CUSTOM_DRAW

    lpNMCustomDraw = (LPNMLVCUSTOMDRAW) lParam;

#elif TOOL_TIPS_CUSTOM_DRAW

    lpNMCustomDraw = (LPNMTTCUSTOMDRAW) lParam;

#elif TREE_VIEW_CUSTOM_DRAW

    lpNMCustomDraw = (LPNMTVCUSTOMDRAW) lParam;

#elif TOOL_BAR_CUSTOM_DRAW

    lpNMCustomDraw = (LPNMTBCUSTOMDRAW) lParam;

#else

    lpNMCustomDraw = (LPNMCUSTOMDRAW) lParam;

#endif

...so how to check which X-CUSTOMDRAW must be handled at the NM_CUSTOMDRAW code if I NOT know the control (LV,TV,etc without checking it)?

In the end I have a short question about lparam variable.Normal I do write something like this to check for content in the structs...

.elseif eax == WM_NOTIFY
mov ecx, lParam
.if  [ecx].NMHDR.code == LVN_BEGINDRAG

...so I have to move lparam into register first.Is it also possible without using a register and access / pointing with lparam holder directly?

.elseif eax == WM_NOTIFY
.if  [lParam].NMHDR.code == LVN_BEGINDRAG
or
.if  [[lParam]].NMHDR.code == LVN_BEGINDRAG

Somehow like this etc?I tried but dosent work.Just wanna know why it works using a register DWORD but not using lParam whats also a DWORD.I also can not use a other variable like that when I copy the lParam content into.Its seems I always have to use a register to copy lParam into.Not working with a variable.Something like it works in C code.

case WM_NOTIFY:

switch (((LPNMHDR)lParam)->code) {

    case LVN_BEGINDRAG:

greetz

Link to comment
15 hours ago, LCF-AT said:

...so I have to move lparam into register first.Is it also possible without using a register and access / pointing with lparam holder directly?

Nope, there's no easy way to do that because that would have to translate to a non-existing assembly instruction.

 

See the underlying assembly code:

; mov ecx, lParam
mov     ecx, [ebp+14h]
; .if  [ecx].NMHDR.code == LVN_BEGINDRAG
cmp     dword ptr [ecx+8], 9

So, you're asking for something like:

cmp     dword ptr [[ebp+14h]+8], 9

which obviously doesn't exist.

C/C++ and all other high-level languages hide all this complexity from programmer and use registers automatically when required. You lose a bit of control but gain a lot of readability and simplicity. :) 

  • Like 2
Link to comment

Hi again,

ah ok.So I thought there would be any advanced macro which could handle that maybe too.So I like loosing the complexity of assembling and getting more comfort and simplicity if possible. :) Earlier I wan't a fan of it but at the end its just better and code snippets are a lot smaller and clearer to read.

greetz

Link to comment

Hi,

I still have some questions about LV and drag / drop.I made a new drag and drop code for the rearrangement items using similar code like this....

https://www.codeproject.com/Articles/1298/Rearrange-rows-in-a-ListView-control-by-drag-and-d

The drag / drop works so far pretty well but there are still some issues I would like to change.

1.) Using ImageList_Create function with ILC_COLOR32 or ILC_MASK flags creates good looking icons in my listview but it makes trouble when doing the drag moves and the results are this....Image 2 & 3 using ILC_COLOR24 flag...

DRAG_01.png.db7a0f1249674a847867fe8ddedbc2e4.pngDRAG_02.png.3187db3a2c775dfd010277c25c9f136c.png

DRAG_03.png.53ffa62d57333ef6230a35bb2f346b3c.pngDRAG_04.png.5688aab74f855eccca31718bd6965324.png

...so is there a way to use ILC_COLOR32 flag and to see the text + background on dragging and why does it not show the text of the outside selection anymore?

2.) So I would like to limit the selection count on a drag move.If the user has selected more than 10 items (like 100 items) then I would like to show at the end of the drag image a info about how much items are selected.How can I do that just by using ImageList_* functions?Is that possible (without doing any ownerdraw stuff)?

3.) How to manage a drag / drop operation on very large listviews with tons of items?

Example: I have created a LV with 700+ items.Now I make it simple and just select the last 3 items and those I wanna drag on top of the listview.In this case I have to scrolll the drag up and up a very long time.How to make it quickly?

DRAG_05.png.4339ac78b6e28d7f7027e2e5d06e41eb.png

...are there any key shortcuts I can use to move,Somehow I must keep the selection (left mouse pressed) and moving the scroller on top anyhow.Right?No clue yet.Otherwise I need to add a another function via right mouse press / context menu "Insert items to line X" followed by a new box where the user can enter a desired LV line position like 1 in this case to let move all selected item on that location.But its again a detour I would like to prevent creating another dialog just that the user can enter a value.So does anyone have any smarter idea for that?

greetz

Link to comment

the solution I have implement for this, on a C# is the  DragOver event 

        private void TR_DragOver(object sender, DragEventArgs e)
        {
 >>>>>>>>>           NativeMethods.Scroll(TR);

            TreeView tree = (TreeView)sender;

            e.Effect = DragDropEffects.None;

            if ((e.Data.GetData(typeof(TreeNode)) != null))
            {
                Point pt = new Point(e.X, e.Y);
                pt = tree.PointToClient(pt);
                TreeNode node = tree.GetNodeAt(pt);

                if ((node != null))
                {
                    e.Effect = DragDropEffects.Move;
                    tree.SelectedNode = node;
                }

            }
        }

//NativeMethods Class
    public static class NativeMethods
    {
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        internal static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

        public static void Scroll(this Control control)
        {
            var pt = control.PointToClient(Cursor.Position);

            if ((pt.Y + 20) > control.Height)
            {
                // scroll down
                SendMessage(control.Handle, 277, (IntPtr)1, (IntPtr)0);
            }
            else if (pt.Y < 20)
            {
                // scroll up
                SendMessage(control.Handle, 277, (IntPtr)0, (IntPtr)0);
            }
        }
    }

 

ref
stackoverflow.com/questions/6034942/treeview-autoscroll-while-dragging
www.syncfusion.com/faq/windowsforms/treeview/how-do-i-make-the-treeview-scroll-when-i-drag-an-item-to-the-top-or-bottom
social.msdn.microsoft.com/Forums/en-US/a336643c-11a9-451a-9d68-da0fd072383c/treeview-drag-drop-scrolling

Edited by whoknows
  • Like 1
Link to comment

Hi,

thanks but those scroll operations need much time in listviews with 100+ items you know.I created a quicker method to move all selected items to a specific new desired line the user want to move the items into...

Video_2021-04-19_005551_merged..gif.169af9123b02a30c8601995ecfa9e0f4.gif

...its a little de-tour but works total quick without doing some drag moved over the whole listview when the user has tons of items stored.

greetz

Link to comment

Hi,

so I have another question about using Edit Controls like you can see in my animation of my last post.So in this to create a extra Edit control I wanna also catch some VK keys for enter & escape.The problem is that I have to create a new dialog procedere (Init/Exit) to show the new dialog where I have put the Edit control on it.In case of catching VK Keys I have to create a subclass routine = 2 new routines I have to create just to show a simple Edit control with key catch functions.I think that pretty bad to that each time for any edit controls etc.Just wanna ask whether there is any better method to do that without to produce the extra routines?Are there no templates for that maybe?So Windows itself has also some Window templates I can fill and call (load/save Window / and others so I dont know all at the moment).Maybe you know something for that.

PS: Is it also possible to show the Edit control without the dialogBox?Just the edit field and hiding the dialog or so?I tried to check some styles but didnt found anything yet.

PS2: About subclassing and checking for WM_CHAR & WM_KEYDOWN.So if I handle WM_GETDLGCODE with DLGC_WANTALLKEYS or DLGC_WANTTAB flag then I can handle WM_CHAR & WM_KEYDOWN.First comes WM_CHAR followed by WM_KEYDOWN after.So in case of catching VK keys I could choose between both MSGs to handle VK keys.Does it play any role if I choose WM_CHAR or WM_KEYDOWN or have I to handle both?Or is it not important to choose CHAR or KEYDOWN?The description is pretty same for both messages.

greetz

Link to comment
  • 7 months later...

Hi guys,

just have a tiny question about Listview and trying to catch virtual keys.I would like to catch the VK_RETURN when I have pressed return key on any selected entry of listview.Problem is that I don't get VK_RETURN at WM_NOTIFY / LVN_KEYDOWN message in LV_KEYDOWN struct.I get other keys like VK_DOWN VK_UP VK_DELETE etc but not VK_RETURN and some others too.Why?How to catch VK_RETURN now too WITHOUT to subclass my listview (just using one and handle all in main procedere)?

greetz

Link to comment

google.com/search?q=listview+VK_RETURN

forums.codeguru.com/showthread.php?55767-How-make-an-Enter-Return-key-work-with-the-item-selected-in-listview-control

  • Haha 1
Link to comment

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...