JakeJohnson74

GUI's Child GUI moving unexpectedly when resized

11 posts in this topic

Hello, 

I had a thread somewhat related to this where I was nesting tabs - and found out that in order to nest multiple tab controls, I needed 1 GUI per Tab control. 

Well this leads me to this post :) I have a simple test with everything removed but 2 of the many GUI's and all the controls are gone to isolate this behavior. 

What I'm trying to do: 

I want to drag the window to resize, or minimize/maximize and I want all of my child GUI's to follow suit (Like a control that is set to dock to the various areas of the form)

To do this I have created a label and colored it green in the example - This label acts exactly how I want it to act. 

The Child GUI of my main GUI should resize and position itself right on top of my label, but it's not. 

I get the correct resize, but it seems to be putting the child GUI in X,Y coords of my monitor, not the parent GUI. (not sure if that is what's really happening, but that is what it looks like to me)

Here is the example:

#include <GUIConstants.au3>
#include <GuiConstantsEx.au3>

$iGuiWidth = 660
$iGUIHeight = 320

Global $hgui, $hgui1, $cLabel_1
Global $bSysMsg = False

GUI()
GUIRegisterMsg($WM_SIZE, "_WM_SIZE")
GUIRegisterMsg($WM_SYSCOMMAND, "_WM_SYSCOMMAND")

func GUI()
$hGui = GUICreate("test",$iGuiWidth,$iGUIHeight,-1,-1,BitOR($WS_OVERLAPPEDWINDOW, $WS_POPUP))
GUISetBkColor(0x666666)

$cLabel_1 = GUICtrlCreateLabel("I am the label",4,65,$iGuiWidth-7,250)
GUICtrlSetBkColor(-1,0x00FF00)
GUICtrlSetResizing(-1, BitOR($GUI_DOCKLEFT, $GUI_DOCKTOP, $GUI_DOCKBOTTOM, $GUI_DOCKWIDTH,$GUI_DOCKRIGHT))
GUICtrlSetState(-1, $GUI_DISABLE)
GUISetState()

$hGui1 = GUICreate("",$iGuiWidth-7,$iGUIHeight-70,-1,60, $WS_POPUP, $WS_EX_MDICHILD, $hgui)
GUISetBkColor(0x888888)
GUISetState()

EndFunc   ;==>GUI

While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $GUI_EVENT_CLOSE
            Quit()
    EndSwitch

    If $bSysMsg Then
        $bSysMsg = False
        _Resize_GUIs()
    EndIf

WEnd

Func Quit()
    Exit
EndFunc   ;==>Quit

Func _Resize_GUIs()
    $aRet = ControlGetPos($hgui, "", $cLabel_1)
    WinMove($hgui1, "", $aRet[0], $aRet[1], $aRet[2], $aRet[3])
EndFunc   ;==>_Resize_GUIs

Func _WM_SYSCOMMAND($hWnd, $msg, $wParam, $lParam)

    Const $SC_MAXIMIZE = 0xF030
    Const $SC_RESTORE = 0xF120

    Switch $wParam
        Case $SC_MAXIMIZE, $SC_RESTORE
            $bSysMsg = True
    EndSwitch

EndFunc   ;==>_WM_SYSCOMMAND

Func _WM_SIZE($hWnd, $msg, $wParam, $lParam)
    _Resize_GUIs()
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_SIZE

Share this post


Link to post
Share on other sites



JakeKenmode,

You need to determine the screen coordinates required for the GUI move - this shows how you can do it: :)

#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>

$iGuiWidth = 660
$iGUIHeight = 320

Global $hgui, $hgui1, $cLabel_1, $iOFfset_X, $iOFfset_Y
Global $bSysMsg = False

GUI()
GUIRegisterMsg($WM_SIZE, "_WM_SIZE")
GUIRegisterMsg($WM_SYSCOMMAND, "_WM_SYSCOMMAND")

Func GUI()
    $hgui = GUICreate("test", $iGuiWidth, $iGUIHeight, -1, -1, BitOR($WS_OVERLAPPEDWINDOW, $WS_POPUP))
    GUISetBkColor(0x666666)

    $cLabel_1 = GUICtrlCreateLabel("I am the label", 4, 65, $iGuiWidth - 7, 250)
    GUICtrlSetBkColor(-1, 0x00FF00)
    GUICtrlSetResizing(-1, BitOR($GUI_DOCKLEFT, $GUI_DOCKTOP, $GUI_DOCKBOTTOM, $GUI_DOCKWIDTH, $GUI_DOCKRIGHT))
    GUICtrlSetState(-1, $GUI_DISABLE)
    GUISetState()

    $hgui1 = GUICreate("", $iGuiWidth - 7, $iGUIHeight - 70, -1, 60, $WS_POPUP, $WS_EX_MDICHILD, $hgui)
    GUISetBkColor(0x888888)
    GUISetState()

    ; Determine offset of client area inside GUI <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    $aWin = WinGetPos($hgui)                                ; GUI position in screen coords
    Local $tPoint = DllStructCreate("int X;int Y")          ; Beginnning of client area (0, 0)
    DllStructSetData($tPoint, "X", 0)
    DllStructSetData($tPoint, "Y", 0)
    _WinAPI_ClientToScreen($hgui, $tPoint)                      ; Convert to screen coords
    $iOFfset_X = DllStructGetData($tPoint, "X") -  $aWin[0] ; Size of left border
    $iOFfset_Y = DllStructGetData($tPoint, "Y") -  $aWin[1]     ; Size of top border

