Что нового

[Элементы GUI] GUICtrlCreateListView - изменение порядка элементов drag&drop'ом

killbond

Осваивающий
Сообщения
96
Репутация
32
Имеется GUICtrlCreateListView, в качестве элементов в него добавляется 2D массив, один из элементов которого хранит в себе порядок, нужно организовать изменение порядка элементов списка drag'n'drop-ом, при том, необходимо учесть, что после перетаскивания порядок в виде числа, который хранится в массиве, тоже менялся, как это сделать?

Вот пример в качестве "болванки":
Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#Include <GuiListView.au3>

dim $aItems [5] [3] = [ _ 
[ 1, "1 элемент", "1 элемент" ], _ 
[ 2, "2 элемент", "2 элемент" ], _ 
[ 3, "3 элемент", "3 элемент" ], _ 
[ 4, "4 элемент", "4 элемент" ], _ 
[ 5, "5 элемент", "5 элемент" ] ]

$hForm1 = GUICreate("GUICtrlCreateListView ", 400, 400, 300, 150, _ 
BitOR($WS_SYSMENU,$WS_CAPTION,$WS_POPUP,$WS_POPUPWINDOW,$WS_BORDER,$WS_CLIPSIBLINGS, $WS_EX_ACCEPTFILES))

$hList = GUICtrlCreateListView ( "Порядок|Данные|Данные", 20, 20 , 360 , 360, $GUI_SS_DEFAULT_LISTVIEW, _ 
BitOR($LVS_EX_HEADERDRAGDROP, $LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT ))

_GUICtrlListView_SetColumnWidth($hList, 0, 60)
_GUICtrlListView_SetColumnWidth($hList, 1, 150)
_GUICtrlListView_SetColumnWidth($hList, 2, 145)

_GUICtrlListView_AddArray($hList, $aItems)

GUICtrlSetState($hList, $GUI_DROPACCEPTED)
GUISetState(@SW_SHOW)

Do
$nMsg = GUIGetMsg()
Until $nMsg = $GUI_EVENT_CLOSE
exit
 

bulldog5293

Знающий
Сообщения
172
Репутация
10
Не знаю я что тебе там нужно, т.к. всё равно не сильно автоит понимаю, но твой пример в моём проекте помог, если позже пойму что тебе нужно то напишу
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Если я правильно понял, то нужно добавить Drag & Drop пунктов списка, и менять первую колонку таким образом, чтобы там всегда было 1 2 3 4 5 и т.д...

Тема конечно старая, но вот решение:

Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GUIListView.au3>

Global $iLast_Index = -1
Global $a_Index[2] ;From and to
Global $iLastLineTop, $iLastLineLeft

Global $iDragging = False
Global $iDrawing = False ;To ensure mousemove doesn't cause more than one line to be drawn
Global $iLButtonIsUp = False ;To ensure a correct redraw of ListView

Dim $aItems[5][3] = [ _
		[1, "1 элемент", "1 элемент"], _
		[2, "2 элемент", "2 элемент"], _
		[3, "3 элемент", "3 элемент"], _
		[4, "4 элемент", "4 элемент"], _
		[5, "5 элемент", "5 элемент"]]

$hForm1 = GUICreate("GUICtrlCreateListView ", 400, 400, 300, 150, _
	BitOR($WS_SYSMENU, $WS_CAPTION, $WS_POPUP, $WS_POPUPWINDOW, $WS_BORDER, $WS_CLIPSIBLINGS, $WS_EX_ACCEPTFILES))

$nListView = GUICtrlCreateListView("Порядок|Данные|Данные", 20, 20, 360, 360, $GUI_SS_DEFAULT_LISTVIEW, _
	BitOR($LVS_EX_HEADERDRAGDROP, $LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT))
$hListView = GUICtrlGetHandle($nListView)

GUICtrlSetState($nListView, $GUI_DROPACCEPTED)

_GUICtrlListView_SetColumnWidth($hListView, 0, 60)
_GUICtrlListView_SetColumnWidth($hListView, 1, 150)
_GUICtrlListView_SetColumnWidth($hListView, 2, 145)

_GUICtrlListView_AddArray($hListView, $aItems)

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY_EVENTS")
GUIRegisterMsg($WM_LBUTTONUP, "WM_LBUTTONUP_EVENTS")
GUIRegisterMsg($WM_MOUSEMOVE, "WM_MOUSEMOVE_EVENTS")

GUISetState(@SW_SHOW)

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
	EndSwitch

	If $iLButtonIsUp Then
		$iLButtonIsUp = False
		_WinAPI_RedrawWindow($hListView)
	EndIf
WEnd

