mpower

Scrollable area and resizing

6 posts in this topic

#1 ·  Posted (edited)

Hi guys, I have a GUI which requires scrolling, however resizing is a bit of a problem because any time you scroll down/up and then resize, the controls move down/up and blank space is created within the scrollable area. 

Any help with maintaining scrollable area size to be fixed would be great.

Here is a reproducer:

To achieve the undesirable effect I described, simply run the script, scroll down and then resize window. You will notice that new blank space is created either on top or on bottom of the window depending on scrolling/resizing direction. Easiest way to see how bad it is, is to scroll down the page about half-way and then maximise the window. You will notice now a whole bunch of blank space is added to the top of the window and scrolling up simply shows nothing, scrolling down shows controls but they are cut off because of the blank space created on top of the page.

This is all happening within the yellow bg  child gui. I need to make it so that even if the GUI is resized the contents of the yellow bg child gui do not move and the scrollable area within the child gui remains the same.

#NoTrayIcon
#include-once
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GUIScroll.au3>
#include <SendMessage.au3>
Opt("GUIResizeMode", 802)

Global $parentgui_w = 880, $parentgui_h = 810, $childgui_w = $parentgui_w - 2, $childgui_h = $parentgui_h - 292

$parentgui = GUICreate("Scrollbar resize problem", $parentgui_w, $parentgui_h, -1, -1, BitOR($WS_MINIMIZEBOX, $WS_MAXIMIZEBOX, $WS_SIZEBOX))
GUISetBkColor(0xFFFFFF, $parentgui)

$childgui = GUICreate("", $childgui_w, $childgui_h, -5, 263, $WS_POPUP, $WS_EX_MDICHILD, $parentgui)
GUISetBkColor(0xFFF123, $childgui)
Dim $buttons[25]

For $i = 0 to 24
    If $i > 0 Then
        $cPos = ControlGetPos($childgui, "", $buttons[$i - 1])
        $buttons[$i] = GUICtrlCreateButton("Button " & $i + 1, ($childgui_w - 200) / 2, $cPos[1] + $cPos[3] + 50, 200, 80)
    Else
        $buttons[$i] = GUICtrlCreateButton("Button " & $i + 1, ($childgui_w - 200) / 2, 20, 200, 80)
    EndIf
Next

Scrollbar_Create($childgui, $SB_VERT, 130 * 25)
Scrollbar_Step(15, $childgui, $SB_VERT)

GUIRegisterMsg($WM_SIZE, "WM_SIZE")
GUIRegisterMsg($WM_NCACTIVATE, "WM_NCACTIVATE")
GUIRegisterMsg($WM_MOUSEWHEEL, "WM_MOUSEWHEEL")

GUISetState(@SW_SHOW, $parentgui)
GUISetState(@SW_SHOWNOACTIVATE, $childgui)

While 1
    $msg = GUIGetMsg(1)
    Switch $msg[1]
        Case $parentgui
            Switch $msg[0]
                Case $GUI_EVENT_CLOSE
                    Exit
                Case $GUI_EVENT_RESTORE
                    $pPos = WinGetPos($parentgui)
                    WinMove($parentgui, "", Default, Default, $pPos[2]+1, $pPos[3]+1)
                    WinMove($parentgui, "", Default, Default, $pPos[2]-1, $pPos[3]-1)
            EndSwitch
    EndSwitch
WEnd

Func WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)
    Local $iMw = BitShift($wParam, 16)
    $scroll_lines = 5

    If $iMw > 0 Then
        For $i = 0 to $scroll_lines
            _SendMessage($childgui, $WM_VSCROLL, $SB_LINEUP)
        Next
    Else
        For $i = 0 to $scroll_lines
            _SendMessage($childgui, $WM_VSCROLL, $SB_LINEDOWN)
        Next
    EndIf
    Return $GUI_RUNDEFMSG
EndFunc

Func WM_SIZE($hwnd, $uMsg, $wParam, $lParam)
    If $hwnd = $parentgui Then
        $wPos = WinGetPos($parentgui)
        $pgui_wdiff = ($wPos[2] - $parentgui_w) / 2
        $pgui_hdiff = ($wPos[3] - $parentgui_h) / 2
        If $pgui_wdiff > 7 Then
            If $pgui_hdiff <> 0 Then
                If $wPos[2] > $parentgui_w Then
                    WinMove($childgui, "", $wPos[0] + 2 + $pgui_wdiff, Default, $parentgui_w - 2, $wPos[3] - 306)
                Else
                    WinMove($childgui, "", $wPos[0] + 2 + $pgui_wdiff, Default, $wPos[2] - 16, $wPos[3] - 306)
                EndIf
            Else
                WinMove($childgui, "", $wPos[0] + 2 + $pgui_wdiff, Default)
            EndIf
        ElseIf $pgui_wdiff < 7 Then
            If $wPos[0] <> -32000 Then
                WinMove($childgui, "", $wPos[0] + 8, Default, $wPos[2] - 16, $wPos[3] - 306)
            EndIf
        ElseIf $pgui_hdiff > 42 Then
            WinMove($childgui, "", Default, Default, Default, $wPos[3] - 306)
        EndIf
    EndIf
    Return 0
EndFunc

Func WM_NCACTIVATE($hwnd, $imsg, $wparam)
    If $hwnd = $parentgui Then
        If NOT $wparam Then Return 1
    EndIf
    Return $gui_rundefmsg
EndFunc

 

Edited by mpower

Share this post


Link to post
Share on other sites



I'd recommend getting the dialog metrics for the system so you can make your child fit a little better.

Func GetDialogMetrics()
    Local $tStruct = DllStructCreate("struct;long caption;long xBorder;long yBorder;long xDlgFrame;long yDlgFrame;endstruct")
    For $iSysMetric = $SM_CYCAPTION To $SM_CYDLGFRAME
        DllStructSetData($tStruct, $iSysMetric - $SM_CYCAPTION + 1, _WinAPI_GetSystemMetrics($iSysMetric))
    Next
    Return $tStruct
EndFunc   ;==>GetDialogMetrics

As for the sizing, you can get the new width and height of the main gui using the lParam from the WM_SIZE function

Func WM_SIZE($hwnd, $uMsg, $wParam, $lParam)
    Local $iWidth = _WinAPI_LoWord($lParam)
    Local $iHeight = _WinAPI_HiWord($lParam)

    If $hwnd = $parentgui Then
        WinMove($childgui, "", x, y, $iWidth - 2, $iHeight - 292)
    EndIf
    Return 0
EndFunc

Also, if you use _WinApi_SetParent you can make your child GUI a real mdi child gui, so it's drawn inside the parent. It will get rid of that nasty effect where the child and parent minimize separately.

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

49 minutes ago, InunoTaishou said:

I'd recommend getting the dialog metrics for the system so you can make your child fit a little better.

Func GetDialogMetrics()
    Local $tStruct = DllStructCreate("struct;long caption;long xBorder;long yBorder;long xDlgFrame;long yDlgFrame;endstruct")
    For $iSysMetric = $SM_CYCAPTION To $SM_CYDLGFRAME
        DllStructSetData($tStruct, $iSysMetric - $SM_CYCAPTION + 1, _WinAPI_GetSystemMetrics($iSysMetric))
    Next
    Return $tStruct
EndFunc   ;==>GetDialogMetrics

As for the sizing, you can get the new width and height of the main gui using the lParam from the WM_SIZE function

Func WM_SIZE($hwnd, $uMsg, $wParam, $lParam)
    Local $iWidth = _WinAPI_LoWord($lParam)
    Local $iHeight = _WinAPI_HiWord($lParam)

    If $hwnd = $parentgui Then
        WinMove($childgui, "", x, y, $iWidth - 2, $iHeight - 292)
    EndIf
    Return 0
EndFunc

Also, if you use _WinApi_SetParent you can make your child GUI a real mdi child gui, so it's drawn inside the parent. It will get rid of that nasty effect where the child and parent minimize separately.

Thanks for these! I will take this into account, especially _WinApi_SetParent. 

