Previous | Index | Next 

[PRB] Multiple or missing Paint events

The Windows Forms portion of the .NET Framework suffers from a very elusive bug: if a form contains one or more Label, Command or Panel controls, then the form fires two consecutive Paint events when the form become visible.  This bug affects forms, PictureBox and UserControl controls.

Early versions of VB Migration Partner library "inherited" this problem and consequently fired one spurious Paint event.

Unfortunately, there is no bullet-proof way to detect the second spurious Paint event from the first Paint event or from a regular Paint event that fires sometime later, during the normal form lifetime. The call stack is the same and there is no way to understand when a Paint event is to be discarded to preserve full functional equivalence with VB6.

Starting with version 1.32, we have added a boolean variable to the VB6Form, VB6PictureBox, and VB6UserControl classes, named IgnoreNextPaintEvent. You can set this variable to True to force VB Migration Partner to ignore the next Paint event for a given form, picturebox or UserControl. Typically you do this in the Form_Load event handler

        Private Sub Form_Load()
            '## InsertStatement Me.IgnoreNextPaintEvent = True
            ...
        End Sub

The IgnoreNextPaintEvent variable has a protected scope in the VB6Form class, and a public scope in the VB6PictureBox and VB6UserControl classes. We recommend that you set this variable only if you notice that a migrated .NET form suffers from problems related to duplicate Paint events.

Another problem related to the Paint event is that .NET doesn't fire the Paint event on child controls in some cases, which in turn prevents the application from updating the controls' contents. If your code relies on these (missing) Paint events, you should force them from inside the Form_Paint event handler, as in this example:

        Private Sub Form_Paint()
            ' here is the standard code for the form's Paint event
            ' ...
  
            '## InsertStatement ' force the Paint event for the Picture1 control
            '## InsertStatement Me.Picture1.Refresh()
            ...
        End Sub

If the form contains many child controls that must fire the Paint event, invoking the Refresh on each control can be an annoying, error-prone approach. For this reason, starting with version 1.32, the VB6Form class exposes the new RefreshChildControls method, which invokes the Refresh method on each child control. Invoking this method can be necessary, for example, immediately after a Cls method:

        Me.Cls()
        Me.RefreshChildControls(False)

The argument is optional: if True all the controls on the form are refreshed, including nested controls. If False or omitted, only the controls that are contained directly on the form are refreshed.

Keep in mind that forcing the refresh of one or more controls from inside the Form_Paint event handler can slightly degrade performances (compare to the original VB6 code), because if the form was covered only partially you might be refreshing a control that doesn't really need to. In most cases, this behavioral difference shouldn't cause any serious problem.

Please notice, however, that in some especially complex cases - for example, when you rely on the Paint event to draw custom drawings with the Cls, Line, and Circle graphic methods - the result might different from .NET. At each new release we attempt to reduce the gap between VB6 and .NET, however the two worlds are very different and some differences aren't avoidable.

 

Previous | Index | Next