Что нового

[Элементы GUI] Как обвести по периметру заданный контрол?

V

VitAl2013

Гость
AutoInfo обводит их както? Нельзяли повторить фокус?

Вижу
Код:
_WinAPI_Rectangle ( $hDC, $tRECT )
, но что такое $tRECT понять не могу. Описание
$tRECT - $tagRECT structure that contains the logical coordinates of the rectangle.
есть, но что оно значит? Какая такая структура с логическими координатами?
Там ещё написано что есть пример, а где?

Ладно, идём дальше, есть ф-ия _WinAPI_CreateRectEx которая нам делает $tRECT. И вроде никто неругается, но не обводит.

Также есть
Код:
$pos = ControlGetPos ()
_WinAPI_CreateRect($pos[0], $pos[1], $pos[2]+$pos[0], $pos[3]+$pos[1])
Но тоже не обводит. Либо обводит каким-то прозрачным цветом.

Yashied помогай! - они твоих рук творенья.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,486
Пример отлова и подсвечивания элементов под курсором

Код:
#include <GuiConstants.au3>
#include <EditConstants.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>
#include <Misc.au3>
;

Opt("GuiOnEventMode", 1)

HotKeySet("{ESC}", "_QuitApp")

Global $hSquare_GUI = -1
Global $hCtrl = -1
Global $Last_hControl = -1

Global $Frame_Color = 0xFF0000
Global $Frame_Width = 3

$Main_GUI = GUICreate("Highlight Controls Demo")
WinSetOnTop($Main_GUI, "", 1)

GUISetOnEvent($GUI_EVENT_CLOSE, "_QuitApp")
GUIRegisterMsg($WM_WINDOWPOSCHANGED, "WM_WINDOWPOSCHANGED")

GUICtrlCreateButton("Button", 20, 20)
GUICtrlCreateCheckbox("CheckBox", 20, 60)

GUICtrlCreateLabel("Info: ", 20, 150)
GUICtrlSetFont(-1, 9, 800)

$Info_Edit = GUICtrlCreateEdit("", 80, 150, 300, 220, $GUI_SS_DEFAULT_EDIT + $ES_READONLY)

GUISetState()

While 1
	Sleep(10) ;So the CPU will not increes "badly" while we play with the mouse cursor :)
	_IdleWait()
	
	If _IsPressed(1) Then
		_GUIDeleteSquare($hSquare_GUI)
		
		While _IsPressed(1)
			Sleep(10)
			_Check_Highlight_Controls_Proc()
		WEnd
		
		$Last_hControl = -1
	EndIf
	
	_Check_Highlight_Controls_Proc()
WEnd

Func _Check_Highlight_Controls_Proc()
	Local $hCtrl = _ControlGetHovered()

	If $hCtrl <> 0 And $Last_hControl <> $hCtrl And $hSquare_GUI <> $hCtrl Then
		$Last_hControl = $hCtrl
		Local $aCtrlPos = WinGetPos($hCtrl)

		GUICtrlSetData($Info_Edit, _
				"X = " & $aCtrlPos[0] & @CRLF & _
				"Y = " & $aCtrlPos[1] & @CRLF & _
				"W = " & $aCtrlPos[2] & @CRLF & _
				"H = " & $aCtrlPos[3] & @CRLF & @CRLF & _
				"Control/Win Class Name: " & _WinGetClassNameNN($hCtrl) & @CRLF & _
				"Control/Win Handle: " & $hCtrl & @CRLF & _
				"Control ID: " & _HwndToID($hCtrl) & @CRLF & @CRLF & _
				"Control Data:" & @CRLF & ControlGetText($hCtrl, "", ""))

		_GUIDeleteSquare($hSquare_GUI)
		$hSquare_GUI = _GUICreateSquare($aCtrlPos[0], $aCtrlPos[1], $aCtrlPos[2], $aCtrlPos[3])
	EndIf
EndFunc