Func _WinAPI_DrawLineEx($iLeft, $iTop, $iWidth, $iHeight, $sColor, $hWnd = 0)
	$iDrawing = True
	$sColor = Hex("0x" & BitAND(BitShift(String(Binary($sColor)), 8), 0xFFFFFF)) ;RGB2BGR
	
	Local $hDC = DllCall("User32.dll", "int", "GetDC", "hwnd", $hWnd)
	Local $aPen = DllCall("GDI32.dll", "int", "CreatePen", "int", 0, "int", $iHeight, "int", $sColor)
	
	DllCall("GDI32.dll", "int", "SelectObject", "int", $hDC[0], "int", $aPen[0])
	
	If $iLastLineTop > -1 And $iLastLineLeft > -1 Then
		If $iLastLineTop <> $iTop Then
			$iLastLineLeft = $iLeft
			$iLastLineTop = $iTop

			DllCall("user32.dll", "int", "InvalidateRect", "hwnd", $hWnd, "int", 0, "int", 1)
			Sleep(50) ;seems to be needed to ensure redrawn before line is drawn
		EndIf
	EndIf

	DllCall("GDI32.dll", "int", "MoveToEx", "hwnd", $hDC[0], "int", $iLeft, "int", $iTop, "int", 0)
	DllCall("GDI32.dll", "int", "LineTo", "hwnd", $hDC[0], "int", $iLeft + $iWidth, "int", $iTop)

	DllCall("user32.dll", "int", "ReleaseDC", "hwnd", $hWnd, "int", $hDC[0])
	DllCall("GDI32.dll", "int", "DeleteObject", "int", $aPen[0])

	$iDrawing = False
EndFunc   ;==>_DrawLine

Func _GUICtrlListView_CopyItemsEx($hWnd_Source, $hWnd_Destination, $iSrcIndex, $iDstIndex, $fDelFlag = False)
	Local $iInsert_Index
	Local $tItem = DllStructCreate($tagLVITEM)

	Local $iCols = _GUICtrlListView_GetColumnCount($hWnd_Source)
	Local $iItems = _GUICtrlListView_GetItemCount($hWnd_Source)
	Local $iDest_Items = _GUICtrlListView_GetItemCount($hWnd_Destination)

	_GUICtrlListView_BeginUpdate($hWnd_Source)

	If $hWnd_Destination <> $hWnd_Source Then
		_GUICtrlListView_BeginUpdate($hWnd_Destination)
	EndIf

	DllStructSetData($tItem, "Mask", BitOR($LVIF_GROUPID, $LVIF_IMAGE, $LVIF_INDENT, $LVIF_PARAM, $LVIF_STATE))
	DllStructSetData($tItem, "Item", $iSrcIndex)
	DllStructSetData($tItem, "SubItem", 0)
	DllStructSetData($tItem, "StateMask", -1)

	_GUICtrlListView_GetItemEx($hWnd_Source, $tItem)

	If $iDstIndex > $iSrcIndex Then
		$iDstIndex += 1
	ElseIf $iSrcIndex > $iDstIndex Then
		$iSrcIndex += 1
	EndIf

	$iInsert_Index = _GUICtrlListView_InsertItem($hWnd_Destination, _
			_GUICtrlListView_GetItemText($hWnd_Source, $iSrcIndex, 0), $iDstIndex, DllStructGetData($tItem, "Image"), _
			_GUICtrlListView_GetItemParam($hWnd_Source, $iSrcIndex))

	If BitAND(_GUICtrlListView_GetExtendedListViewStyle($hWnd_Source), $LVS_EX_CHECKBOXES) == $LVS_EX_CHECKBOXES Then
		If _GUICtrlListView_GetItemChecked($hWnd_Source, $iSrcIndex) Then
			_GUICtrlListView_SetItemChecked($hWnd_Destination, $iInsert_Index)
		EndIf
	EndIf

	For $i = 0 To $iCols - 1
		DllStructSetData($tItem, "Item", $iInsert_Index)
		DllStructSetData($tItem, "SubItem", $i)

		_GUICtrlListView_GetItemEx($hWnd_Source, $tItem)

		_GUICtrlListView_AddSubItem($hWnd_Destination, $iInsert_Index, _
				_GUICtrlListView_GetItemText($hWnd_Source, $iSrcIndex, $i), $i, DllStructGetData($tItem, "Image"))
	Next

	If $fDelFlag Then _GUICtrlListView_DeleteItem($hWnd_Source, $iSrcIndex)

	If $iDstIndex > $iSrcIndex Then $iDstIndex -= 1
	_GUICtrlListView_SetItemSelected($hWnd_Source, $iDstIndex)

	_GUICtrlListView_EndUpdate($hWnd_Source)

	If $hWnd_Destination <> $hWnd_Source Then
		_GUICtrlListView_EndUpdate($hWnd_Destination)
	EndIf

	_GUICtrlListView_RedrawItems($hWnd_Destination, $iSrcIndex, $iDstIndex)
EndFunc   ;==>_GUICtrlListView_CopyItemsEx

