Старожил
Сообщения: 352
Благодарности: 193
|
Профиль
|
Отправить PM
| Цитировать
Ботяра,
Тут всё немного сложнее, чем кажется на первый взгляд.
Z-order направлен по вымышленной оси от экрана наружу (к пользователю) ( z-order).
Дочерние окна (в терминологии WinAPI, кнопки и прочие штуки -- окна определённого класса) при содании добавляются в конец z-order ( CreateWindowEx). Т.е. первый элемент -- самый верхний в порядке, второй ниже по иерархии, третий еще ниже и т.д.
Windows по умолчанию так и отрисовывает - сначала самый верхний первый, потом второй, ...
Для правильной отрисовки (с обрезкой перекрывающихся частей окон) требуется присвоить накладывающимся элементам стиль WS_CLIPSIBLINGS ( Child Window Update Region, последний абзац).
Альтернативный способ (со своими особенностями) - присвоить родительскому окну расширенный стиль WS_EX_COMPOSITED.
В скрипте-примере:
- получение массива дочерних окон в z-порядке через _WinAPI_GetTopWindow, _WinAPI_GetWindow(.., GW_HWNDNEXT)
- изменение z-order через _WinAPI_SetWindowPos
- быстрая отрисовка при массовом изменении окон (здесь для функции сброса) через _WinAPI_BeginDeferWindowPos, _WinAPI_DeferWindowPos, _WinAPI_EndDeferWindowPos
Пример
Код:
AutoItSetOption("GUIOnEventMode", 1)
#include <WinAPI.au3>
#include <WinAPISysWin.au3>
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
Main()
Func Main()
Global $hGUI, $hLabels[5], $idButtons[3][4], $hControls[256]
Global Enum $MTOP, $MHIGHER, $MLOWER, $MBOTTOM
$hGUI = GUICreate("Z-order playground", 600, 600)
GUISetOnEvent($GUI_EVENT_CLOSE, "EV_Exit")
GUICreateControls()
While 1
Sleep(100)
WEnd
EndFunc
Func GUICreateControls()
Local $GW, $GH, $tRECT, $top
$tRECT = _WinAPI_GetClientRect($hGUI)
$GW = DllStructGetData($tRECT, "Right")
$GH = DllStructGetData($tRECT, "Bottom")
$hLabels[0] = GUICtrlCreateLabel_My(0, 10, 10, 230, 55, 0xFFAAAA)
$hLabels[1] = GUICtrlCreateLabel_My(1, 35, 40, 190, 70, 0xAAFFAA)
$hLabels[2] = GUICtrlCreateLabel_My(2, 60, 45, 150, 90, 0xAAAAFF)
$hLabels[3] = GUICtrlCreateLabel_My(3, 10, 140, $GW/2-20, $GH-150, 0xFFFFFF)
$hLabels[4] = GUICtrlCreateLabel_My(4, 10+$GW/2, 140, $GW/2-20, $GH-150, 0xFFFFFF)
For $i = 0 To 2
$top = 10+$i*30
$idButtons[$i][0] = GUICtrlCreateButton("top", 250, $top, 60, 24)
GUICtrlSetOnEvent(-1, "EV_ChangeZOrder")
$idButtons[$i][1] = GUICtrlCreateButton("higher", 250+65*1, $top, 60, 24)
GUICtrlSetOnEvent(-1, "EV_ChangeZOrder")
$idButtons[$i][2] = GUICtrlCreateButton("lower", 250+65*2, $top, 60, 24)
GUICtrlSetOnEvent(-1, "EV_ChangeZOrder")
$idButtons[$i][3] = GUICtrlCreateButton("bottom", 250+65*3, $top, 60, 24)
GUICtrlSetOnEvent(-1, "EV_ChangeZOrder")
Next
GUICtrlCreateButton("RESET", $GW-70, 10, 60, 24)
GUICtrlSetOnEvent(-1, "GUIResetControls")
$hControls = GUIGetChildsList($hGUI)
UpdateWindowInfo()
UpdateWindowInfo2()
GUISetState(@SW_SHOW)
EndFunc
Func GUIResetControls()
Static Local $swp_flags = BitOr($SWP_NOMOVE, $SWP_NOSIZE)
Local $HDWP
$HDWP = _WinAPI_BeginDeferWindowPos(UBound($hControls))
$HDWP = _WinAPI_DeferWindowPos($HDWP, $hControls[0], $HWND_TOP, 0,0,0,0, $swp_flags)
For $i = 1 To UBound($hControls) - 1
$HDWP = _WinAPI_DeferWindowPos($HDWP, $hControls[$i], $hControls[$i-1], 0,0,0,0, $swp_flags)
Next
_WinAPI_EndDeferWindowPos($HDWP)
UpdateWindowInfo()
UpdateWindowInfo2()
EndFunc
Func GUICtrlCreateLabel_My($idx = "@", $x = 0, $y = 0, $w = 0, $h = 0, $bkcolor = $GUI_BKCOLOR_DEFAULT)
Local $id = GUICtrlCreateLabel("", $x, $y, $w, $h, $WS_CLIPSIBLINGS)
Local $hwnd = GUICtrlGetHandle($id)
Local $text = StringFormat("[%i] 0x%08X", $idx, $hwnd) & @crlf
_WinAPI_SetWindowText($hwnd, $text & $text & $text & $text & $text)
GUICtrlSetBkColor(-1, $bkcolor)
GUICtrlSetFont(-1, 9, 400, 0, "Consolas")
Return $hwnd
EndFunc
Func GUIGetChildsList($parent)
Local $count = 0, $array[256]
$array[0] = _WinAPI_GetTopWindow($hGUI)
While True
$count += 1
$array[$count] = _WinAPI_GetWindow($array[$count-1], $GW_HWNDNEXT)
If $array[$count] = 0 Then ExitLoop
WEnd
ReDim $array[$count]
Return $array
EndFunc
Func FindInArray($value, $array)
For $i = 0 To UBound($array) - 1
if $value = $array[$i] Then Return $i
Next
Return -1
EndFunc
Func UpdateWindowInfo()
Local $text, $sfmt = "%-12s = 0x%08X\n"
$text = StringFormat("[3] 0x%08X", $hLabels[3]) & @crlf & @crlf
$text &= StringFormat($sfmt, "hGUI", $hGUI)
$text &= StringFormat($sfmt, "parent c", _WinAPI_GetParent($hLabels[1]))
$text &= StringFormat($sfmt, "top", _WinAPI_GetTopWindow($hGUI))
$text &= StringFormat($sfmt, "first c", _WinAPI_GetWindow($hLabels[1], $GW_HWNDFIRST))
$text &= StringFormat($sfmt, "last", _WinAPI_GetWindow(_WinAPI_GetTopWindow($hGUI), $GW_HWNDLAST))
$text &= StringFormat($sfmt, "last c", _WinAPI_GetWindow($hLabels[1], $GW_HWNDLAST))
$text &= StringFormat($sfmt, "next c(1)", _WinAPI_GetWindow($hLabels[1], $GW_HWNDNEXT))
_WinAPI_SetWindowText($hLabels[3], $text)
EndFunc
Func UpdateWindowInfo2()
Local $ctl = GUIGetChildsList($hGUI)
Local $text = StringFormat("[4] 0x%08X\n\n%s\n", $hLabels[4],"Z-order:")
For $i = 0 To UBound($ctl) - 1
$text &= $ctl[$i] _
& (FindInArray($ctl[$i], $hLabels)>=0 ? (" :: " & FindInArray($ctl[$i], $hLabels)) : "" ) _
& ($i = 0 ? " :: first" : "" ) _
& @crlf
Next
_WinAPI_SetWindowText($hLabels[4], $text)
EndFunc
Func GUIControlChangeZOrder($hwnd, $action)
Static Local $swp_flags = BitOr($SWP_NOMOVE, $SWP_NOSIZE)
Switch $action
Case $MTOP
_WinAPI_SetWindowPos($hwnd, $HWND_TOP, 0,0,0,0, $swp_flags)
Case $MHIGHER
If $hwnd <> _WinAPI_GetTopWindow($hGUI) Then
_WinAPI_SetWindowPos(_WinAPI_GetWindow($hwnd, $GW_HWNDPREV), $hwnd, 0,0,0,0, $swp_flags)
EndIf
Case $MLOWER
If $hwnd <> _WinAPI_GetWindow($hwnd, $GW_HWNDLAST) Then
_WinAPI_SetWindowPos($hwnd, _WinAPI_GetWindow($hwnd, $GW_HWNDNEXT), 0,0,0,0, $swp_flags)
EndIf
Case $MBOTTOM
_WinAPI_SetWindowPos($hwnd, $HWND_BOTTOM, 0,0,0,0, $swp_flags)
EndSwitch
UpdateWindowInfo()
UpdateWindowInfo2()
EndFunc
Func EV_ChangeZOrder()
For $ctl = 0 To 2
For $action = 0 To 3
If $idButtons[$ctl][$action] = @GUI_CtrlId Then ExitLoop 2
Next
Next
GUIControlChangeZOrder($hLabels[$ctl], $action)
EndFunc
Func EV_Exit()
GUIDelete($hGUI)
Exit
EndFunc
|