Visual Help for drag&drop in ListView

Just starting out? Need help? Post your questions and find answers here.
tatanas
Enthusiast
Enthusiast
Posts: 260
Joined: Wed Nov 06, 2019 10:28 am
Location: France

Visual Help for drag&drop in ListView

Post by tatanas »

Hi,

I'm trying to draw a line to show where the listview row will drop. But I can't get it to work properly (I just focused on the draw part).
Could you help me please ? Here is the code :

EDIT : Here is a working code from Shardik (thank you !)

Code: Select all

Structure LVINSERTMARK
  cbSize.L
  dwFlags.L
  iItem.L
  dwReserved.L
EndStructure

Define DraggingIsActive.I
Define HeaderHeight.I
Define Rectangle.RECT
Define RowIndex.I
Define RowHeight.I
Define RowInsertionIndex.I

Procedure WindowCallback(WindowHandle.I, Msg.I, WParam.I, LParam.I)
  Shared DraggingIsActive.I

  Protected *NMHdr.NMHDR

  Select Msg
    Case #WM_NOTIFY
      *NMHdr = LParam

      If *NMHdr\hwndFrom = GadgetID(0)       
        If *NMHdr\code = #LVN_ITEMCHANGING
          If DraggingIsActive And GetGadgetState(0) = -1
            ; ----- Disable highlighting of item under cursor
            ProcedureReturn #True
          EndIf
        EndIf
      EndIf
  EndSelect

  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