EndFunc   ;==>GUI

While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $GUI_EVENT_CLOSE
            Quit()
    EndSwitch

    If $bSysMsg Then
        $bSysMsg = False
        _Resize_GUIs()
    EndIf

WEnd

Func Quit()
    Exit
EndFunc   ;==>Quit

Func _Resize_GUIs() ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    $aWin = WinGetPos($hgui)
    $aRet = ControlGetPos($hgui, "", $cLabel_1)
    ; Now sum GUI position, border offsets and label position within the GUI
    WinMove($hgui1, "", $aWin[0] + $iOFfset_X + $aRet[0], $aWin[1] + $iOFfset_Y + $aRet[1], $aRet[2], $aRet[3])
EndFunc   ;==>_Resize_GUIs

Func _WM_SYSCOMMAND($hWnd, $msg, $wParam, $lParam)

    Const $SC_MAXIMIZE = 0xF030
    Const $SC_RESTORE = 0xF120

    Switch $wParam
        Case $SC_MAXIMIZE, $SC_RESTORE
            $bSysMsg = True
    EndSwitch

EndFunc   ;==>_WM_SYSCOMMAND

Func _WM_SIZE($hWnd, $msg, $wParam, $lParam)
    _Resize_GUIs()
    Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_SIZE
There are other ways to get the GUI border sizes but I quite like this one. ;)

M23

P.S. Do not use #include <GUIConstants.au3> as it adds all of the constants files into your script - much better to add only those you need. ;)


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

Gotcha :) Ill give it a go! 

Share this post


Link to post
Share on other sites

So, another odd thing I noticed, when I Drag the title bar of the window to the top of the desktop to maximize the screen, it does not resize correctly. 

Is there an event I can access to capture this type of GUI interaction? 

Share this post


Link to post
Share on other sites

JakeKenmode,

Can you be more specific in what you need to do to see this problem because I can drag the GUI anywhere on screen and it still resizes correctly? :huh:

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

JakeKenmode,

I do not use Aero, so I cannot really offer any useful advice. From what I can quickly google, dragging a GUI by its title bar sends different SC_MOVE/RESTORE message sequences with Aero enabled/disabled which may well be the cause of the problem. Sorry not to be of more help. :(>

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

Just looking from the users standpoint - Because I know in my company all of the workstations are defaulted with Aero on. So If I can do it - someone else will eventually do it as well lol :)

Ill snoop around and see what I can come up with. 

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

Ok - I have done some prelim investigating. 