Func WM_LBUTTONUP_EVENTS($hWndGUI, $MsgID, $wParam, $lParam)
	$iLButtonIsUp = True
	$iDragging = False
	$iDrawing = False

	$iLast_Index = -1

	Local $aLV_Pos = ControlGetPos($hWndGUI, "", $nListView)

	Local $iX = BitAND($lParam, 0xFFFF) - $aLV_Pos[0]
	Local $iY = BitShift($lParam, 16) - $aLV_Pos[1]

	Local $struct_LVHITTESTINFO = DllStructCreate("int;int;uint;int;int;int")

	DllStructSetData($struct_LVHITTESTINFO, 1, $iX)
	DllStructSetData($struct_LVHITTESTINFO, 2, $iY)

	$a_Index[1] = GUICtrlSendMsg($nListView, $LVM_HITTEST, 0, DllStructGetPtr($struct_LVHITTESTINFO))
	Local $iFlags = DllStructGetData($struct_LVHITTESTINFO, 2)

	;// Out of the ListView?
	If $a_Index[1] = -1 Then $a_Index[1] = _GUICtrlListView_GetItemCount($hListView) - 1 ;Return $GUI_RUNDEFMSG

	;// Not in an item?
	;If BitAND($iFlags, $LVHT_ONITEMLABEL) = 0 And BitAND($iFlags, $LVHT_ONITEMSTATEICON) = 0 Then
	;	Return $GUI_RUNDEFMSG
	;EndIf

	If $a_Index[0] < $a_Index[1] Then
		_GUICtrlListView_CopyItemsEx($hListView, $hListView, $a_Index[0], $a_Index[1], 1)
	ElseIf $a_Index[0] > $a_Index[1] Then
		_GUICtrlListView_CopyItemsEx($hListView, $hListView, $a_Index[0], $a_Index[1], 1)
	EndIf

	For $i = 0 To _GUICtrlListView_GetItemCount($hListView) - 1
		_GUICtrlListView_SetItemText($hListView, $i, $i + 1, 0)
	Next

	Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_LBUTTONUP_EVENTS

Func WM_MOUSEMOVE_EVENTS($hWndGUI, $MsgID, $wParam, $lParam)
	If Not $iDragging Or $iDrawing Then
		Return $GUI_RUNDEFMSG
	EndIf

	Local $aLV_Pos = ControlGetPos($hWndGUI, "", $nListView)

	Local $iX = BitAND($lParam, 0xFFFF) - $aLV_Pos[0]
	Local $iY = BitShift($lParam, 16) - $aLV_Pos[1]

	Local $struct_LVHITTESTINFO = DllStructCreate("int;int;uint;int;int;int")

	DllStructSetData($struct_LVHITTESTINFO, 1, $iX)
	DllStructSetData($struct_LVHITTESTINFO, 2, $iY)

	Local $iItem = GUICtrlSendMsg($nListView, $LVM_HITTEST, 0, DllStructGetPtr($struct_LVHITTESTINFO))
	If $iItem = -1 Then $iItem = _GUICtrlListView_GetItemCount($hListView) ;Return $GUI_RUNDEFMSG

	If $iLast_Index = $iItem Then Return $GUI_RUNDEFMSG

	If $iLast_Index > $iItem Then ;Move up
		_GUICtrlListView_RedrawItems($hListView, $iItem, $iLast_Index)
	Else
		_GUICtrlListView_RedrawItems($hListView, $iLast_Index, $iItem - 1)
	EndIf

	$iLast_Index = $iItem

	Local $aLV_Pos = ControlGetPos($hWndGUI, "", $nListView)
	Local $iX = _GUICtrlListView_GetItemPositionX($hListView, $iItem)
	Local $iY = _GUICtrlListView_GetItemPositionY($hListView, $iItem)

	If $iX < 0 Or $iY <= 0 Then
		Return $GUI_RUNDEFMSG
	EndIf
	
	_WinAPI_DrawLineEx($iX, $iY, $aLV_Pos[2], 2.5, 0xFF0000, $hListView)
EndFunc   ;==>WM_MOUSEMOVE_EVENTS

Func WM_NOTIFY_EVENTS($hWndGUI, $MsgID, $wParam, $lParam)
	Local $tagNMHDR, $iEvent, $hwndFrom, $iCode, $iItem

	$tagNMHDR = DllStructCreate("int;int;int;int", $lParam) ;NMHDR (hwndFrom, idFrom, code, Item)
	If @error Then Return $GUI_RUNDEFMSG

	$iCode = DllStructGetData($tagNMHDR, 3)
	$iItem = DllStructGetData($tagNMHDR, 4)

	Switch $wParam
		Case $nListView
			Switch $iCode
				Case $LVN_BEGINDRAG
					$a_Index[0] = $iItem
					$iDragging = True

					;_GUICtrlListView_SetItemSelected($ListView, $iItem, False)
			EndSwitch
	EndSwitch

	Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY_EVENTS
 
Верх