Procedure DragCallback(Action.I)
  Shared HeaderHeight.I
  Shared RowHeight.I
  Shared RowInsertionIndex.I

  Protected CursorPositon.POINT
  Protected CursorRow.I
  Protected InsertMark.LVINSERTMARK
  Protected Rectangle.RECT
  Protected RowCount.I

  InsertMark\cbSize = SizeOf(LVINSERTMARK)
  GetCursorPos_(CursorPositon)
  GetWindowRect_(GadgetID(0), Rectangle)

  If PtInRect_(Rectangle, CursorPositon\x + (CursorPositon\y) << 32)
    ; ----- Convert x and y from coordinate space to window-relative space
    MapWindowPoints_(0, GadgetID(0), CursorPositon, 1)

    ; ----- Get row index of current cursor position
    CursorRow = (CursorPositon\y - HeaderHeight) / RowHeight
    RowCount = CountGadgetItems(0)

    If CursorRow >= RowCount
      ; ----- Cursor is in empty row below last item
      RowInsertionIndex = RowCount
    ElseIf CursorRow = -1
      CursorRow = 0
    Else
      ; ----- Get row insertion index
      SendMessage_(GadgetID(0), #LVM_INSERTMARKHITTEST, @CursorPositon,
        @InsertMark)
      ; ----- Display insertion line
      SendMessage_(GadgetID(0), #LVM_SETINSERTMARK, 0, @InsertMark)
      RowInsertionIndex = InsertMark\iItem

      ; ----- Increase index if cursor is in lower part of row
      If (CursorPositon\y - HeaderHeight) % RowHeight > RowHeight * 0.5
        RowInsertionIndex + 1
      EndIf
    EndIf

    ProcedureReturn #True
  EndIf
EndProcedure

Procedure DropCallback(TargetHandle.I, Status.I, Format.I, Action.I, x.I, y.I)
  Shared DraggingIsActive.I

  Protected InsertMark.LVINSERTMARK
  Protected Result.I = #False

  InsertMark\cbSize = SizeOf(LVINSERTMARK)

  Select Status
    Case #PB_Drag_Move, #PB_Drag_Enter
      DraggingIsActive = #True
    Case #PB_Drag_Leave, #PB_Drag_Finish
      DraggingIsActive = #False

      ; ----- Remove insertion line
      InsertMark\iItem = -1
      SendMessage_(GadgetID(0), #LVM_SETINSERTMARK, 0, @InsertMark)
  EndSelect

  If Status <> #PB_Drag_Leave
    Result = #True
  EndIf

  ProcedureReturn Result
EndProcedure

OpenWindow(0, 100, 100, 370, 150, "Drag 'n drop row inside gadget")

ListIconGadget(0, 10, 10, WindowWidth(0) - 20, WindowHeight(0) - 20,
  "Name", 100,
  #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect)
AddGadgetColumn(0, 1, "Address", GadgetWidth(0) - GetGadgetItemAttribute(0,
  0, #PB_ListIcon_ColumnWidth) - 4)
AddGadgetItem(0, -1, "Harry Rannit" + #LF$ +
  "12 Parliament Way, Battle Street, By the Bay")
AddGadgetItem(0, -1, "Ginger Brokeit" + #LF$ +
  "130 PureBasic Road, BigTown, CodeCity")
AddGadgetItem(0, -1, "Didi Foundit" + #LF$ +
  "321 Logo Drive, Mouse House, Downtown")
EnableGadgetDrop(0, #PB_Drop_Text, #PB_Drag_Copy)
SetDragCallback(@DragCallback())
SetDropCallback(@DropCallback())

; ----- Get height of header row
GetClientRect_(SendMessage_(GadgetID(0), #LVM_GETHEADER, 0, 0), @Rectangle)
HeaderHeight = Rectangle\bottom - Rectangle\top

; ----- Get height of single row
RowHeight = SendMessage_(GadgetID(0), #LVM_GETITEMSPACING, #True, 0) >> 16

; ----- Initialize WindowCallback to suppress highlighting
SetWindowCallback(@WindowCallback(), 0)

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
    Case #PB_Event_Gadget
      If EventGadget() = 0 And EventType() = #PB_EventType_DragStart
        DraggingIsActive = #True
        RowIndex = GetGadgetState(0)

        ; ----- Deselect any selected entry
        SetGadgetState(0, -1)
     
        If RowIndex >= 0
          DragText(GetGadgetItemText(0, RowIndex, 0) + #LF$ +
            GetGadgetItemText(0, RowIndex, 1), #PB_Drag_Copy)
        EndIf
      EndIf
    Case #PB_Event_GadgetDrop
      AddGadgetItem(0, RowInsertionIndex, EventDropText())

      ; ----- Deselect any selected entry
      SetGadgetState(0, -1)
  EndSelect
ForEver
Last edited by tatanas on Fri Jan 10, 2020 12:39 pm, edited 1 time in total.
Windows 10 Pro x64
PureBasic 6.20 x64
User avatar
Shardik
Addict
Addict
Posts: 2058
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: Visual Help for drag&drop in ListView

Post by Shardik »

tatanas wrote:I'm trying to draw a line to show where the listview row will drop
I have just posted this example which demonstrates how to drag a row from one ListIconGadget to another one while drawing a target line in the destination ListIconGadget in order to exactly position the dropped row.
tatanas
Enthusiast
Enthusiast
Posts: 260
Joined: Wed Nov 06, 2019 10:28 am
Location: France

Re: Visual Help for drag&drop in ListView

Post by tatanas »

It's funny that's someone ask the same thing one day before me.
However I don't see any line at destination drop, just the highlighted row under the cursor and every items are inserted at the beginning of the listview.
(your variable RowInsertionIndex is always equal to 0)
Actually, your never enter this IF statement :

Code: Select all

		If SendMessage_(GadgetID(1), #LVM_SETINSERTMARK, 0, @InsertMark)
			RowInsertionIndex = InsertMark\iItem

			If (CursorPositon\y - HeaderHeight) % RowHeight > RowHeight * 0.5
				RowInsertionIndex + 1
			EndIf
		EndIf
Windows 10 Pro x64
PureBasic 6.20 x64
User avatar
Shardik
Addict
Addict
Posts: 2058
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: Visual Help for drag&drop in ListView

Post by Shardik »

I have tested my example successfully - as written in the linked thread - on Windows 7 x64 SP1 with PB 5.71 x86 and Windows 10 Version 1809 x64 with PB 5.46 x64 in ASCII and Unicode mode. When having problems executing a posted code, please post always your OS and PB version in order for others to reproduce your described problem. The other posters in the linked thread didn't seem to have any problems, so it's important to know your programming environment.

A shot in the dark: Have you disabled "Enable modern theme support" in the menu
"Compiler" > "Compiler Options..." > Tab "Compiler Options"? This option has to be enabled in order to work.
tatanas
Enthusiast
Enthusiast
Posts: 260
Joined: Wed Nov 06, 2019 10:28 am
Location: France

Re: Visual Help for drag&drop in ListView

Post by tatanas »

Sorry.
I'm using Purebasic 5.71 x64 on a Windows 7 Sp1 x64.
I will check "Enable modern theme support" option as soon as i'm back to home.

EDIT : "Enable modern theme support" is enabled.
I don't know why but InsertMark\iItem is always equal to 0
Last edited by tatanas on Sun Jan 05, 2020 7:53 pm, edited 1 time in total.
Windows 10 Pro x64
PureBasic 6.20 x64
tatanas
Enthusiast
Enthusiast
Posts: 260
Joined: Wed Nov 06, 2019 10:28 am
Location: France

Re: Visual Help for drag&drop in ListView

Post by tatanas »

this small code doesn't work either :

Code: Select all

Structure LVINSERTMARK
  cbSize.I
  dwFlags.L
  iItem.I
  dwReserved.L
EndStructure


Window_0 = OpenWindow(#PB_Any, 0, 0, 400, 300, "", #PB_Window_SystemMenu)
ListIcon_0 = ListIconGadget(#PB_Any, 24, 22, 336, 246, "Column 1", 100)
For i = 1 To 10
	AddGadgetItem(ListIcon_0, -1, "item" + Str(i))
Next

pMark.LVINSERTMARK
pMark\cbSize = SizeOf(LVINSERTMARK)
pMark\iItem = 5
pMark\dwReserved = 0

; SetWindowTheme_(GadgetID(ListIcon_0), " ", " ")
SendMessage_(GadgetID(ListIcon_0), #LVM_SETINSERTMARK, 0, @pMark)



Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
  EndSelect
ForEver
If I'm right, it should add a line before item at index 5. What's going on ?

EDIT : I just did the same with Autoit and it works as it should
Windows 10 Pro x64
PureBasic 6.20 x64
User avatar
Shardik
Addict
Addict
Posts: 2058
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: Visual Help for drag&drop in ListView

Post by Shardik »

Thank you for posting your programming environment (Windows 7 SP1 x64 with PB 5.71 x64). I was able to reproduce your error! The Structure LVINSERTMARK seems to be wrongly declared for x64. If you change the type declaration for the 2 elements with .I to .L, your last example works like a charm! I have therefore also changed the declaration in my linked example.
tatanas
Enthusiast
Enthusiast
Posts: 260
Joined: Wed Nov 06, 2019 10:28 am
Location: France

Re: Visual Help for drag&drop in ListView

Post by tatanas »

Thanks, it's works fine !

Now, I would like to disable the item selection when dragging. I tryed by intercepting the LVN_ITEMCHANGING message but the result is strange.

Code: Select all

EnableExplicit

Structure LVINSERTMARK
	cbSize.l
	dwFlags.l
	iItem.l
	dwReserved.l
EndStructure

Define HeaderHeight.I
Define Rectangle.RECT
Define Row.I
Define RowHeight.I
Define RowInsertionIndex.I

Procedure WinProc(hWnd, Msg, wParam, lParam)
	Protected result = #PB_ProcessPureBasicEvents	 
	Protected *tInfo.NMITEMACTIVATE

	Select Msg
			 
		Case #WM_NOTIFY
      
			Protected *tNMHDR.NMHDR = lParam
			
			Select *tNMHDR\hwndFrom
					
				Case GadgetID(1)       
					Select *tNMHDR\code
						Case #LVN_ITEMCHANGING
							ProcedureReturn #True
							
					EndSelect
									
			EndSelect
								
	EndSelect
	ProcedureReturn result
EndProcedure

Procedure DragCallback(Action.I)
	Shared HeaderHeight.I
	Shared RowHeight.I
	Shared RowInsertionIndex.I
	
	Protected CursorPositon.POINT
	Protected InsertMark.LVINSERTMARK
	Protected Rectangle.RECT
	
	InsertMark\cbSize = SizeOf(LVINSERTMARK)
	GetCursorPos_(CursorPositon)
	GetWindowRect_(GadgetID(1), Rectangle)
	
	If PtInRect_(Rectangle, CursorPositon \ x + (CursorPositon \ y) << 32)
		MapWindowPoints_(0, GadgetID(1), CursorPositon, 1)
		
		; ----- Display insertion line
		SendMessage_(GadgetID(1), #LVM_INSERTMARKHITTEST, @CursorPositon, @InsertMark)
	
		If SendMessage_(GadgetID(1), #LVM_SETINSERTMARK, 0, @InsertMark)
			RowInsertionIndex = InsertMark\iItem
			
			If (CursorPositon\y - HeaderHeight) % RowHeight > RowHeight * 0.5
				RowInsertionIndex + 1
			EndIf
		EndIf
		
		ProcedureReturn #True
	EndIf
EndProcedure

OpenWindow(0, 0, 0, 730, 500, "Drag row from left to right", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

ListIconGadget(0, 10, 10, WindowWidth(0) / 2 - 15, WindowHeight(0) - 20, "Name", 100, #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect)
AddGadgetColumn(0, 1, "Address", GadgetWidth(0) - GetGadgetItemAttribute(0, 0, #PB_ListIcon_ColumnWidth) - 4)
AddGadgetItem(0, -1, "Harry Rannit" + #LF$ + "12 Parliament Way, Battle Street, By the Bay")
AddGadgetItem(0, -1, "Ginger Brokeit" + #LF$ + "130 PureBasic Road, BigTown, CodeCity")
AddGadgetItem(0, -1, "Didi Foundit" + #LF$ + "321 Logo Drive, Mouse House, Downtown")

ListIconGadget(1, WindowWidth(0) / 2 + 5, 10, WindowWidth(0) / 2 - 15, WindowHeight(0) - 20,  "Name", 100, #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect)
AddGadgetColumn(1, 1, "Address", GadgetWidth(0) - GetGadgetItemAttribute(0, 0, #PB_ListIcon_ColumnWidth) - 4)

EnableGadgetDrop(1, #PB_Drop_Text, #PB_Drag_Copy)
SetDragCallback(@DragCallback())

; ----- Get height of header row
GetClientRect_(SendMessage_(GadgetID(1), #LVM_GETHEADER, 0, 0), @Rectangle)
HeaderHeight = Rectangle\bottom - Rectangle\top

; ----- Get height of single row
RowHeight = SendMessage_(GadgetID(0), #LVM_GETITEMSPACING, #True, 0) >> 16
SendMessage_(GadgetID(1), #LVM_SETINSERTMARKCOLOR, 0, $0000FF) ; couleur de la ligne d'insertion

SetWindowCallback(@WinProc(), 0)

Repeat
	Select WaitWindowEvent()
		Case #PB_Event_CloseWindow
			Break
		Case #PB_Event_Gadget
			If EventGadget() = 0 And EventType() = #PB_EventType_DragStart
				Row = GetGadgetState(0)
				
				If Row >= 0
					DragText(GetGadgetItemText(0, Row, 0) + #LF$ + GetGadgetItemText(0, Row, 1), #PB_Drag_Copy)
				EndIf
			EndIf
		Case #PB_Event_GadgetDrop
			AddGadgetItem(1, RowInsertionIndex, EventDropText())
	EndSelect
ForEver
Windows 10 Pro x64
PureBasic 6.20 x64
User avatar
Shardik
Addict
Addict
Posts: 2058
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: Visual Help for drag&drop in ListView

Post by Shardik »

tatanas wrote:Now, I would like to disable the item selection when dragging.
Have you already tried RASHAD's modification of my example which uses SetWindowsTheme with "Explorer" to eliminate the highlighting? But remember to modify the LVINSERTMARK structure before testing with your PB x64 compiler... :wink:
camille
User
User
Posts: 71
Joined: Tue Nov 19, 2019 12:52 pm

Re: Visual Help for drag&drop in ListView

Post by camille »

Have you already tried RASHAD's modification of my example which uses SetWindowsTheme with "Explorer" to eliminate the highlighting?
Does it fully eliminate the highlighting for you?

It does modify it here on my system (Windows Server 2019, 10.0.17763.107), but it is still a light blue (and not a darker one without the modification) that is visible when hovering over a column...
tatanas
Enthusiast
Enthusiast
Posts: 260
Joined: Wed Nov 06, 2019 10:28 am
Location: France

Re: Visual Help for drag&drop in ListView

Post by tatanas »

Same here too.
There is still a light blue selection.

EDIT : it works better but it hangs when you select an item in the right listview and retry a drag.

Code: Select all

EnableExplicit

Structure LVINSERTMARK
   cbSize.l
   dwFlags.l
   iItem.l
   dwReserved.l
EndStructure

Define HeaderHeight.I
Define Rectangle.RECT
Define Row.I
Define RowHeight.I
Define RowInsertionIndex.I
Global drag = #False

Procedure WinProc(hWnd, Msg, wParam, lParam)
   Protected result = #PB_ProcessPureBasicEvents   
   Protected *tInfo.NMITEMACTIVATE

   Select Msg
         
      Case #WM_NOTIFY
     
         Protected *tNMHDR.NMHDR = lParam
         
         Select *tNMHDR\hwndFrom
               
            Case GadgetID(1)       
               Select *tNMHDR\code
						Case #LVN_ITEMCHANGING
							If drag
								ProcedureReturn #True ; disable Highlight
							Else
								ProcedureReturn #False ; normal behaviour
							EndIf
                     
               EndSelect
                           
         EndSelect
                        
   EndSelect
   ProcedureReturn result
EndProcedure

Procedure DragCallback(Action.I)
   Shared HeaderHeight.I
   Shared RowHeight.I
   Shared RowInsertionIndex.I
   
   Protected CursorPositon.POINT
   Protected InsertMark.LVINSERTMARK
   Protected Rectangle.RECT
   
   InsertMark\cbSize = SizeOf(LVINSERTMARK)
   GetCursorPos_(CursorPositon)
   GetWindowRect_(GadgetID(1), Rectangle)
   
   If PtInRect_(Rectangle, CursorPositon \ x + (CursorPositon \ y) << 32)
      MapWindowPoints_(0, GadgetID(1), CursorPositon, 1)
      
      ; ----- Display insertion line
      SendMessage_(GadgetID(1), #LVM_INSERTMARKHITTEST, @CursorPositon, @InsertMark)
   
      If SendMessage_(GadgetID(1), #LVM_SETINSERTMARK, 0, @InsertMark)
         RowInsertionIndex = InsertMark\iItem
         
         If (CursorPositon\y - HeaderHeight) % RowHeight > RowHeight * 0.5
            RowInsertionIndex + 1
         EndIf
      EndIf
      
      ProcedureReturn #True
   EndIf
EndProcedure

OpenWindow(0, 0, 0, 730, 500, "Drag row from left to right", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

ListIconGadget(0, 10, 10, WindowWidth(0) / 2 - 15, WindowHeight(0) - 20, "Name", 100, #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect)
AddGadgetColumn(0, 1, "Address", GadgetWidth(0) - GetGadgetItemAttribute(0, 0, #PB_ListIcon_ColumnWidth) - 4)
AddGadgetItem(0, -1, "Harry Rannit" + #LF$ + "12 Parliament Way, Battle Street, By the Bay")
AddGadgetItem(0, -1, "Ginger Brokeit" + #LF$ + "130 PureBasic Road, BigTown, CodeCity")
AddGadgetItem(0, -1, "Didi Foundit" + #LF$ + "321 Logo Drive, Mouse House, Downtown")

ListIconGadget(1, WindowWidth(0) / 2 + 5, 10, WindowWidth(0) / 2 - 15, WindowHeight(0) - 20,  "Name", 100, #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect)
AddGadgetColumn(1, 1, "Address", GadgetWidth(0) - GetGadgetItemAttribute(0, 0, #PB_ListIcon_ColumnWidth) - 4)

EnableGadgetDrop(1, #PB_Drop_Text, #PB_Drag_Copy)
SetDragCallback(@DragCallback())

; ----- Get height of header row
GetClientRect_(SendMessage_(GadgetID(1), #LVM_GETHEADER, 0, 0), @Rectangle)
HeaderHeight = Rectangle\bottom - Rectangle\top

; ----- Get height of single row
RowHeight = SendMessage_(GadgetID(0), #LVM_GETITEMSPACING, #True, 0) >> 16
SendMessage_(GadgetID(1), #LVM_SETINSERTMARKCOLOR, 0, $0000FF) ; couleur de la ligne d'insertion

SetWindowCallback(@WinProc(), 0)

Repeat
   Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
         Break
      Case #PB_Event_Gadget
         If EventGadget() = 0 And EventType() = #PB_EventType_DragStart
				drag = #True
            Row = GetGadgetState(0)
            
            If Row >= 0
               DragText(GetGadgetItemText(0, Row, 0) + #LF$ + GetGadgetItemText(0, Row, 1), #PB_Drag_Copy)
            EndIf
         EndIf
      Case #PB_Event_GadgetDrop
			drag = #False
         AddGadgetItem(1, RowInsertionIndex, EventDropText())
   EndSelect
ForEver
Windows 10 Pro x64
PureBasic 6.20 x64
User avatar
Shardik
Addict
Addict
Posts: 2058
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: Visual Help for drag&drop in ListView

Post by Shardik »

camille wrote:Does it fully eliminate the highlighting for you?

It does modify it here on my system (Windows Server 2019, 10.0.17763.107), but it is still a light blue (and not a darker one without the modification) that is visible when hovering over a column...
tatanas wrote:Same here too.
There is still a light blue selection.
Unfortunately you are both right.

I know that there always exists the possibility to use a callback like tatanas demonstrated and which also had been my first idea. But RASHAD's approach is so much simpler and shorter! I have now found a solution using RASHAD's approach. Please try and add the following code to my example or change RASHAD's code accordingly:

Code: Select all

Import "UxTheme.lib"
  SetWindowTheme(WindowHandle.I, SubAppName.P-Unicode, ClassNameList.P-Unicode)
EndImport

Code: Select all

SetWindowTheme(GadgetID(1), "", "STATUS")
camille
User
User
Posts: 71
Joined: Tue Nov 19, 2019 12:52 pm

Re: Visual Help for drag&drop in ListView

Post by camille »

Thanks for trying to "fix" this, Shardik!

With your latest modification the light blue is removed and it really looks like it should.

But...
There is a drawback.

Look at these pictures please:
01. Your code without the SetWindowTheme(GadgetID(1), "", "STATUS" line
https://imgur.com/a/UUlAML8

02. Your code including that line
https://imgur.com/a/3oUWNB2

The last one:
- The black border around the gadget is missing
- The column separation lines are shifted a bit to the left (marked in red) after the header row
tatanas
Enthusiast
Enthusiast
Posts: 260
Joined: Wed Nov 06, 2019 10:28 am
Location: France

Re: Visual Help for drag&drop in ListView

Post by tatanas »

You made my day Shardik ! :) And thank you to RASHAD too !

It is just I wanted to do :

Code: Select all

EnableExplicit

Import "UxTheme.lib"
  SetWindowTheme(WindowHandle.I, SubAppName.P-Unicode, ClassNameList.P-Unicode)
EndImport

Structure LVINSERTMARK
   cbSize.l
   dwFlags.l
   iItem.l
   dwReserved.l
EndStructure

Define HeaderHeight.I
Define Rectangle.RECT
Define Row.I
Define RowHeight.I
Define RowInsertionIndex.I


Procedure DragCallback(Action.I)
   Shared HeaderHeight.I
   Shared RowHeight.I
   Shared RowInsertionIndex.I
   
   Protected CursorPositon.POINT
   Protected InsertMark.LVINSERTMARK
   Protected Rectangle.RECT
   
   InsertMark\cbSize = SizeOf(LVINSERTMARK)
   GetCursorPos_(CursorPositon)
   GetWindowRect_(GadgetID(0), Rectangle)
   
   If PtInRect_(Rectangle, CursorPositon \ x + (CursorPositon \ y) << 32)
      MapWindowPoints_(0, GadgetID(0), CursorPositon, 1)
      
      ; ----- Display insertion line
      SendMessage_(GadgetID(0), #LVM_INSERTMARKHITTEST, @CursorPositon, @InsertMark)
   
      If SendMessage_(GadgetID(0), #LVM_SETINSERTMARK, 0, @InsertMark)
         RowInsertionIndex = InsertMark\iItem
         
         If (CursorPositon\y - HeaderHeight) % RowHeight > RowHeight * 0.5
            RowInsertionIndex + 1
         EndIf
      EndIf
      
      ProcedureReturn #True
   EndIf
EndProcedure

OpenWindow(0, 0, 0, 400, 500, "Drag row from left to right", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

ListIconGadget(0, 10, 10, 380, WindowHeight(0) - 20, "Name", 100, #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect)
AddGadgetColumn(0, 1, "Address", GadgetWidth(0) - GetGadgetItemAttribute(0, 0, #PB_ListIcon_ColumnWidth) - 4)
AddGadgetItem(0, -1, "Harry Rannit" + #LF$ + "12 Parliament Way, Battle Street, By the Bay")
AddGadgetItem(0, -1, "Ginger Brokeit" + #LF$ + "130 PureBasic Road, BigTown, CodeCity")
AddGadgetItem(0, -1, "Didi Foundit" + #LF$ + "321 Logo Drive, Mouse House, Downtown")
AddGadgetItem(0, -1, "Didi Foundit" + #LF$ + "321 Logo Drive, Mouse House, Downtown")
AddGadgetItem(0, -1, "Harry Rannit" + #LF$ + "12 Parliament Way, Battle Street, By the Bay")
AddGadgetItem(0, -1, "Ginger Brokeit" + #LF$ + "130 PureBasic Road, BigTown, CodeCity")


EnableGadgetDrop(0, #PB_Drop_Text, #PB_Drag_Copy)
SetDragCallback(@DragCallback())

; ----- Get height of header row
GetClientRect_(SendMessage_(GadgetID(0), #LVM_GETHEADER, 0, 0), @Rectangle)
HeaderHeight = Rectangle\bottom - Rectangle\top

; ----- Get height of single row
RowHeight = SendMessage_(GadgetID(0), #LVM_GETITEMSPACING, #True, 0) >> 16
SendMessage_(GadgetID(0), #LVM_SETINSERTMARKCOLOR, 0, $0000FF)


Repeat
   Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
         Break
      Case #PB_Event_Gadget
         If EventGadget() = 0 And EventType() = #PB_EventType_DragStart
				SetWindowTheme(GadgetID(0), "", "STATUS")
            Row = GetGadgetState(0)
            
            If Row >= 0
               DragText(GetGadgetItemText(0, Row, 0) + #LF$ + GetGadgetItemText(0, Row, 1), #PB_Drag_Copy)
            EndIf
         EndIf
      Case #PB_Event_GadgetDrop
			SetWindowTheme(GadgetID(0), #Null$, #Null$)
        AddGadgetItem(0, RowInsertionIndex, EventDropText())

   EndSelect
ForEver
EDIT1 : Where did you find the value to use with SetWindowTheme() ?
EDIT2 : It seems I can't reapply the previous theme after changing it. SetWindowTheme(GadgetID(0), #Null$, #Null$) is not working as it should or I'm not using it correctly.
Windows 10 Pro x64
PureBasic 6.20 x64
camille
User
User
Posts: 71
Joined: Tue Nov 19, 2019 12:52 pm

Re: Visual Help for drag&drop in ListView

Post by camille »

@tatanas

Your last code seems to work nicely in the first place but this happens when you add enough elements to the list view:

1. Just moved one line to duplicate so that the scrollbar appears (it's still fine)
https://imgur.com/a/BCcf9pP

2. Moved another line to duplicate it (it's getting ugly from here)
https://imgur.com/a/fEhXpMR
Post Reply