Что нового

[Элементы GUI] Как вычислить элемент контрола по его относительной геометрии?

V

VitAl2013

Гость
Есть контрол Class:Layout, который содержит Class:Sash, тот в свою очередь содержит TextArea. То что они друг в друга вложены ясно только геометрически, по габаритам и расположению. Существуюе также куча других Layout, Sash и TextArea, но у них совсем другая визульная вложенность. Как мне вычислить именно этих трёх товарищей, используя только их габариты, не используя какую либо вложенность на програмном уровне (подчинений одного элемента другому нет)?

Проблема в том что они каждый раз меняют свой "INSTANCE" и имеют только этот постоянный признак.

По идее тривиальная задача на логику, но сразуже столкнулся с проблемой. Я заранее не знаю сколько вообще там элементов определённого класса. Как узнаю буду проводить выборку. Потом выборку по выборке. Опять же пока ещё не знаю как, но варианты есть.

1. Список элементов я получил тут:http://autoit-script.ru/index.php?topic=1393.0
2. Отсял нужное тут: http://autoit-script.ru/index.php?topic=1396.0
3. Проанализировал и сопоставил геометрию.

Получилось так:
Код:
#Include <Array.au3>
#Include <WinAPIEx.au3>

WinActivate ("[REGEXPTITLE:(Active).*Pro/ENGINEER]")
$hForm = WinGetHandle("[REGEXPTITLE:(Active).*Pro/ENGINEER]")

$array = _WinAPI_EnumChildWindows($hForm)
If IsArray($array) Then
    _ArraySort($array, 0, 1, 0, 1)
;~     _ArrayDisplay($array, '_WinAPI_EnumChildWindows')
EndIf

$Layout_array = _ArrayCut("Layout", $array)
$Sash_array = _ArrayCut("Sash", $array)
$TextArea_array = _ArrayCut("TextArea", $array)
_ArrayDisplay($Layout_array, "Layout")
_ArrayDisplay($Sash_array, "Sash")
;~ _ArrayDisplay($TextArea_array, "TextArea")

Dim $Sash_array_new[1]
For $i=UBound($Sash_array)-1 to 0 step -1
;~ 	MsgBox (64, "$Sash_array["&$i&"]", "");$Sash_array[$i])
	$Sash_array_pos = ControlGetPos("","",$Sash_array[$i])
;~ 	MsgBox(64, "Show me", $Sash_array[$i]&" = "&$i&" element")
	_showme($Sash_array[$i])
	$u=0
	for $k = UBound($TextArea_array)-1 to 0 step -1
		_showme($TextArea_array[$k])
		$TextArea_pos = ControlGetPos("","",$TextArea_array[$k])
		if IsArray($TextArea_pos) then
;~ 			MsgBox(64, "View", $Sash_array_pos[0] &"~"& $TextArea_pos[0] &@CRLF& $Sash_array_pos[1] &"~"& $TextArea_pos[1] &@CRLF& $Sash_array_pos[2] &"~"& $TextArea_pos[2] &@CRLF& $Sash_array_pos[3] &"~"& $TextArea_pos[3])
			if $Sash_array_pos[0] <= $TextArea_pos[0] AND $Sash_array_pos[1] <= $TextArea_pos[1] AND $Sash_array_pos[2] >= $TextArea_pos[2] AND $Sash_array_pos[3] >= $TextArea_pos[3]   then
				_ArrayAdd($Sash_array_new, $Sash_array[$i])
				$u += 1
				$Sash_array_new[0] = $u
;~ 				MsgBox (64, "test", "TextArea handle = "&$TextArea_array[$k]&@CRLF&"Sash handle = "&$Sash_array[$i])
			EndIf
		EndIf
	next
next

_ArrayDisplay($Sash_array_new, "Sash_new")

Dim $Layout_array_new[1]
For $i=UBound($Layout_array)-1 to 0 step -1
;~ 	MsgBox (64, "$Layout_array["&$i&"]", "");$Layout_array[$i])
	$Layout_array_pos = ControlGetPos("","",$Layout_array[$i])
;~ 	MsgBox(64, "Show me", $Layout_array[$i]&" = "&$i&" element")
	_showme($Layout_array[$i])
	$j=0
	for $k = UBound($Sash_array)-1 to 0 step -1
		_showme($Sash_array[$k])
		$Sash_array_pos = ControlGetPos("","",$Sash_array[$k])
		if IsArray($Sash_array_pos) and IsArray($Layout_array_pos) then
;~ 			MsgBox(64, "View", $Layout_array_pos[0] &"~"& $Sash_array_pos[0] &@CRLF& $Layout_array_pos[1] &"~"& $Sash_array_pos[1] &@CRLF& $Layout_array_pos[2] &"~"& $Sash_array_pos[2] &@CRLF& $Layout_array_pos[3] &"~"& $Sash_array_pos[3])
			if $Layout_array_pos[0] <= $Sash_array_pos[0] AND $Layout_array_pos[1] <= $Sash_array_pos[1] AND $Layout_array_pos[2] >= $Sash_array_pos[2] AND $Layout_array_pos[3] >= $Sash_array_pos[3]   then
				_ArrayAdd($Layout_array_new, $Layout_array[$i])
				$j += 1
				$Layout_array_new[0] = $j
;~ 				MsgBox (64, "test", "TextArea handle = "&$Sash_array[$k]&@CRLF&"Sash handle = "&$Layout_array[$i])
			EndIf
		EndIf
	next
next

_ArrayDisplay($Layout_array_new, "Layout_new")

func _showme($hButton) ;блок для обводки находимых контролов
$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)
EndFunc

Func _ArrayCut($whatleave, ByRef $array)
	Dim $result[1]
    $u = 0
    For $i = UBound($array, 1) - 1 To 0 Step -1
        If $array[$i][1] = $whatleave Then
            _ArrayAdd($result, $array[$i][0])
            $u += 1
            $result[0] = $u
        EndIf
    Next
    Return $result
EndFunc   ;==>_ArrayCut


Ну чтож. Это не гуру вариант и подлежит глубокой оптимизации, а то и переделке. Работает ли он корректно сказать трудно. Включив блок обводки (взятый отсюда: http://autoit-script.ru/index.php?topic=1398.0) контролов увидел, что в моём случии геометрией зацепиться за контролы будет нельзя, так как существует какое-то множество попадающее под теже самые условия, но для когото окажется (надеюсь) полезным.
 
Верх