Func _GUICreateSquare($i_X = -1, $i_Y = -1, $i_W = -1, $i_H = -1)
	Local $hSquare_GUI = GUICreate("", $i_W, $i_H, $i_X, $i_Y, $WS_POPUP, $WS_EX_TOOLWINDOW + $WS_EX_TOPMOST)
	GUISetBkColor($Frame_Color)
	
	_GUISetHole($hSquare_GUI, $Frame_Width, $Frame_Width, $i_W - ($Frame_Width * 2), $i_H - ($Frame_Width * 2))
	
	GUISetState(@SW_SHOWNOACTIVATE, $hSquare_GUI)
	
	Return $hSquare_GUI
EndFunc

Func _GUIDeleteSquare($hSquare_GUI)
	If IsHWnd($hSquare_GUI) And $hSquare_GUI <> $Main_GUI Then GUIDelete($hSquare_GUI)
EndFunc

Func _ControlGetHovered()
	Local $aRet = DllCall("user32.dll", "int", "WindowFromPoint", "long", MouseGetPos(0), "long", MouseGetPos(1))
	
	If @error Or Not IsArray($aRet) Then Return SetError(1, 0, 0)
	Return HWnd($aRet[0])
EndFunc

Func _HwndToID($hWnd)
	If Not IsHWnd($hWnd) Then Return SetError(1, 0, "")
	
	Local $aRet = DllCall("user32.dll", "int", "GetDlgCtrlID", "hwnd", $hWnd)
	If Not IsArray($aRet) Then Return SetError(2, 0, "")
	
	Return $aRet[0]
EndFunc

Func _WinGetClassName($hWnd)
	$aClassName = DllCall("user32.dll", "int", "GetClassName", "hWnd", $hWnd, "str", "", "int", 64)
	If Not @error And $aClassName[0] <> 0 Then Return $aClassName[2]
	Return ""
EndFunc

Func _WinGetClassNameNN($hCtrlWnd)
	$hParent = _WinAPI_GetAncestor($hCtrlWnd, $GA_ROOTOWNER)
	$hCtrlWnd = ControlGetHandle($hParent, "", $hCtrlWnd)
	$sClassList = StringSplit(StringStripCR(_WinGetNumeratedClassList($hParent)), @LF)
	
	For $i = $sClassList[0] To 1 Step -1
		If $sClassList[$i] = "" Then ContinueLoop
		
		If ControlGetHandle($hParent, "", $sClassList[$i]) = $hCtrlWnd Then Return $sClassList[$i]
	Next
	
	Return _WinGetClassName($hCtrlWnd)
EndFunc

Func _WinGetNumeratedClassList($sTitle, $sText = "")
	Local $sClassList = WinGetClassList($sTitle, $sText)
	Local $aClassList = StringSplit($sClassList, @CRLF)
	Local $sRetClassList = "", $sHold_List = "|"
	Local $aiInHold, $iInHold
	
	For $i = 1 To UBound($aClassList) - 1
		If $aClassList[$i] = "" Then ContinueLoop
		
		If StringRegExp($sHold_List, "\|" & $aClassList[$i] & "~(\d+)\|") Then
			$aiInHold = StringRegExp($sHold_List, ".*\|" & $aClassList[$i] & "~(\d+)\|.*", 1)
			$iInHold = Number($aiInHold[UBound($aiInHold) - 1])
			
			If $iInHold = 0 Then $iInHold += 1
			
			$aClassList[$i] &= "~" & $iInHold + 1
			$sHold_List &= $aClassList[$i] & "|"
			
			$sRetClassList &= $aClassList[$i] & @CRLF
		Else
			$aClassList[$i] &= "~1"
			$sHold_List &= $aClassList[$i] & "|"
			$sRetClassList &= $aClassList[$i] & @CRLF
		EndIf
	Next
	
	Return StringReplace(StringStripWS($sRetClassList, 3), "~", "")
EndFunc

