Что нового

Перемещение элемента с помощью мышки

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Этот простой пример показывает как можно задать перемещение (перетаскивание) указанного элемента GUI при помощи указателя мышки.

Код:
#include <GUIConstantsEx.au3>

$hGUI = GUICreate("Move Label")
$Label = GUICtrlCreateLabel("My Label, Move me ;)", 20, 20, -1, 16)
GUICtrlSetCursor(-1, 0)

GUISetState()

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
		Case $GUI_EVENT_PRIMARYDOWN
			Ctrl_Drag_And_Move($hGUI, $Label)
	EndSwitch
WEnd

Func Ctrl_Drag_And_Move($hGUI, $nCtrlID)
	Local $iOld_Opt_MCM = Opt("MouseCoordMode", 2)
	
	Local $aCurInfo = GUIGetCursorInfo($hGUI)
	Local $aCtrl_Pos, $aMouse_Pos, $iNewLeft_Pos, $iNewTop_Pos
	
	If IsArray($aCurInfo) And $aCurInfo[2] = 1 And $aCurInfo[4] = $nCtrlID Then
		While IsArray($aCurInfo) And $aCurInfo[2] = 1
			$aCurInfo = GUIGetCursorInfo($hGUI)
			$aCtrl_Pos = ControlGetPos($hGUI, "", $nCtrlID)
			$aMouse_Pos = MouseGetPos()
			
			$iNewLeft_Pos = $aMouse_Pos[0] - ($aCtrl_Pos[2] / 2)
			$iNewTop_Pos = $aMouse_Pos[1] - ($aCtrl_Pos[3] / 2)
			
			If $aCtrl_Pos[0] <> $iNewLeft_Pos Or $aCtrl_Pos[1] <> $iNewTop_Pos Then
				GUICtrlSetPos($nCtrlID, $iNewLeft_Pos, $iNewTop_Pos)
			Else
				Sleep(5)
			EndIf
		WEnd
	EndIf
	
	Opt("MouseCoordMode", $iOld_Opt_MCM)
EndFunc
 
  • Like
Реакции: Norm

AZJIO

Меценат
Меценат
Сообщения
2,874
Репутация
1,194
К этому скрипту добавить бы прозрачность и возвращение координат элемента в буфер (и в подсказку), получилась бы удобная утилитка, ту что я просил на руборде. Переделывать фейс в Koda не очень удобно, готовый скрипт она не перевариавает, обрезаю скрипт оставляя только элементы и начинает работать.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Примерно так:

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

$hGUI = GUICreate("Move Label")
$Checkbox = GUICtrlCreateCheckbox("My Checkbox, Move me ;)", 20, 20, -1, 16)
$Label = GUICtrlCreateLabel("My Label, Move me ;)", 20, 50, -1, 16)
GUICtrlSetCursor(-1, 0)

GUISetState()

While 1
	Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
			Exit
		Case $GUI_EVENT_PRIMARYDOWN
			Ctrl_Drag_And_Move($hGUI, $Checkbox, "Checkbox")
			Ctrl_Drag_And_Move($hGUI, $Label, "Label")
	EndSwitch
WEnd

Func Ctrl_Drag_And_Move($hGUI, $nCtrlID, $sCtrlName)
	Local $aCur_Info, $aCtrl_Pos, $aMouse_Pos, $iNewLeft_Pos, $iNewTop_Pos, $aRet[2]
	Local $stPoint, $iOld_Opt_MCM, $aGUI_Pos, $aCtrl_Pos, $hGUI_Dummy, $nCtrlID_Dummy
	
	$aMouse_Pos = MouseGetPos()
	
	$stPoint = DllStructCreate("int X;int Y")
	DllStructSetData($stPoint, 1, $aMouse_Pos[0])
	DllStructSetData($stPoint, 2, $aMouse_Pos[1])
	
	If _WinAPI_WindowFromPoint($stPoint) <> GUICtrlGetHandle($nCtrlID) Then
		Return SetError(1, 0, 0)
	EndIf
	
	$iOld_Opt_MCM = Opt("MouseCoordMode", 2)
	$aGUI_Pos = WinGetPos($hGUI)
	$aCtrl_Pos = ControlGetPos($hGUI, "", $nCtrlID)
	
	$hGUI_Dummy = GUICreate("", _
		$aGUI_Pos[2]-10, $aGUI_Pos[3]-30, $aGUI_Pos[0]+5, $aGUI_Pos[1]+25, $WS_POPUP, $WS_EX_TOPMOST, $hGUI)
	
	$nCtrlID_Dummy = Execute("GUICtrlCreate" & $sCtrlName & _
		'(' & _
		'"' & GUICtrlRead($nCtrlID, 1) & '", ' & _
		$aCtrl_Pos[0] & ', ' & _
		$aCtrl_Pos[1] & ', ' & _
		$aCtrl_Pos[2] & ', ' & _
		$aCtrl_Pos[3] & _
		')')
	
	WinSetTrans($hGUI_Dummy, "", 50)
	GUISetState(@SW_SHOW, $hGUI_Dummy)
	
    $aCur_Info = GUIGetCursorInfo($hGUI_Dummy)
    
	GUICtrlSetState($nCtrlID, $GUI_HIDE)
	
    If IsArray($aCur_Info) And $aCur_Info[2] = 1 Then
        While IsArray($aCur_Info) And $aCur_Info[2] = 1
            $aCur_Info = GUIGetCursorInfo($hGUI_Dummy)
            $aCtrl_Pos = ControlGetPos($hGUI_Dummy, "", $nCtrlID_Dummy)
            $aMouse_Pos = MouseGetPos()
            
            $iNewLeft_Pos = $aMouse_Pos[0] - ($aCtrl_Pos[2] / 2)
            $iNewTop_Pos = $aMouse_Pos[1] - ($aCtrl_Pos[3] / 2)
            
            If $aCtrl_Pos[0] <> $iNewLeft_Pos Or $aCtrl_Pos[1] <> $iNewTop_Pos Then
                GUICtrlSetPos($nCtrlID_Dummy, $iNewLeft_Pos, $iNewTop_Pos)
				
				ToolTip($sCtrlName & " coords:" & @CRLF & "X: " & $iNewLeft_Pos & @CRLF & "Y: " & $iNewTop_Pos, _
					$aGUI_Pos[0] + $aMouse_Pos[0] + 20, $aGUI_Pos[1] + $aMouse_Pos[1] + 50)
            Else
                Sleep(5)
            EndIf
        WEnd
    EndIf
    
	ToolTip("")
	
	If $iNewLeft_Pos And $iNewTop_Pos Then GUICtrlSetPos($nCtrlID, $iNewLeft_Pos+2, $iNewTop_Pos+3)
	GUICtrlSetState($nCtrlID, $GUI_SHOW)
	GUIDelete($hGUI_Dummy)
	
    Opt("MouseCoordMode", $iOld_Opt_MCM)
	
	$aRet[0] = $iNewLeft_Pos
	$aRet[1] = $iNewTop_Pos
	
	Return $aRet
