Jump to content

Recommended Posts

Posted (edited)

Hello everybody :)
I got an issue with the following script (tested on Windows 11)

#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WinAPISysWin.au3>
#include <WindowsConstants.au3>

Opt("MustDeclareVars", 1)
Global $g_hGui

Example()

;==============================================
Func Example()

    Local $idButton, $idLabel, $idCheckbox, $idEdit
    $g_hGui = GUICreate("Drag controls (GUI_ONTOP issue)", 400, 150)

    $idButton = GUICtrlCreateButton("", 10, 30, 80, 80, $WS_CLIPSIBLINGS)
    GUICtrlSetData(-1, "Button " & $idButton)

    $idLabel = GUICtrlCreateLabel("", 100, 40, 80, 60, BitOr($SS_CENTERIMAGE, $SS_CENTER, $WS_CLIPSIBLINGS))
    GUICtrlSetData(-1, "Label " & $idLabel)
    GUICtrlSetBkColor(-1, 0x00FF00) ; green

    $idCheckbox = GUICtrlCreateCheckbox("", 190, 50, 80, 40, $WS_CLIPSIBLINGS)
    GUICtrlSetData(-1, "Checkbox " & $idCheckbox)
    GUICtrlSetBkColor(-1, 0xFFFF00) ; yellow

    $idEdit = GUICtrlCreateEdit("", 280 ,40, 100, 70, BitOr($GUI_SS_DEFAULT_EDIT, $WS_CLIPSIBLINGS))
    GUICtrlSetData(-1, "Edit " & $idEdit)

    GUISetState()

    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                Exit
            Case $GUI_EVENT_PRIMARYDOWN
                _ControlMove()
        EndSwitch
    WEnd
EndFunc   ;==>Example

;==============================================
Func _ControlMove()

    Local $aInfo, $idControl, $hControl, $aPos, $iSubtractX, $iSubtractY, $iLoopCount
    $aInfo = GUIGetCursorInfo($g_hGUI)

    If Not @error And $aInfo[4] Then
        $idControl = $aInfo[4]
        $hControl = GUICtrlGetHandle($idControl)
        $aPos = ControlGetPos($g_hGui, "", $idControl)
        $iSubtractX = $aInfo[0] - $aPos[0]
        $iSubtractY = $aInfo[1] - $aPos[1]

        While $aInfo[2] ; LMB pressed
            $iLoopCount += 1
            If $iLoopCount = 1 Then
                ; GUICtrlSetState($idControl, $GUI_ONTOP) ; changes wrongly the z-order of a label control, why ?
                ; _WinAPI_SetWindowPos($hControl, $HWND_TOP, 0, 0, 0, 0,  BitOr($SWP_NOMOVE, $SWP_NOSIZE, $SWP_NOACTIVATE))
            EndIf
            $aInfo = GUIGetCursorInfo($g_hGui)
            GUICtrlSetPos($idControl, $aInfo[0] - $iSubtractX, $aInfo[1] - $iSubtractY)
            Sleep(10)
        WEnd
    EndIf
EndFunc   ;==>_ControlMove

1) When you run the script "as-is" (without modifying any line) :
* Each control dragged to the right covers the controls found at its right
* Each control dragged to the left is covered by the controls found at its left.

2) Now let's uncomment the $GUI_ONTOP line :

GUICtrlSetState($idControl, $GUI_ONTOP) ; seems to change wrongly the z-order of a label control, why ?

; _WinAPI_SetWindowPos($hControl, $HWND_TOP, 0, 0, 0, 0,  BitOr($SWP_NOMOVE, $SWP_NOSIZE, $SWP_NOACTIVATE))

* Button, Checkbox, Edit : they all behave correctly, covering all controls when dragged.
* Label : on the contrary, the label control is covered by any control when dragged.

So the question is : why the label control doesn't follow the other controls behavior ?

3) Final test : please comment out the $GUI_ONTOP line and uncomment the _WinAPI_SetWindowPos line, like this :

; GUICtrlSetState($idControl, $GUI_ONTOP) ; changes wrongly the z-order of a label control, why ?

_WinAPI_SetWindowPos($hControl, $HWND_TOP, 0, 0, 0, 0,  BitOr($SWP_NOMOVE, $SWP_NOSIZE, $SWP_NOACTIVATE))

Now the label control behaves differently and covers all other controls when dragged.
So is there a bug with $GUI_ONTOP when applied to label controls ?

For the record, a track ticket #2287 concerning this question was closed by Jon 12 years ago.
But isn't the test in 2) enough to show that the label behaves differently from the other controls when $GUI_ONTOP is applied to it ?

Edit 1: no more sure of anything as the $WS_CLIPSIBLINGS style seems to interfere with all this !

Edit 2 : even if you remove the 4 $WS_CLIPSIBLINGS style at control creation, you'll notice that test 2) shows a different behavior when it comes to the label control, compared to the 3 other controls, but test 3) shows the same behavior for all controls.

