Что нового

Нарисовать прямоугольник выделения

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Как нарисовать прямоугольник выделения, такой (или похожий), какой рисует проводник при выделении мышкой, но в любом окне (или в своем для начала)?
Было бы здорово посмотреть на решения :scratch:
 

rusreg79

Продвинутый
Сообщения
159
Репутация
57
Код:
#include <Misc.au3>
#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>

;~ Opt("MouseCoordMode", 2)

$coord = _AreaCoordinates() ; Opt Coord Mode: 0-2 , $hWnd
If Not @error Then
	ConsoleWrite('left:' & @TAB & $coord[0] & @CR & 'top:' & @TAB & $coord[1] & @CR & 'right:' & @TAB & $coord[2] & @CR & 'bottom:' & @TAB & $coord[3]	&@cr)
Else
	ConsoleWrite('! Error ! '&$coord &@cr)
EndIf


Func _AreaCoordinates($__opt = -1, $hWnd = '')
	Local $_block, $__aGUI[4], $__pm[2], $__pos1, $__pos2
	Local $opt_MouseCoordMode = Opt("MouseCoordMode")
	If $__opt = -1 Then $__opt = $opt_MouseCoordMode ;координаты по умолчанию от настройки в Opt("MouseCoordMode")
	If  Not IsNumber($__opt) Or $__opt > 2 Then Return SetError(1,1,'опция координат должна быть от 0 до 2')
	For $i = 0 To 3
		$__aGUI[$i] = GUICreate('', 0, 0, 0, 0, $WS_POPUP, BitOR($WS_EX_TOOLWINDOW, $WS_EX_TOPMOST))
		GUISetBkColor(0xFF0000, $__aGUI[$i])
	Next
	Opt("MouseCoordMode", 1)
	While 1
		If _IsPressed('01') Then ;лкм
			$__pos1 = MouseGetPos()
			If Not IsHWnd($hWnd) Then
				Sleep(50)
				$hWnd = WinGetHandle("[active]")
				If @error Then
					Opt("MouseCoordMode", $opt_MouseCoordMode)
					Return SetError(1,1,'Не удалось определить дескриптор окна')
				EndIf
			EndIf

			While _IsPressed('01') ;лкм
				$__pos2 = MouseGetPos()
				If $__pos2[0] > $__pos1[0] And $__pos2[1] > $__pos1[1] Then
					If Not $_block Then
						For $i = 0 To 3
							GUISetState(@SW_SHOW, $__aGUI[$i])
						Next
						$_block = 1;блок
					EndIf
					If $__pos2[0] <> $__pm[0] Or $__pos2[1] <> $__pm[1] Then
						WinMove($__aGUI[0], '', $__pos1[0], $__pos1[1], 2, $__pos2[1] - $__pos1[1]); 			<
						WinMove($__aGUI[1], '', $__pos1[0], $__pos1[1], $__pos2[0] - $__pos1[0] + 2, 2);		^
						WinMove($__aGUI[2], '', $__pos2[0], $__pos1[1], 2, $__pos2[1] - $__pos1[1] + 2);		>
						WinMove($__aGUI[3], '', $__pos1[0], $__pos2[1], $__pos2[0] - $__pos1[0], 2); 			v
						$__pm[0] = $__pos2[0]
						$__pm[1] = $__pos2[1]
					EndIf
				Else
					If $_block Then
						For $i = 0 To 3
							GUISetState(@SW_HIDE, $__aGUI[$i])
						Next
						$_block = 0;блок
					EndIf
				EndIf
				Sleep(10)
			WEnd
			For $i = 0 To 3
				GUIDelete($__aGUI[$i])
			Next
			Opt("MouseCoordMode", $opt_MouseCoordMode);вернуть изначальную опцию
			If $_block Then
				If $__opt = 0 Then;вычисления оконных координат
					Local $WinPos = WinGetPos($hWnd)
					If @error Then Return SetError(1,1,'не удалось определить позицию окна')
					$__aGUI[0] = $__pos1[0] - $WinPos[0]
					$__aGUI[1] = $__pos1[1] - $WinPos[1]
					$__aGUI[2] = $__pos2[0] - $WinPos[0]
					$__aGUI[3] = $__pos2[1] - $WinPos[1]
					If $__aGUI[0] < 0 Or $__aGUI[1] < 0 Or $__aGUI[2] < 0 Or $__aGUI[3] < 0 Then Return SetError(1,1,'рамка за пределами окна')
					If $__aGUI[0] > $WinPos[2] Or $__aGUI[2] > $WinPos[2] Or $__aGUI[1] > $WinPos[3] Or $__aGUI[3] > $WinPos[3] Then Return SetError(1,1,'рамка за пределами окна')
				ElseIf $__opt = 2 Then;вычисления клиентских координат
					Local $ClientSizeWin = WinGetClientSize($hWnd)
					If @error Then Return SetError(1,1,'не удалось определить размер клиентской области')
					Local $WinPos = WinGetPos($hWnd)
					If @error Then Return SetError(1,1,'не удалось определить позицию окна')
					$__aGUI[0] = $__pos1[0] - $WinPos[0] - ($WinPos[2] - $ClientSizeWin[0]) / 2
					$__aGUI[1] = $__pos1[1] - $WinPos[1] - (($WinPos[3] - $ClientSizeWin[1]) - (($WinPos[2] - $ClientSizeWin[0]) / 2))
					$__aGUI[2] = $__pos2[0] - $WinPos[0] - ($WinPos[2] - $ClientSizeWin[0]) / 2
					$__aGUI[3] = $__pos2[1] - $WinPos[1] - (($WinPos[3] - $ClientSizeWin[1]) - (($WinPos[2] - $ClientSizeWin[0]) / 2))
					If $__aGUI[0] < 0 Or $__aGUI[1] < 0 Or $__aGUI[2] < 0 Or $__aGUI[3] < 0 Then Return SetError(1,1,'рамка за пределами окна')
					If $__aGUI[0] > $ClientSizeWin[0] Or $__aGUI[2] > $ClientSizeWin[0] Or $__aGUI[1] > $ClientSizeWin[1] Or $__aGUI[3] > $ClientSizeWin[1] Then Return SetError(1,1,'рамка за пределами окна')
				Else;абсолютные координаты
					$__aGUI[0] = $__pos1[0]
					$__aGUI[1] = $__pos1[1]
					$__aGUI[2] = $__pos2[0]
					$__aGUI[3] = $__pos2[1]
				EndIf
				Return $__aGUI
			Else
				Return SetError(1,1,'не была выделена область')
			EndIf
		EndIf
		Sleep(10)
	WEnd