Func _GUISetHole($hWin, $i_X, $i_Y, $i_SizeW, $i_SizeH)
	Local $aWinPos, $Outer_Rgn, $Inner_Rgn, $Wh, $Combined_Rgn
	Local Const $RGN_DIFF = 4
	$aWinPos = WinGetPos($hWin)

	$Outer_Rgn = DllCall("gdi32.dll", "long", "CreateRectRgn", "long", 0, "long", 0, "long", $aWinPos[2], "long", $aWinPos[3])
	$Inner_Rgn = DllCall("gdi32.dll", "long", "CreateRectRgn", "long", $i_Y, "long", $i_Y, "long", $i_Y + $i_SizeW, _
			"long", $i_Y + $i_SizeH)
	$Combined_Rgn = DllCall("gdi32.dll", "long", "CreateRectRgn", "long", 0, "long", 0, "long", 0, "long", 0)
	DllCall("gdi32.dll", "long", "CombineRgn", "long", $Combined_Rgn[0], "long", $Outer_Rgn[0], "long", $Inner_Rgn[0], _
			"int", $RGN_DIFF)
	DllCall("user32.dll", "long", "SetWindowRgn", "hwnd", $hWin, "long", $Combined_Rgn[0], "int", 1)
EndFunc

Func _IdleWait($IdleSec = 0)
	Local $iSave, $stLastInput = DllStructCreate("uint;dword")
	DllStructSetData($stLastInput, 1, DllStructGetSize($stLastInput))
	DllCall("user32.dll", "int", "GetLastInputInfo", "ptr", DllStructGetPtr($stLastInput))
	
	Do
		$iSave = DllStructGetData($stLastInput, 2)
		Sleep(20)
		DllCall("user32.dll", "int", "GetLastInputInfo", "ptr", DllStructGetPtr($stLastInput))
	Until (DllStructGetData($stLastInput, 2) - $iSave) > $IdleSec
	
	Return DllStructGetData($stLastInput, 2) - $iSave
EndFunc

Func WM_WINDOWPOSCHANGED($hWndGUI, $MsgID, $WParam, $LParam)
	If $hWndGUI <> $Main_GUI Then Return $GUI_RUNDEFMSG
	_GUIDeleteSquare($hSquare_GUI)
	_Check_Highlight_Controls_Proc()
	$Last_hControl = -1
EndFunc

Func _QuitApp()
	Exit
EndFunc
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
VitAl2013, а что ты ожидал от этих функций? В WinAPI, как правило ничего не делается вызовом всего лишь одной функции. Вот минимальный код, который обводит контрол (в данном случае кнопку):

Код:
#Include <WinAPIEx.au3>

$hForm = GUICreate('MyGUI', 400, 400)
$Button = GUICtrlCreateButton('OK', 100, 100, 70, 23)
GUISetState()

; Теперь самое интересное, обводим кнопку красной рамкой
$hButton = GUICtrlGetHandle($Button)
$tRECT = _WinAPI_CreateRectEx(0, 0, _WinAPI_GetWindowWidth($hButton), _WinAPI_GetWindowHeight($hButton))
$hDC = _WinAPI_GetDC($hButton)
$hBruish = _WinAPI_SelectObject($hDC, _WinAPI_GetStockObject($NULL_BRUSH))
$hPen = _WinAPI_SelectObject($hDC, _WinAPI_GetStockObject($DC_PEN))
_WinAPI_SetDCPenColor($hDC, 0xFF0000)
_WinAPI_Rectangle($hDC, $tRECT)
_WinAPI_SelectObject($hDC, $hPen)
_WinAPI_SelectObject($hDC, $hBruish)
_WinAPI_ReleaseDC($hButton, $hDC)

Do
Until GUIGetMsg() = -3
 

w3d

Новичок
Сообщения
84
Репутация
3
Поищи мои темы по форуму - там было решение.
Я примерно подобное спрашивал :smile:
 
Верх