Jump to content

Docking minimized windows


pixelsearch
 Share

Recommended Posts

Hi everybody :)
There's an interesting feature in PaintShop Pro (PSP) and I succeeded in doing same with AutoIt.
When you got "inner child" windows inside a GUI (the ones created with $WS_CHILD style) and you minimize them, here is what happens :

1) With PSP

1856903371_1a-PSP.png.bb1224920a449a6f84cb6e21f611a9f9.png

2) With AutoIt

1581751483_1a-AutoIt.png.dec06bd2cf1e616c5dad3954309648b6.png

Until now, it's the same behavior : child windows are minimized at the left bottom corner of the parent window.
But when you resize the parent GUI (or Maximize it) then things become very different :

3) With PSP : minimized child windows are still docked in the left bottom corner, great !
(I upload a small parent image, but it would show same if higher or maximized)

779432788_2a-PSP.png.ad6340c33ec2d25954a7cd9f6d6a17b4.png

4) With AutoIt : minimized child windows vanish or are not docked anymore after you resize or maximize the parent window
Of course they're still here somewhere, visible or not, but you'll have to dock them by hand after you resized or maximized the parent window.

464976730_2a-AutoIt.png.f56a2641fccb64a088128418273e963c.png

So, with the following script, based on WM_SIZE message, the behavior is now the same as PSP

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

$hGUI0 = GUICreate("Minimize child then resize parent", 500, 300, 100, 100, _
    BitOr($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX), $WS_EX_COMPOSITED) ; parent

$hGUI1 = GUICreate("Child1 with style", 200, 200, 20, 20, _
    BitOR($WS_CHILD, $WS_OVERLAPPEDWINDOW), -1, $hGUI0) ; child 1
GUISetBkColor(0xF0F4F9)
GUICtrlCreateCheckbox('Filler 1', 10, 10, 50, 20)

$hGUI2 = GUICreate("Child2 with style", 200, 200, 250, 20, _
    BitOR($WS_CHILD, $WS_OVERLAPPEDWINDOW), -1, $hGUI0) ; child 2
GUISetBkColor(0xFFFFDD)
GUICtrlCreateCheckbox('Filler 2', 10, 10, 50, 20)

GUISetState(@SW_SHOW, $hGUI0)
GUISetState(@SW_SHOW, $hGUI1)
GUISetState(@SW_SHOW, $hGUI2)

GUIRegisterMsg($WM_SIZE, "WM_SIZE")

While 1
    $aMsg = GUIGetMsg($GUI_EVENT_ARRAY)

    Switch $aMsg[1]
        Case $hGUI0
            Switch $aMsg[0]
                Case $GUI_EVENT_CLOSE
                    _Exit()
            EndSwitch

        Case $hGUI1
            Switch $aMsg[0]
                Case $GUI_EVENT_CLOSE
                    GUIDelete($hGUI1)
            EndSwitch

        Case $hGUI2
            Switch $aMsg[0]
                Case $GUI_EVENT_CLOSE
                    GUIDelete($hGUI2)
            EndSwitch
    EndSwitch
WEnd

;==========================================
Func WM_SIZE($hWnd, $iMsg, $wParam, $lParam)

    If $hWnd = $hGUI0 Then ; parent
        ; Parent client width  = BitAND($lParam, 0xFFFF) = _WinAPI_LoWord($lParam)
        ; Parent client height = BitShift($lParam, 16)   = _WinAPI_HiWord($lParam)
        Local $aEnumChild = _WinAPI_EnumChildWindows($hWnd)
        If IsArray($aEnumChild) Then
            Local Static $iWidth_Child = 0, $iHeight_Child = 0
            Local $hChild, $iNb_Child_Minimized = 0
            For $i = 1 To $aEnumChild[0][0]
                If $aEnumChild[$i][1] = "AutoIt v3 GUI" Then
                    $hChild = $aEnumChild[$i][0]
                    If BitAND(WinGetState($hChild), $WIN_STATE_MINIMIZED) _
                    And _WinAPI_GetParent($hChild) = $hWnd Then ; ignore eventual grand child
                        If $iWidth_Child = 0 Then ; only once (as Static variable)
                            Local $aPos_Child = WinGetPos($hChild)
                            $iWidth_Child = $aPos_Child[2] ; minimized
                            $iHeight_Child = $aPos_Child[3] ; minimized
                        EndIf
                        Winmove($hChild, "", $iWidth_Child * $iNb_Child_Minimized, _
                            BitShift($lParam, 16) - $iHeight_Child)
                        $iNb_Child_Minimized +=1
                    EndIf
                EndIf
            Next
        EndIf
    EndIf
    Return $GUI_RUNDEFMSG

EndFunc

;==========================================
Func _Exit()

    GUIDelete($hGUI2)
    GUIDelete($hGUI1)
    GUIDelete($hGUI0)
    Exit

EndFunc

If you want to compare with AutoIt original behavior, just comment out this line :

; GUIRegisterMsg($WM_SIZE, "WM_SIZE")

This function WM_SIZE seems portable : only the parent GUI handle is required once at 1st line of function.

* Update Sept 10, 2020 : ignore an eventual grand child window (a child window created inside another child window)
* Update Sept 11, 2020 : got rid of $iInc counter variable

Edited by pixelsearch
Update (changes listed just above)
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...