EndFunc   ;==>_AreaCoordinates
 
Автор
inververs

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
rusreg79
Интересный пример! Как я понял рисуется и правильно склеивается 4 разных окна? У меня стразу возник вопрос, а почему бы не нарисовать одно окно с красными границами...?
И в вашем пример можно рисовать только слева на право, сверху вниз. А хочется во всех направлениях.
За идею спасибо все равно :smile:
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,487
Код:
_DrawSquare(480, 150, 120, 100, 0xFF0000, 3)
_DrawSquare(300, 150, 120, 100, 0x0000FF, 3)

Func _DrawSquare($iLeft, $iTop, $iWidth, $iHeight, $sColor, $iLineWidth=2, $hWnd=0)
	$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", $iLineWidth, "int", $sColor)
	
	DllCall("GDI32.dll", "int", "SelectObject", "int", $hDC[0], "int", $aPen[0])
	
	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("GDI32.dll", "int", "LineTo", "hwnd", $hDC[0], "int", $iLeft+$iWidth, "int", $iTop+$iHeight)
	DllCall("GDI32.dll", "int", "LineTo", "hwnd", $hDC[0], "int", $iLeft, "int", $iTop+$iHeight)
	DllCall("GDI32.dll", "int", "LineTo", "hwnd", $hDC[0], "int", $iLeft, "int", $iTop)
	
	DllCall("user32.dll", "int", "ReleaseDC", "hwnd", $hWnd, "int", $hDC[0])
	DllCall("GDI32.dll", "int", "DeleteObject", "int", $aPen[0])
EndFunc
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,487
Или вот такой пример, взято с FreeShooter:

Код:
#include <WinAPI.au3>
#include <Misc.au3>

_GUISelection_GetRegion()

