Что нового

Прорисовка Icon на форме при перемещении

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
Ни как не могу добиться корректной прорисовки иконки, при перемещении она плывёт.

OffTopic:

И если не так сложно, то как выравнить иконку по сетке, как на рабочем столе.


Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <WinAPIEx.au3>
#include <GDIPlus.au3>
#include <GuiImageList.au3>
#include <Misc.au3>

Global $hDesktop = RegRead("HKEY_CURRENT_USER\Control Panel\Desktop", "Wallpaper")

$hForm = GUICreate("Virtual Desktop", 800, 600)
$hListView = _GUICtrlListView_Create($hForm, 'Имя|Размер|Тип|Изменён', 0, 0, 800, 600, BitOR($LVS_EDITLABELS, $LVS_ICON, $LVS_NOSCROLL))
_GUICtrlListView_SetColumnWidth($hListView, 0, 200)
_GUICtrlListView_SetBkImageEx($hListView, $hDesktop)
_GUICtrlListView_SetTextColor($hListView, 0xFFFFFF)

$hImage = _GUIImageList_Create(32, 32, 5, 1)
_GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -49, 4)
_GUICtrlListView_SetImageList($hListView, $hImage, 0)
_GUICtrlListView_AddItem($hListView, "Мой компьютер", 0)

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUISetState()

While 1
    Switch GUIGetMsg()
	  Case $GUI_EVENT_PRIMARYDOWN
		 $nPOINT = _WinAPI_GetMousePos(True, $hListView)
		 $nX = DllStructGetData($nPOINT, 'X')
		 $nY = DllStructGetData($nPOINT, 'Y')
		 $lv_Item = _GUICtrlListView_GetHotItem($hListView)
		 If _GUICtrlListView_GetItemSelected($hListView, $lv_Item) Then
			Dim $iPos[2]
			$iPos[0] = _GUICtrlListView_GetItemPositionX($hListView, $lv_Item)
			$iPos[1] = _GUICtrlListView_GetItemPositionY($hListView, $lv_Item)
			While _IsPressed(1)
			   $tPOINT = _WinAPI_GetMousePos(True, $hListView)
			   $tX = DllStructGetData($tPOINT, 'X')
			   $tY = DllStructGetData($tPOINT, 'Y')
			   _GUICtrlListView_SetItemPosition($hListView, $lv_Item, $iPos[0] + $tX - $nX, $iPos[1] + $tY - $nY)
			   Sleep(20)
			WEnd 
		 EndIf
	  Case $GUI_EVENT_CLOSE
		 Exit
    EndSwitch       
WEnd

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
   $tNMTVDISPINFO = DllStructCreate($tagNMTVDISPINFO, $lParam)
   $iCode = DllStructGetData($tNMTVDISPINFO, "Code")
   $Index = _GUICtrlListView_GetSelectedIndices($hListView)
   If $iCode = $NM_DBLCLK And StringLen($Index) <> 0 Then
	  $lvText = _GUICtrlListView_GetItemText($hListView, $Index)
	  If $lvText = 'Мой компьютер' Then
         ShellExecute('::{20D04FE0-3AEA-1069-A2D8-08002B30309D}')
      EndIf
   EndIf
   Return $GUI_RUNDEFMSG
EndFunc 