EndFunc
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
CreatoR
Ваш первый код отрабатывает у меня отлично, а второй не работает, то есть в окне Checkbox и Label, которые не перетаскиваются. :(
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
madmasles [?]
второй не работает
А всё потому, что в версий 3.3.2.0, в функций _WinAPI_WindowFromPoint использовались имена элементов структуры, вместо их индексов, это видимо поправили в 3.3.4.0 (я не уверен, но в списке изменений про это забыли написать).

Я поправил свой код (добавил имена к данным в структуре), теперь должно работать и там там.

P.S
Я вовсе не понимаю, зачем там нужна структура...
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
CreatoR
Вы извините за мою назойливость :smile:, теперь все перетаскивается, но Checkbox не отметить.
 

AZJIO

Меценат
Меценат
Сообщения
2,874
Репутация
1,194
CreatoR
Я имел ввиду прозрачность окна. Чтобы поверх своего скрипта его поставить и передвинуть элемент в нужную позицию. И сделать элемент кнопкой, чтобы по нажатию она возвращала координаты в буфер обмена.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
AZJIO [?]
Я имел ввиду прозрачность окна. Чтобы поверх своего скрипта его поставить и передвинуть элемент в нужную позицию. И сделать элемент кнопкой, чтобы по нажатию она возвращала координаты в буфер обмена.
Это проще...

Код:
#include <GUIConstantsEx.au3>

$hGUI = GUICreate("Move Label")
WinSetTrans($hGUI, "", 150)

$Label = GUICtrlCreateLabel("My Label, Move me ;)", 20, 20, -1, 16)
GUICtrlSetCursor($Label, 0)

$Checkbox = GUICtrlCreateCheckbox("My Checkbox, Move me ;)", 20, 50, -1, 16)
GUICtrlSetCursor($Checkbox, 0)

GUISetState()

While 1
	$nMsg = GUIGetMsg()
	
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit
		Case $GUI_EVENT_PRIMARYDOWN
			Ctrl_Drag_And_Move($hGUI, $Label)
			Ctrl_Drag_And_Move($hGUI, $Checkbox)
			
			Local $aCurInfo = GUIGetCursorInfo($hGUI)
			
			If $aCurInfo[4] > 0 Then
				$aCtrl_Pos = ControlGetPos($hGUI, "", $aCurInfo[4])
				ClipPut("X: " & $aCtrl_Pos[0] & @CRLF & "Y: " & $aCtrl_Pos[1])
			EndIf
	EndSwitch
WEnd

Func Ctrl_Drag_And_Move($hGUI, $nCtrlID)
	Local $iOld_Opt_MCM = Opt("MouseCoordMode", 2)
	
	Local $aCurInfo = GUIGetCursorInfo($hGUI)
	Local $aCtrl_Pos, $aMouse_Pos, $iNewLeft_Pos, $iNewTop_Pos
	
	If IsArray($aCurInfo) And $aCurInfo[2] = 1 And $aCurInfo[4] = $nCtrlID Then
		While IsArray($aCurInfo) And $aCurInfo[2] = 1
			$aCurInfo = GUIGetCursorInfo($hGUI)
			$aCtrl_Pos = ControlGetPos($hGUI, "", $nCtrlID)
			$aMouse_Pos = MouseGetPos()
			
			$iNewLeft_Pos = $aMouse_Pos[0] - ($aCtrl_Pos[2] / 2)
			$iNewTop_Pos = $aMouse_Pos[1] - ($aCtrl_Pos[3] / 2)
			
			If $aCtrl_Pos[0] <> $iNewLeft_Pos Or $aCtrl_Pos[1] <> $iNewTop_Pos Then
				GUICtrlSetPos($nCtrlID, $iNewLeft_Pos, $iNewTop_Pos)
			Else
				Sleep(5)
			EndIf
		WEnd
	EndIf
	
	Opt("MouseCoordMode", $iOld_Opt_MCM)
EndFunc
 
Верх