Func _GUISelection_GetRegion()
	Local $aLast_MPos[2] = [-1, -1], $aMouse_Pos, $hMask, $hMaster_Mask, $iTemp
	
	$hCross_GUI = GUICreate("", @DesktopWidth, @DesktopHeight - 20, 0, 0, -2147483648, 8)
	WinSetTrans($hCross_GUI, "", 8)
	GUISetState(@SW_SHOW, $hCross_GUI)
	GUISetCursor(3, 1, $hCross_GUI)
	
	Global $hRectangle_GUI = GUICreate("", @DesktopWidth, @DesktopHeight, 0, 0, -2147483648, 128 + 8)
	GUISetBkColor(0x000000)
	
	While Not _IsPressed("01")
		Sleep(10)
		
		$aMPos = MouseGetPos()
		
		If ($aMPos[0] <> $aLast_MPos[0]) Or ($aMPos[1] <> $aLast_MPos[1]) Then
			ToolTip('Нажмите "Левую кнопку мыши" для начала выделения')
			$aLast_MPos = $aMPos
		EndIf
		
		If _IsPressed("02") Or _IsPressed("1B") Then
			GUIDelete($hRectangle_GUI)
			GUIDelete($hCross_GUI)
			ExitLoop
		EndIf
	WEnd
	
	$aMouse_Pos = MouseGetPos()
	
	$pos_x_1 = $aMouse_Pos[0]
	$pos_y_1 = $aMouse_Pos[1]
	
	$sData = "Горизонталь [X]: Начало = %i, Длина = %i\nВертикаль [Y]:    Начало = %i, Высота = %i\n\nОтпустите клавишу мыши для завершения"
	
	ToolTip("")
	
	While _IsPressed("01")
		$aMouse_Pos = MouseGetPos()

		If ($aMouse_Pos[0] <> $aLast_MPos[0]) Or ($aMouse_Pos[1] <> $aLast_MPos[1]) Then
			$nWidth = $aMouse_Pos[0] - $aMPos[0]
			$nHeight = $aMouse_Pos[1] - $aMPos[1]
			
			If $aMouse_Pos[0] < $aMPos[0] Then $nWidth = $aMPos[0] - $aMouse_Pos[0]
			If $aMouse_Pos[1] < $aMPos[1] Then $nHeight = $aMPos[1] - $aMouse_Pos[1]
			
			ToolTip(StringFormat($sData, $aMPos[0], $nWidth, $aMPos[1], $nHeight))
			
			$aLast_MPos = $aMouse_Pos
		EndIf
		
		$hMaster_Mask = _WinAPI_CreateRectRgn(0, 0, 0, 0)
		$hMask = _WinAPI_CreateRectRgn($pos_x_1, $aMouse_Pos[1], $aMouse_Pos[0], $aMouse_Pos[1] + 1)
		_WinAPI_CombineRgn($hMaster_Mask, $hMask, $hMaster_Mask, 2)
		$hMask = _WinAPI_CreateRectRgn($pos_x_1, $pos_y_1, $pos_x_1 + 1, $aMouse_Pos[1])
		_WinAPI_CombineRgn($hMaster_Mask, $hMask, $hMaster_Mask, 2)
		$hMask = _WinAPI_CreateRectRgn($pos_x_1 + 1, $pos_y_1 + 1, $aMouse_Pos[0], $pos_y_1)
		_WinAPI_CombineRgn($hMaster_Mask, $hMask, $hMaster_Mask, 2)
		$hMask = _WinAPI_CreateRectRgn($aMouse_Pos[0], $pos_y_1, $aMouse_Pos[0] + 1, $aMouse_Pos[1])
		_WinAPI_CombineRgn($hMaster_Mask, $hMask, $hMaster_Mask, 2)
		_WinAPI_SetWindowRgn($hRectangle_GUI, $hMaster_Mask)
		If WinGetState($hRectangle_GUI) < 15 Then GUISetState()
		
		Sleep(10)
	WEnd
	
	$pos_x_2 = $aMouse_Pos[0]
	$pos_y_2 = $aMouse_Pos[1]
	
	If $pos_x_2 < $pos_x_1 Then
		$iTemp = $pos_x_1
		$pos_x_1 = $pos_x_2
		$pos_x_2 = $iTemp
	EndIf
	
	If $pos_y_2 < $pos_y_1 Then
		$iTemp = $pos_y_1
		$pos_y_1 = $pos_y_2
		$pos_y_2 = $iTemp
	EndIf
	
	GUIDelete($hRectangle_GUI)
	GUIDelete($hCross_GUI)
EndFunc
 

GreyWerewolf

То тут, то там...
Сообщения
23
Репутация
0
CreatoR сказал(а):
Или вот такой пример, взято с FreeShooter:

Код нуждается в доработке. В цикле While не хватало удаления созданных Win_api - в итоге если держать около 15 секунд выделение - будем иметь офигенный баг. Подправил:

Код:
Global $WidthX=(WinGetPos('Program Manager'))[2];разрешение экрана в сумме

