简体   繁体   中英

C# How to force Paint event of Panel1 and Panel2 complete at the same time?

I have a SplitContainer (a NonFlickerSplitContainer one to be exact) and I treat its both panels as a single canvas to paint on. I use Graphics.DrawImage method to paint bitmaps on the panels separately. I refresh Panel1 first, then Panel2 which results in vertical/horizontal tearing - painting of Panel1 ends, then painting of Panel2 starts - that's the reason. What would be the solution to my problem? I use a splitContainer as an output to a "bitmap video stream" with before/after capability. Maybe I can freeze UI somehow until Panel2_Paint ends?

    private void splitContainer_Panel1_Paint(object sender, PaintEventArgs e)
    {
        if (frameA != null)
        {
            if (ORIGINAL_SIZE_SET)
                e.Graphics.DrawImage(frameA, 0, 0);
            else
                e.Graphics.DrawImage(frameA, 0, 0, ClientSize.Width, ClientSize.Height);
        }
    }

    private void splitContainer_Panel2_Paint(object sender, PaintEventArgs e)
    {
        if (frameB != null)
        {
            //...

            if (ORIGINAL_SIZE_SET)
                e.Graphics.DrawImage(frameB, x, y);
            else
                e.Graphics.DrawImage(frameB, x, y, ClientSize.Width, ClientSize.Height);
        }
    }

    private Bitmap frameA = null;
    private Bitmap frameB = null;

    private void RefreshOutput(bool refreshClipA = true, bool refreshClipB = true)
    {
        if (refreshClipA)
        {
            frameA = GetVideoFrame(...);

            //...
        }

        if (refreshClipB)
        {
            frameB = GetVideoFrame(...);

            //...
        }

        if (refreshClipA)
            splitContainer.Panel1.Refresh();

        if (refreshClipB)
            splitContainer.Panel2.Refresh();
    }

Maybe I can freeze UI somehow until Panel2_Paint ends?

Take a look at: https://msdn.microsoft.com/en-us/library/system.windows.forms.control.suspendlayout(v=vs.110).aspx

Call SuspendLayout() on your control, do all of your graphics operations and then call ResumeLayout() to update everything all at once. There is an example in that documentation.

If your drawing operations take too long then temporary graphical artifacts mght begin to appear in the "frozen" area until after ResumeLayout().

Have a look at the documentation for SplitContainer.Invalidate(bool invalidate Children) .

From the link:

Invalidates a specific region of the control and causes a paint message to be sent to the control. Optionally, invalidates the child controls assigned to the control.

So instead of invalidating each panel separately just call this method once and it should do what you want. Or to modify your code only a bit:

if (refreshClipA && refreshClipB)
{
    splitContainer.Invalidate(true);
}
else
{
    if (refreshClipA)
    {
        splitContainer.Panel1.Refresh();
    }
    else if (refreshClipB)
    {
        splitContainer.Panel2.Refresh();
    }
}

Essentially what I am doing is if both of them need repainting let splitContainer handle it, else check each one individually and paint if required.

Leading on from @DonBoitnott's comment, Instead of using Invalidate(true) use Refresh() which from the documentation:

Forces the control to invalidate its client area and immediately redraw itself and any child controls.

So just change splitContainer.Invalidate(true) to splitContainer.Refresh() .

I have experienced it is impossible to make sure that two separate panel.Paint() events complete at the same moment, at least not in a WinForms project. The only solution that worked for me is the suggested by DonBoitnott. I use a single panel now and simulate a splitcontainer behavior.

If I were answering this, I would suggest you ditch the splitcontainer and render to a single surface, that way you are always in a single Paint event and you simply region it off and draw accordingly. DonBoitnott Feb 17 '16 at 17:51

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM