Symptom
When the TabbedView feature is enabled in the MDI Frame window and the MaximizeAllTabbedSheets option is checked, it is found that opening and switching windows is slower than when this feature is not enabled, and there are performance issues.
Environment
PowerBuilder 2022 R3 MR
Cause
Due to the internal mechanism of MDI, there can only be one maximized sheet window. So when one sheet window is maximized, the other sheet windows will resize to normal state. Therefore, when the MaximizeAllTabbedSheets option is checked, you will see the following behaviors:
1. When the first sheet window opens, the resize event of this window will be triggered two times, 1) when the sheet window is loaded; 2) when the sheet window is maximized.
2. When the second sheet window opens, there will be three resize events, 1) when the previous sheet window is resized to normal state; 2) when the second window is loaded; 3) when the second sheet window is maximized.
3. When the user switches the two sheet windows (from A to B), there will be two resize events, 1) when sheet A is resized to normal state; 2) when sheet B is resized to maximized state.
You can refer to the following link for the original behavir of sheets in MDI without TabbedView:
https://docs.appeon.com/pb2022/application_techniques/Using_sheets.html
Resolution
There are three optimization suggestions for your reference.
1. Optimize the existing resize logic.
For example: Optimize the UI refresh time when resize is executed by adding SetRedraw(False).
2. Uncheck the MaximizeAllTabbedSheets option. Manually add code to maximize the window.
Or, when opening the window, keep the window in the normal state and adjust the width and height of the window to fill the MDI Client as much as possible.
3. Keep the MaximizeAllTabbedSheets option checked and refer to the following example to optimize the resize code:
a. Modify your MDI Window (e.g.: w_tabbedviewdemo_frame, you need to replace the window name to yours in this case):
• Add Instance Variables:
Public: Boolean ib_maximizealltabbedsheets_checked // whether the maximizealltabbedsheets option is checked by default.
• Add the following code in the Open event:
// Remember the default option, before opening any sheet window. ib_maximizealltabbedsheets_checked = This.ismaximizealltabbedsheetsenabled()
• Add a new user event ue_tabbedview_restoring_sheet ( window currentsheet ), return (None).
// Recall Resize events of other sheets. // When user click RESTORE or MINIMIZE, inform the mdi window to recall the RESIZE events of other sheets, which were suppressed in resize event. boolean bValid window wSheet wSheet = This.GetFirstSheet() Do wSheet = This.GetNextSheet(wSheet) bValid = IsValid (wSheet) If bValid and wSheet <> currentsheet Then wSheet.Event Resize(0, wSheet.WorkSpaceWidth(), wSheet.WorkSpaceHeight()) End If Loop While bValid
b. Modify the base sheet window (e.g.: w_tabbedviewdemo_basesheet)
• Add new Instance Variables:
Protected: Boolean ib_is_opened_flag = False // This sheet has been opened. Boolean ib_is_first_sheet_opening = False // This sheet is the first sheet opening in MDI window. UnsignedLong ii_lastest_resize_sizetype // The latest sizetype of this sheet. Boolean ib_has_resize_cache = False // Has the cache of the arguments that execute the real resize log. UnsignedLong iul_resize_cache_sizetype // Cache of the sizetype argument Int ii_resize_cache_newwidth // Cache of the newwidth argument Int ii_resize_cache_newheight // Cache of the newheight argument
• Add a new function protected subroutine of_set_tabbedview_opened_flag (), return (None).
protected subroutine of_set_tabbedview_opened_flag (); // Set opened flag w_tabbedviewdemo_frame lw_mdi //MDI Frame Window name, please change it by yourself. lw_mdi = w_tabbedviewdemo_frame If lw_mdi.IsTabbedViewEnabled() And lw_mdi.ib_maximizealltabbedsheets_checked Then // This sheet has been opened and actived If Not ib_is_opened_flag Then ib_is_opened_flag = True End If end subroutine
• Add the following code in the Open event:
This.Post of_set_tabbedview_opened_flag()
• Add a new event event ue_tabbedview_syscommand that map to pbm_syscommand:
// When user click RESTORE or MINIMIZE, inform the mdi window to recall the RESIZE events of other sheets, which were suppressed in resize event. Constant unsignedlong SC_RESTORE = 61728 Constant unsignedlong SC_MINIMIZE = 61472 Constant unsignedlong SC_MAXIMIZE = 61488 w_tabbedviewdemo_frame lw_mdi //MDI Frame Window name, please change it by yourself. lw_mdi = w_tabbedviewdemo_frame If (commandtype = SC_RESTORE or commandtype = SC_MINIMIZE) And This.WindowState = Maximized! Then lw_mdi.Post Event ue_tabbedview_restoring_sheet(This) End If
• Add a new function protected function boolean of_is_tabbedview_resize_optimized (unsignedlong sizetype, integer newwidth, integer newheight):
protected function boolean of_is_tabbedview_resize_optimized (unsignedlong sizetype, integer newwidth, integer newheight); // Try to optimize the resize event when TabbedView and MaximizeAllTabbedSheets is check. Boolean lb_skip_resize w_tabbedviewdemo_frame lw_mdi //MDI Frame Window name, please change it by yourself. lw_mdi = w_tabbedviewdemo_frame If lw_mdi.IsTabbedViewEnabled() And lw_mdi.ib_maximizealltabbedsheets_checked Then If lw_mdi.ismaximizealltabbedsheetsenabled() Then // If ArrangeSheets or RESTORE/MINIMIZE, don't need to optimize the resize event. // Optimize selectionchanging process (including closing) If ib_has_resize_cache And ib_is_opened_flag Then If sizetype = 0 And iul_resize_cache_sizetype = 2 Then // Suppress resize logic when the current sheet is changing to normal! state lb_skip_resize = True ElseIf sizetype = 2 And ii_lastest_resize_sizetype = 0 And (sizetype = iul_resize_cache_sizetype And newwidth = ii_resize_cache_newwidth And newheight = ii_resize_cache_newheight) Then lb_skip_resize = True // Suppress resize logic when changing to this sheet and arguments are the same as cached. End If End If // Optimize Open process If Not ib_is_opened_flag And sizetype <> 2 Then // Normal. Suppress the redundant resize event triggerred when opening the window the first time. lb_skip_resize = True End If End If ii_lastest_resize_sizetype = sizetype // Always remember the lastest sizetype If lb_skip_resize Then // Skip resize Return True Else // Record arguments and go on ib_has_resize_cache = True iul_resize_cache_sizetype = sizetype ii_resize_cache_newwidth = newwidth ii_resize_cache_newheight = newheight End If End If Return False end function
• Add the following code at the top of the resize event:
// Skip resize log if can be optimized If of_is_tabbedview_resize_optimized(sizetype, newwidth, newheight) Then return //Original resize logic //…
Notes:
1) This is a case that optimizes resize event in the base sheet. You may refer to this solution to add similar code when your heavy resize logic is located in the derived window.
2) For sheet windows with special layouts and "Extend Ancestor Script" is not checked in the resize event, you need to add the of_is_tabbedview_resize_optimized function so that it is executed in the front of the resize event.