mpower Posted April 21, 2016 Posted April 21, 2016 (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. expandcollapse popup#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 April 21, 2016 by mpower
InunoTaishou Posted April 21, 2016 Posted April 21, 2016 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.
mpower Posted April 21, 2016 Author Posted April 21, 2016 (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 April 21, 2016 by mpower
mpower Posted May 2, 2016 Author Posted May 2, 2016 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?
mpower Posted May 4, 2016 Author Posted May 4, 2016 (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 May 5, 2016 by mpower
Moderators Melba23 Posted May 5, 2016 Moderators Posted May 5, 2016 (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 May 5, 2016 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 Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now