Func _GUISelection_GetRegion()
    Local $aLast_MPos[2] = [-1, -1], $aMouse_Pos, $hMask, $hMaster_Mask, $iTemp
    Local $coords[4]
    $hCross_GUI = GUICreate("", $WidthX, @DesktopHeight - 20, 0, 0, 2147483648, 8,$hParenttt)
    WinSetTrans($hCross_GUI, "", 8)
    GUISetState(@SW_SHOW, $hCross_GUI)
    GUISetCursor(3, 1, $hCross_GUI)

    Global $hRectangle_GUI = GUICreate("", $WidthX, @DesktopHeight, 0, 0, -2147483648, 128 + 8,$hParenttt)
    GUISetBkColor(0x000000)

    While Not _IsPressed("01")
        Sleep(10)

        $aMPos = MouseGetPos()

        If ($aMPos[0] <> $aLast_MPos[0]) Or ($aMPos[1] <> $aLast_MPos[1]) Then
            ToolTip('Нажмите "Левую кнопку мыши" для начала выделения')
            $aLast_MPos = $aMPos
        EndIf

        If _IsPressed("02") Or _IsPressed("1B") Then
            GUIDelete($hRectangle_GUI)
            GUIDelete($hCross_GUI)
            ExitLoop
        EndIf
    WEnd

    $aMouse_Pos = MouseGetPos()

    $pos_x_1 = $aMouse_Pos[0]
    $pos_y_1 = $aMouse_Pos[1]
    $coords[0]=$pos_x_1
	$coords[1]=$pos_y_1
    $sData = "Начальные координаты X = %i, Y = %i\nКонечные координаты X = %i, Y = %i\n\nОтпустите клавишу мыши для завершения"

    ToolTip("")
    While _IsPressed("01")
		$aMouse_Pos = MouseGetPos()
        If ($aMouse_Pos[0] <> $aLast_MPos[0]) Or ($aMouse_Pos[1] <> $aLast_MPos[1]) Then

            ToolTip(StringFormat($sData, $aMPos[0], $aMPos[1], MouseGetPos(0), MouseGetPos(1)))

            $aLast_MPos = $aMouse_Pos
        EndIf

        $hMaster_Mask = _WinAPI_CreateRectRgn(0, 0, 0, 0)
        $hMask = _WinAPI_CreateRectRgn($pos_x_1, $aMouse_Pos[1], $aMouse_Pos[0], $aMouse_Pos[1] + 1)
        _WinAPI_CombineRgn($hMaster_Mask, $hMask, $hMaster_Mask, 2)
		_WinAPI_DeleteObject($hMask)
        $hMask = _WinAPI_CreateRectRgn($pos_x_1, $pos_y_1, $pos_x_1 + 1, $aMouse_Pos[1])
        _WinAPI_CombineRgn($hMaster_Mask, $hMask, $hMaster_Mask, 2)
		_WinAPI_DeleteObject($hMask)
        $hMask = _WinAPI_CreateRectRgn($pos_x_1 + 1, $pos_y_1 + 1, $aMouse_Pos[0], $pos_y_1)
        _WinAPI_CombineRgn($hMaster_Mask, $hMask, $hMaster_Mask, 2)
		_WinAPI_DeleteObject($hMask)
        $hMask = _WinAPI_CreateRectRgn($aMouse_Pos[0], $pos_y_1, $aMouse_Pos[0] + 1, $aMouse_Pos[1])
        $reg=_WinAPI_CombineRgn($hMaster_Mask, $hMask, $hMaster_Mask, 2)
        _WinAPI_SetWindowRgn($hRectangle_GUI, $hMaster_Mask)
		_WinAPI_DeleteObject($hMaster_Mask)
        _WinAPI_DeleteObject($hMask)
		_WinAPI_DeleteObject($reg)
        If WinGetState($hRectangle_GUI) < 15 Then GUISetState()
        Sleep(10)
    WEnd

    $pos_x_2 = $aMouse_Pos[0]
    $pos_y_2 = $aMouse_Pos[1]

    If $pos_x_2 < $pos_x_1 Then
        $iTemp = $pos_x_1
        $pos_x_1 = $pos_x_2
        $pos_x_2 = $iTemp
    EndIf

    If $pos_y_2 < $pos_y_1 Then
        $iTemp = $pos_y_1
        $pos_y_1 = $pos_y_2
        $pos_y_2 = $iTemp
    EndIf

    GUIDelete($hRectangle_GUI)
    GUIDelete($hCross_GUI)
EndFunc
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Вы на дату последнего ответа посмотрите.
 

GreyWerewolf

То тут, то там...
Сообщения
23
Репутация
0
Yashied сказал(а):
Вы на дату последнего ответа посмотрите.
OffTopic:
Видел, ну мне же код понадобился, мало ли ещё таких будет. ;)
Это я еще до MouseOnEvent не добрался, там багов столько, что проще с нуля писать :(, но я в хуках пока плохо разбираюсь, да и не на столько это нужно в данный момент.
 
Верх