Search code examples
c#winformspaintinvalidation

Control.Invalidate does not trigger the paint event of hidden or invisible Control


When I call Invalidate method on a hidden or invisible control, paint event is not triggered.

Is this the behavior of windows forms controls ? Is there any documentation available ?

I checked the documentation of Control.Invalidate method but it does not mention about invisible controls https://msdn.microsoft.com/en-in/library/system.windows.forms.control.invalidated(v=vs.110).aspx

I checked the following SO question How are the painting of invisible controls handled in WinForms? but it is asked for flickering problem in compact framework and not related to my question


Solution

  • Well i think the best way to investigate this was to check the source code from Microsoft. This is what's going on:

    When the Control is set to Visible false, the Control's handle created flag is also set to false.

    The Invalidate() method (source code below) doesn't do its work when IsHandleCreated is false; That's the entire story actually.

    /// <include file='doc\Control.uex' path='docs/doc[@for="Control.Invalidate3"]/*' />
    /// <devdoc>
    ///     Invalidates the control and causes a paint message to be sent to the control.
    ///     This will not force a synchronous paint to occur, calling update after
    ///     invalidate will force a synchronous paint.
    /// </devdoc>
    public void Invalidate(bool invalidateChildren)
    {
        if (IsHandleCreated)
        {
            if (invalidateChildren)
            {
                SafeNativeMethods.RedrawWindow(new HandleRef(window, Handle),
                                                null, NativeMethods.NullHandleRef,
                                                NativeMethods.RDW_INVALIDATE |
                                                NativeMethods.RDW_ERASE |
                                                NativeMethods.RDW_ALLCHILDREN);
            }
            else
            {
                // It's safe to invoke InvalidateRect from a separate thread.
                using (new MultithreadSafeCallScope())
                {
                    SafeNativeMethods.InvalidateRect(new HandleRef(window, Handle),
                                                        null,
                                                        (controlStyle & ControlStyles.Opaque) != ControlStyles.Opaque);
                }
            }
    
            NotifyInvalidate(this.ClientRectangle);
        }
    }