Hopefully this will help us get to the bottom of it. I know you are not using Aero :( Maybe this will shed some light? 

I used consolewrite() to give me some data on the issue. It is in both of the WINAPI functions WM_SYSCOMMAND and WM_SIZE

Here is the test I did, and the findings. 

Does this tell you anything I am not seeing? It's clear to see that the WM_SIZE Function is not being called for the child when using Aero, but I thought I would post this and see if anything stuck out to you. 

**Edit - The other thing is that the WM_SYSCOMMAND is not seeing the SC_MAXIMIZE and SC_RESTORE messages for the parent, so this is why the child is not reacting.

post-87120-0-36243800-1423675992_thumb.j

Edited by JakeKenmode

Share this post


Link to post
Share on other sites

JakeKenmode

Try registering the $WM_ENTERSIZEMOVE & $WM_EXITSIZEMOVE messages. They appear whenever you start/end a size/move operation and so they might be able to act a trigger for resizing as I understand you have to drag the GUI to the screen edge to get this "Snap" thing to work. Set a flag and then wait for the parent GUI maximized/restore message before resizing the child.

I have not tested it, but something like this might just do the trick:

#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>

$iGuiWidth = 660
$iGUIHeight = 320

Global $hgui, $hgui1, $cLabel_1, $iOFfset_X, $iOFfset_Y
Global $bSysMsg = 0

GUI()
GUIRegisterMsg($WM_SIZE, "_WM_SIZE")
GUIRegisterMsg($WM_SYSCOMMAND, "_WM_SYSCOMMAND")

GUIRegisterMsg($WM_ENTERSIZEMOVE, "_WM_ENTERSIZEMOVE")
GUIRegisterMsg($WM_EXITSIZEMOVE, "_WM_EXITSIZEMOVE")

Func GUI()
    $hgui = GUICreate("test", $iGuiWidth, $iGUIHeight, -1, -1, BitOR($WS_OVERLAPPEDWINDOW, $WS_POPUP))
    GUISetBkColor(0x666666)

    $cLabel_1 = GUICtrlCreateLabel("I am the label", 4, 65, $iGuiWidth - 7, 250)
    GUICtrlSetBkColor(-1, 0x00FF00)
    GUICtrlSetResizing(-1, BitOR($GUI_DOCKLEFT, $GUI_DOCKTOP, $GUI_DOCKBOTTOM, $GUI_DOCKWIDTH, $GUI_DOCKRIGHT))
    GUICtrlSetState(-1, $GUI_DISABLE)
    GUISetState()

    $hgui1 = GUICreate("", $iGuiWidth - 7, $iGUIHeight - 70, -1, 60, $WS_POPUP, $WS_EX_MDICHILD, $hgui)
    GUISetBkColor(0x888888)
    GUISetState()

    ; Determine offset of client area inside GUI <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    $aWin = WinGetPos($hgui)                                ; GUI position in screen coords
    Local $tPoint = DllStructCreate("int X;int Y")          ; Beginnning of client area (0, 0)
    DllStructSetData($tPoint, "X", 0)
    DllStructSetData($tPoint, "Y", 0)
    _WinAPI_ClientToScreen($hgui, $tPoint)                      ; Convert to screen coords
    $iOFfset_X = DllStructGetData($tPoint, "X") -  $aWin[0] ; Size of left border
    $iOFfset_Y = DllStructGetData($tPoint, "Y") -  $aWin[1]     ; Size of top border

EndFunc   ;==>GUI

While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $GUI_EVENT_CLOSE
            Quit()
    EndSwitch

    If $bSysMsg Then
        ConsoleWrite("+ Trigger IN - " & $bSysMsg & @CRLF)
        If $bSysMsg > 3 Then
            ConsoleWrite("! Resize" & @CRLF)
            _Resize_GUIs()
        EndIf
        $bSysMsg = 0
        ConsoleWrite("- Trigger OUT - " & $bSysMsg & @CRLF)
    EndIf

WEnd

Func Quit()
    Exit
EndFunc   ;==>Quit

Func _WM_ENTERSIZEMOVE($hWnd, $iMsg, $wParam, $lParam)

    $bSysMsg += 1
    ConsoleWrite("- ENTERSIZEMOVE - " & $bSysMsg & @CRLF)


EndFunc

Func _WM_EXITSIZEMOVE($hWnd, $iMsg, $wParam, $lParam)

    $bSysMsg += 1
    ConsoleWrite("+ EXITSIZEMOVE - " & $bSysMsg & @CRLF)


EndFunc

Func _Resize_GUIs() ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    $aWin = WinGetPos($hgui)
    $aRet = ControlGetPos($hgui, "", $cLabel_1)
    ; Now sum GUI position, border offsets and label position within the GUI
    WinMove($hgui1, "", $aWin[0] + $iOFfset_X + $aRet[0], $aWin[1] + $iOFfset_Y + $aRet[1], $aRet[2], $aRet[3])
EndFunc   ;==>_Resize_GUIs

Func _WM_SYSCOMMAND($hWnd, $msg, $wParam, $lParam)

    Const $SC_MAXIMIZE = 0xF030
    Const $SC_RESTORE = 0xF120

    Switch $wParam
        Case $SC_MAXIMIZE
            $bSysMsg += 1
            ConsoleWrite("- MAXIMIZE - " & $bSysMsg & @CRLF)
        Case $SC_RESTORE
            $bSysMsg += 1
            ConsoleWrite("+ RESTORE - " & $bSysMsg & @CRLF)
    EndSwitch

EndFunc   ;==>_WM_SYSCOMMAND

Func _WM_SIZE($hWnd, $msg, $wParam, $lParam)
    _Resize_GUIs()
    Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_SIZE
M23

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

I might have to tinker a little but I like the idea! 

The problem currently with that example is that when I drag the window and it maximizes when it gets close to the top of the screen and _WM_SYSCOMMAND is not called, and that is where the your boolean variable gets initially set. 

So since it is never set, its never going to be seen by the message loop. It works just fine for normal maximize/restore because _WM_SYSCOMMAND fires.

Im also looking into WM_WINDOWPOSCHANGED this might be another way to "see" what we are looking for although the lParam returns a pointer to WINDOWSPOS and I'm not exactly sure how to work with pointers here in AutoIt, I might have to take another side track and learn how to get what I need from WM_WINDOWPOSCHANGED  >_<

Ref: 

https://msdn.microsoft.com/en-us/library/windows/desktop/ms632652.aspx

Edited by JakeKenmode

Share this post


Link to post
Share on other sites

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