Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  

Показать сообщение отдельно

Старожил


Сообщения: 327
Благодарности: 178

Профиль | Отправить 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
Это сообщение посчитали полезным следующие участники:

Отправлено: 21:48, 21-02-2023 | #2