Scrollbar issues still persists though :(

 

EDIT: Hmm I tried using _WinApi_SetParent($childgui, $parentgui) however its not working correctly :(

Edited by mpower

Share this post


Link to post
Share on other sites

Does anyone know of an effective way of dealing with the issue of scrollable area when resizing? Is there a way to perhaps retain the scroll position, resize the gui and adjust the scrollable area to fit the new window size?

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

So the only solution I've been able to come up with is to set the vertical scroll position to 0 when resizing. Whilst its not very good for user experience, it does negate the blank white space that would be padded to the top of the gui and end up cutting of controls further down below.

If anyone does come up with a better solution I'd be super keen to see it! :)

 

P.S. Here's the updated WM_SIZE function with the scroll to top line added:

Func WM_SIZE($hwnd, $uMsg, $wParam, $lParam)
    Local $iWidth = _WinAPI_LoWord($lParam)
    Local $iHeight = _WinAPI_HiWord($lParam)

    If $hwnd = $parentgui Then
        Scrollbar_Scroll($childgui, $SB_VERT, 0)
        WinMove($childgui, "", Default, Default, $iWidth - 2, $iHeight - 292)
    EndIf
    Return 0
EndFunc

 

Edited by mpower

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

mpower,

Quote

the only solution I've been able to come up with is to set the vertical scroll position to 0 when resizing

That was my conclusion too - see GUIScrollBars_Ex_Example_5 in my Scrollbars UDF (the link is in my sig). The _Scrollbars_WM_ENTER/EXITSIZEMOVE functions in the main UDF do all the work.

M23

Edited by Melba23
Fixed formatting

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

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

  • Similar Content

    • Guy_
      By Guy_
      Let's say a script has to do something that may or may not shift the page a fair bit in a general DTP program, browser, ...
      In other words, the scrollbar was moved.
      (1) Can the original scrollbar position be saved and restored?
      I can think of a rough workaround or two, but I mean, more precisely...?
      (2) If so, is it for example a different control for every program?
      (3) Let's say for a workaround you might use the help of ...
      MouseWheel ( "direction" [, clicks = 1] ) Is there an absolute relationship of clicks to pixels?
      Or does the amount of scroll from these 'clicks' depend on how much movement was defined for the scroll wheel in Windows or Mouse driver software?
      Thank You
    • RobOtter
      By RobOtter
      Hi,
      I want to write a tool to resize usually unresizable windows (like the file properties window of Windows Explorer for example).
      Although I have already managed to set the window border style to resizable, this of course doesn´t add the resizing feature itself. So, how do I hook on this to perform the resizing of window and controls myself? I think of some kind of event handler but have no idea how start. Can you help me with this?
      Thanks,
      Rob
    • DrPickles
      By DrPickles
      I am interested in using scrolling groups for a dropdown box listing. I add the $WS_VSCROLL and it shows the group scroll control but never actually activates and the information goes past the group.
      any suggestions or workarounds?
      groupscroll.au3
       
      #include <ButtonConstants.au3>
      #include <GUIConstantsEx.au3>
      #include <WindowsConstants.au3>
      #include <ComboConstants.au3>
      #include <GUIConstantsEx.au3>
      #include <GUIListBox.au3>
      #include <SliderConstants.au3>
      #include <StaticConstants.au3>
      #include <WindowsConstants.au3>
      #Region ### START Koda GUI section ### Form=Form1.kxf
      $Form1 = GUICreate("Form1", 615, 438, 192, 124)
      $Group1 = GUICtrlCreateGroup("Group1", 184, 120, 305, 209, BitOR($GUI_SS_DEFAULT_GROUP,$WS_VSCROLL))
      For $i = 0 To 20 Step 1
         $drop = (20* $i)
      $Label2 = GUICtrlCreateLabel($i, 200, 140 + $drop, 28, 31)
      GUICtrlCreateCombo("module", 220, 140 + $drop, 121, 25, BitOR($CBS_DROPDOWN,$CBS_AUTOHSCROLL))
      Next

      GUICtrlCreateGroup("", -99, -99, 1, 1)
      GUISetState(@SW_SHOW)
      #EndRegion ### END Koda GUI section ###
      While 1
       $nMsg = GUIGetMsg()
       Switch $nMsg
        Case $GUI_EVENT_CLOSE
         Exit
       EndSwitch
      WEnd
    • Herb191
      By Herb191
      How can you scroll to the end of a text area in IE without using focus/ControlSend? I have tried several solutions (see code below) but I can't seem to get them to work.
      Test HTML (test.html)
      <!DOCTYPE html> <html> <body> <textarea id="textarea-test" rows="4" cols="50"> </textarea> </body> </html>  
      AutoIt Test Code:
      #RequireAdmin #include <IE.au3> $oIE = _IECreate(@ScriptDir & "\test.html") Local $hWnd = _IEPropertyGet($oIE, "hwnd") Local $oTextarea = _IEGetObjById($oIE, "textarea-test") Local $sText = "" For $i = 1 To 30 $sText &= $i & "&#13;&#10;" _IEPropertySet($oTextarea, "innerhtml", $sText) ;NOT WORKING ;$oTextarea.document.parentwindow.scroll(0, 99999) ;_IEAction($oTextarea, "scrollintoview") ;NOT WORKING ;$iDocHeight = $oTextarea.document.body.scrollHeight() ;$oTextarea.document.parentwindow.scrollTo(0, $iDocHeight) ;NOT WORKING ;$oTextarea.document.parentwindow.scrollTo(0, 99999) ;NOT WORKING ;$oTextarea.scrollintoview() ;WORKING _IEAction($oTextarea, "focus") ControlSend($hWnd, "", "[CLASS:Internet Explorer_Server; INSTANCE:1]", "^{end}") Sleep(100) Next  
       
    • wakillon
      By wakillon
      TinyPicSharer :

      A simple and handy tool for capture window or picture by mouse grab and an uploader for 10 Pic Hosters !
      You can also Resize, Convert, Optimize, add WaterMark to your images easily.
      (optimization with jpegtran.exe, optipng.exe, gifsicle.exe command line tools)
      In plus it can extract images from Docs (pdf, doc, docx, odt, odp, ppt, pptx, pps, ppsx)
      (Doc extraction with b2xtranslator and pdfextract.exe command line tools)
      Just Drag'n drop a picture/doc on the Host Logo for load it.
      I have replaced Curl by WinHttp functions and TrIDLib.DLL by my own FileGetType function.
       

       
      Previous downloads : 1343

      Update of 8 June 2013
      source and executable are available in the Download Section
      See Tray menu for options.
      Double click on his tray icon for restore the gui.
       
      >zlib.au3, WinHttp.au3, >WinAPIEx UDF are needed. ( Thanks to Ward, trancexx, Yashield )
      Hope you 'll find it usefull !