Func _GUICtrlListView_SetBkImageEx($hWnd, $sImage, $iFlags = 0, $iXOffset = 0, $iYOffset = 0)

   Local $hImage, $hThumb, $hBitmap, $tLVBKIMAGE, $pLVBKIMAGE, $tMem, $pMem, $Ret, $Size

   _GDIPlus_Startup()
   $hImage = _GDIPlus_ImageLoadFromFile($sImage)
   $hThumb = DllCall($ghGDIPDll, "int", "GdipGetImageThumbnail", "ptr", $hImage, _
                                 "int", _WinAPI_GetWindowWidth($hWnd), "int", _WinAPI_GetWindowHeight($hWnd), _
								 "ptr*", 0, "ptr", 0, "ptr", 0)
								 
   $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hThumb[4])
   If $hBitmap Then
	  $iFlags = BitOR(BitAND($iFlags, BitOR($LVBKIF_FLAG_TILEOFFSET, $LVBKIF_STYLE_TILE, $LVBKIF_TYPE_WATERMARK, 0x20000000)), $LVBKIF_SOURCE_HBITMAP)
   Else
	  $iFlags = 0
   EndIf
   $tLVBKIMAGE = DllStructCreate('ulong;ptr;ptr;uint;int;int')
   $pLVBKIMAGE = DllStructGetPtr($tLVBKIMAGE)
   DllStructSetData($tLVBKIMAGE, 1, $iFlags)
   DllStructSetData($tLVBKIMAGE, 2, $hBitmap)
   DllStructSetData($tLVBKIMAGE, 5, $iXOffset)
   DllStructSetData($tLVBKIMAGE, 6, $iYOffset)
   $Ret = _SendMessage($hWnd, 4234, 0, $pLVBKIMAGE)
   _GDIPlus_ImageDispose($hThumb[4])
   _WinAPI_DeleteObject($hBitmap)
   _GDIPlus_Shutdown()
	 
    Return $Ret <> 0
EndFunc
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Вообще, смотрите в сторону LVN_BEGINDRAG/LVN_ENDDRAG. Касаемо вашего кода, то во-первых, уберите Sleep(20), а во-вторых, _GUICtrlListView_SetItemPosition() нужно вызывать только в том случае, если координаты курсора изменились, тогда и мерцать не будет.


Добавлено:
Сообщение автоматически объединено:

Viktor1703 сказал(а):
И если не так сложно, то как выравнить иконку по сетке, как на рабочем столе.

Код:
_GUICtrlListView_Arrange($hListView, 3)
 
Автор
V

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
Чуть - чуть не понятно про LVN_BEGINDRAG, нашёл пример использования, но иконка не перемещается:
И плохая прорисовка происходит из - за курсора, при перемещении у курсора в правом нижнем углу появляется +, он и мешает, очень много для меня не понятного в ListView, например есть функция _GUICtrlListView_SetHotCursor(), я так понял устанавливает курсор, а вот как, не понял, пробовал - не получилось, и после перемещения иконки, при отпускании ЛКМ воспроизводится звук, в UDF я не нашёл функции для отключения, в стилях тоже, а может и пропустил (очень плохо английский понимаю).
Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <WinAPIEx.au3>
#include <GDIPlus.au3>
#include <GuiImageList.au3>
#include <Misc.au3>

Global $fDrag = False, $iOld, $sOld
Global $hDesktop = RegRead("HKEY_CURRENT_USER\Control Panel\Desktop", "Wallpaper")

$hForm = GUICreate("Virtual Desktop", 800, 600)
$hListView = _GUICtrlListView_Create($hForm, 'Имя|Размер|Тип|Изменён', 0, 0, 800, 600, BitOR($LVS_EDITLABELS, $LVS_ICON, $LVS_NOSCROLL))
_GUICtrlListView_SetColumnWidth($hListView, 0, 200)
_GUICtrlListView_SetBkImageEx($hListView, $hDesktop)
_GUICtrlListView_SetTextColor($hListView, 0xFFFFFF)

$hImage = _GUIImageList_Create(32, 32, 5, 1)
_GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -49, 4)
_GUICtrlListView_SetImageList($hListView, $hImage, 0)
_GUICtrlListView_AddItem($hListView, "Мой компьютер", 0)

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUISetState()

While 1
   Switch GUIGetMsg()
	  Case $GUI_EVENT_PRIMARYDOWN
		 $nPOINT = _WinAPI_GetMousePos(True, $hListView)
		 $nX = DllStructGetData($nPOINT, 'X')
		 $nY = DllStructGetData($nPOINT, 'Y')
		 $lv_Item = _GUICtrlListView_GetSelectedIndices($hListView)
		 If _GUICtrlListView_GetItemSelected($hListView, $lv_Item) Then
			Dim $iPos[2]
			$iPos[0] = _GUICtrlListView_GetItemPositionX($hListView, $lv_Item)
			$iPos[1] = _GUICtrlListView_GetItemPositionY($hListView, $lv_Item)
			While _IsPressed(1)
			   $tPOINT = _WinAPI_GetMousePos(True, $hListView)
			   $tX = DllStructGetData($tPOINT, 'X')
			   $tY = DllStructGetData($tPOINT, 'Y')
			   _GUICtrlListView_SetItemPosition($hListView, $lv_Item, $iPos[0] + $tX - $nX, $iPos[1] + $tY - $nY)
			   Sleep(20)
			WEnd 
		 EndIf
	  Case $GUI_EVENT_CLOSE
		 Exit
   EndSwitch       
WEnd

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
   If Not IsHWnd($hListView) Then $hListView = GUICtrlGetHandle($hListView) 
   $tNMHDR = DllStructCreate($tagNMHDR, $lParam) 
   $hWndFrom = HWnd(DllStructGetData($tNMHDR, 'hWndFrom')) 
   $iCode = DllStructGetData($tNMHDR, 'Code') 
   Switch $hWndFrom
	  Case $hListView
	     Switch $iCode
			Case $LVN_BEGINDRAG
			   $tInfo = DllStructCreate($tagNMITEMACTIVATE, $lParam) 
	           $iItem = DllStructGetData($tInfo, 'Index') 
			   $iOld = $iItem 
	           $sOld = _GUICtrlListView_GetItemText($hListView, $iOld) 
	           $fDrag = True
			Case $LVN_HOTTRACK  
			   If $fDrag Then 
				  $tInfo = DllStructCreate($tagNMITEMACTIVATE, $lParam) 
				  $iItem = DllStructGetData($tInfo, 'Index') 
				  If $iItem > -1 And $iItem < _GUICtrlListView_GetItemCount($hListView) Then 
					 _GUICtrlListView_DeleteItem($hListView, $iOld) 
					 _GUICtrlListView_InsertItem($hListView, $sOld, $iItem) 
				  EndIf 
				  $fDrag = False 
			   EndIf 
            Case $NM_DBLCLK
	           $lvText = _GUICtrlListView_GetItemText($hListView, $iOld)
	           If $lvText = 'Мой компьютер' Then
                  ShellExecute('::{20D04FE0-3AEA-1069-A2D8-08002B30309D}')
               EndIf
		 EndSwitch
   EndSwitch		
   Return $GUI_RUNDEFMSG
EndFunc 

Func _GUICtrlListView_SetBkImageEx($hWnd, $sImage, $iFlags = 0, $iXOffset = 0, $iYOffset = 0)

   Local $hImage, $hThumb, $hBitmap, $tLVBKIMAGE, $pLVBKIMAGE, $tMem, $pMem, $Ret, $Size

   _GDIPlus_Startup()
   $hImage = _GDIPlus_ImageLoadFromFile($sImage)
   $hThumb = DllCall($ghGDIPDll, "int", "GdipGetImageThumbnail", "ptr", $hImage, _
                                 "int", _WinAPI_GetWindowWidth($hWnd), "int", _WinAPI_GetWindowHeight($hWnd), _
								 "ptr*", 0, "ptr", 0, "ptr", 0)
								 
   $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hThumb[4])
   If $hBitmap Then
	  $iFlags = BitOR(BitAND($iFlags, BitOR($LVBKIF_FLAG_TILEOFFSET, $LVBKIF_STYLE_TILE, $LVBKIF_TYPE_WATERMARK, 0x20000000)), $LVBKIF_SOURCE_HBITMAP)
   Else
	  $iFlags = 0
   EndIf
   $tLVBKIMAGE = DllStructCreate('ulong;ptr;ptr;uint;int;int')
   $pLVBKIMAGE = DllStructGetPtr($tLVBKIMAGE)
   DllStructSetData($tLVBKIMAGE, 1, $iFlags)
   DllStructSetData($tLVBKIMAGE, 2, $hBitmap)
   DllStructSetData($tLVBKIMAGE, 5, $iXOffset)
   DllStructSetData($tLVBKIMAGE, 6, $iYOffset)
   $Ret = _SendMessage($hWnd, 4234, 0, $pLVBKIMAGE)
   _GDIPlus_ImageDispose($hThumb[4])
   _WinAPI_DeleteObject($hBitmap)
   _GDIPlus_Shutdown()
	 
    Return $Ret <> 0
