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

1


•   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

2


•   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.

 

1
0