That's why I prefer to use _WinAPI_SetWindowPos which behaves in the same way for the 4 controls, rather than $GUI_ONTOP which treats labels control differently, especially in this kind of script where we want the dragged control to appear above (in front of) any other control during the drag process.

Edited by pixelsearch
added Edit1 then Edit2

"I think you are searching a bug where there is no bug... don't listen to bad advice."

Posted

Yeah it looks like $GUI_ONTOP sends labels to the wrong end of the z-order.

Just thought I'd add that the example in the track ticket #2287 seems to kind-of work...

"Set ONTOP Label 2" is printed when Label 2 comes to the front... but it's not clipping siblings.  When you click in the area where the 2 controls overlap, its the control underneath that receives the click.  So I take that to mean the "top" control here is being painted into areas where it shouldn't be.

#include <GUIConstants.au3>

GUICreate("Test", 300, 200)
GUISetState()

$idLab1 = GUICtrlCreateLabel("Label 1", 30, 30, 200, 100)
GUICtrlSetBkColor(-1, 0xFF0000)
$idLab2 = GUICtrlCreateLabel("Label 2", 50, 50, 200, 100)
GUICtrlSetBkColor(-1, 0x00FF00)

Local $iMsg
While 1
    $iMsg = GUIGetMsg()
    Switch $iMsg
        Case $idLab1, $idLab2
            ConsoleWrite("Set ONTOP " & GUICtrlRead($iMsg) & @CRLF)
            GUICtrlSetState($iMsg, $GUI_ONTOP)
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd
Posted

Thanks guys for your comments :)

I just rested with older versions of AutoIt, hoping secretly to detect if $GUI_ONTOP behaved correctly for the 4 controls in my initial script from post 1. Bingo !

Reminder of test 2) : $GUI_ONTOP line uncommented, _WinAPI_SetWindowPos line commented out, like this :

GUICtrlSetState($idControl, $GUI_ONTOP) ; changes wrongly the z-order of a label control, why ?

; _WinAPI_SetWindowPos($hControl, $HWND_TOP, 0, 0, 0, 0,  BitOr($SWP_NOMOVE, $SWP_NOSIZE, $SWP_NOACTIVATE))

* AutoIt 3.3.12.0 (2014)
The script works fine for ALL 4 controls, which are correctly on top when dragged (label control too, yes !)

* AutoIt 3.3.14.0 (2015)
The script doesn't work for all controls : the label control doesn't behave as the 3 other controls.

Which means that some code has changed between these 2 versions and the timeline shows that it is connected to Track ticket #2287 owned and closed by Jon, who wrote in the AutoIt history/changelog :

Fixed #2287: GUICtrlSetState() $GUI_ONTOP not set.

Unfortunately, what worked fine (at least for me) with the previous version from 2014 doesn't work anymore with the version from 2015 and further. For the record, I don't understand trancexx answer in the track ticket, quote :

Changed 13 years ago by trancexx
Resolution set to No Bug
Status changed from new to closed

$GUI_ONTOP does what it's docummented that it does. There is no bug here.
Documentation says that control will get to the top of z-order. By default if the control is on top, it's the closest to the parent window (GUI) and it's therefore covered by all other controls being lower down the z-order.

On the other hand, for example, if the GUI would have WS_EX_COMPOSITED ex-style, you would see different effect (also docummented).

Maybe I'm wrong, but an "ontop" control is not covered by all other sibling controls. On the contrary, it is supposed to be in front of us, before all other controls, with the greatest z-order index of the sibling controls. What would be the point of sending it at the bottom of the controls stack, hidden by all of them, and name the variable $GUI_ONTOP ?

I know the actual doc indicates what follows for $GUI_ONTOP, but maybe it has been badly retranscripted in the help file :

$GUI_ONTOP (2048) : Control will be have the ontop attribute for the window (zOrdering).

Also, I have no idea where this link took its source from, in 2017, to indicate a more complete definition :

$GUI_ONTOP : Control will be given the ontop attribute, making it show on top of other elements (zOrdering).

What I may simply do one of these days, it's to add a new comment in trac ticket #2287, linking to the thread we are in, and we'll see what happens : if nothing can be done, at least we'll have the _WinAPI_SetWindowPos function that behaves the same way for all controls.

 

"I think you are searching a bug where there is no bug... don't listen to bad advice."

Posted

Yeah, not sure about trancexx's comment - it doesn't sound right given $HWND_TOP works as expected.

 $WS_EX_COMPOSITED does say it "paints all descendants of a window in bottom-to-top painting order".  I take that as it'll paint each control (within an area) one at a time into a buffer so you can mix alpha channels, then dump the result to the screen.. I don't think the description is alluding to changes in the z-ordering - I'd say its more it's pointing out controls aren't just getting painted on top with some auto-clipping.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...