EndFunc
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Код:
#Include <APIConstants.au3>
#Include <GUIConstantsEx.au3>
#include <GUIImageList.au3>
#Include <GUIListView.au3>
#Include <ListViewConstants.au3>
#Include <WinAPIEx.au3>

Global $hDragList = 0, $Item, $Dx, $Dy, $Px, $Py, $Xi, $Yi, $Xp = Default, $Yp = Default, $Reset = False

$hForm = GUICreate('MyGUI', 800, 600)
$hLV = _GUICtrlListView_Create($hForm, '', 0, 0, 800, 600, BitOR($LVS_EDITLABELS, $LVS_ICON, $LVS_NOSCROLL, $LVS_SINGLESEL), $LVS_EX_DOUBLEBUFFER, 1)
_GUICtrlListView_SetBkImage($hLV, RegRead('HKEY_CURRENT_USER\Control Panel\Desktop', 'Wallpaper'))
_GUICtrlListView_SetTextColor($hLV, 0xFFFFFF)
$hIL = _GUIImageList_Create(32, 32, 5, 1)
_GUIImageList_AddIcon($hIL, @SystemDir & '\shell32.dll', -49, 1)
_GUICtrlListView_SetImageList($hLV, $hIL, 0)
_GUICtrlListView_AddItem($hLV, 'My Computer', 0)
GUIRegisterMsg($WM_NOTIFY, 'WM_NOTIFY')
GUISetState()

While 1
	If $hDragList Then
		$hLVDC = _WinAPI_GetWindowDC($hLV)
		$Size = _GUIImageList_GetIconSize($hDragList)
		While BitAND(_WinAPI_GetAsyncKeyState(0x01), 0x8000)
			$tPoint = _WinAPI_GetMousePos(1, $hLV)
			$X =  DllStructGetData($tPoint, 1)
			$Y =  DllStructGetData($tPoint, 2)
			If ($X <> $Xp) Or ($Y <> $Yp) Then
				_WinAPI_InvalidateRect($hLV, _WinAPI_CreateRectEx($Xp - $Dx, $Yp - $Dy + 1, $Size[0], $Size[1]))
				_GUIImageList_Draw($hDragList, 0, $hLVDC, $X - $Dx, $Y - $Dy + 1, 1)
				$Xp = $X
				$Yp = $Y
			EndIf
			$Reset = 1
		WEnd
		If $Reset Then
			_WinAPI_InvalidateRect($hLV, _WinAPI_CreateRectEx($Xp - $Dx, $Yp - $Dy + 1, $Size[0], $Size[1]))
			_GUICtrlListView_SetItemPosition($hLV, $Item, $X - $Px, $Y - $Py)
			_GUICtrlListView_Arrange($hLV, 3)
			$Reset = 0
		EndIf
		_GUIImageList_Destroy($hDragList)
		_WinAPI_ReleaseDC($hLV, $hLVDC)
		$hDragList = 0
	EndIf
    Switch GUIGetMsg()
        Case 0
            ContinueLoop
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    Local $tNMLV = DllStructCreate($tagNMLISTVIEW, $lParam)
    Local $hTarget = DllStructGetData($tNMLV, 'hWndFrom')
    Local $ID = DllStructGetData($tNMLV, 'Code')
    Switch $hTarget
		Case $hLV
            Switch $ID
				Case $LVN_BEGINDRAG
					Local $tPoint = DllStructCreate($tagPOINT)
					$Item = DllStructGetData($tNMLV, 'Item')
					$hDragList = _SendMessage($hLV, $LVM_CREATEDRAGIMAGE, $Item, DllStructGetPtr($tPoint))
					$Dx = $Xi - DllStructGetData($tPoint, 1)
					$Dy = $Yi - DllStructGetData($tPoint, 2)
					$Pos = _GUICtrlListView_GetItemPosition($hLV, $Item)
					$Px = $Xi - $Pos[0]
					$Py = $Yi - $Pos[1]
					Return 0
				Case $LVN_HOTTRACK
					Local $tPoint = _WinAPI_GetMousePos(1, $hLV)
					$Xi = DllStructGetData($tPoint, 1)
					$Yi = DllStructGetData($tPoint, 2)
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY
 
Верх