简体   繁体   中英

Can I use Graphics object in any other event than Paint event?

I have a WinForm with a docked Panel. I overrode the Panel's Paint event. I have a line that sets up _graphics object:

private Graphics _graphics;

In the override I initialize _graphics object:

private void GridPanel_Paint(object sender, PaintEventArgs e)
{
    _graphics = e.Graphics;

    <snip>
    …
    </snip>
}

Here comes the stupid part, Can I use this _graphics object in any other event like MouseMove?

It depends what do you mean by "use".

Graphics is disposable. After repainting, control disposes Graphics instance, that was passed into Paint event handler. From that point, disposed object is useless. But caching a reference to that instance is absolutely legal.

You can use graphics object of your control using CreateGraphics method where you want, but when the control refreshes, your painting will disappear.

So it's better to draw what you need, in Paint event based on some logic, then each time the control refreshes, your paint logic will apply and the drawing will show on your control.

For example when you want to draw a rectangle in your MouseMove event, its enough to store the rectangle in a class member variable, and call yourControl.Invalidate(); and then use the rectangle in the Paint event handler and draw it. Invalidate makes the control redraw, so your painting logic will run.

Yes, you can use Graphics outside of your Paint/PaintBackground events, but you shouldn't need to, nor is it advised.

My guess is (given that you referenced MouseMove ) that you want some painting to occur when particular events occur on the control; there are a couple of solutions to this:

  • Subclassing (greater control over your component, control reuse etc)
  • Registering event handlers (good for quick and dirty implementation)

Example 1 - registering event handlers

private void panel1_MouseMove(object sender, EventArgs e)
{
    // forces paint event to fire for entire control surface    
    panel1.Refresh();
}

private void panel1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.....;
}

Example 2 - subclassing

class CustomControl : Control
{
    public CustomControl()
    {
        SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintInWmPaint | ControlStyles.ResizeRedraw | ControlStyles.OptimizedDoubleBuffer, true);
        UpdateStyles();
    }

    protected override void OnMouseMove(EventArgs e)
    {
        base.OnMouseMove(e);
        Refresh();
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        e.Graphics...;
    }
}

Notes

  1. Once OnPaint/Paint has been called, e.Graphics will be disposed, therefore, setting a global reference to that object will be useless since it will be null once your Paint event has completed.
  2. You can use CreateGraphics() if you absolutely need Graphics outside of your Paint/PaintBackground methods/events, but this isn't advised.
  3. Paint/PaintBackground fall naturally into the WinForms event/rendering pipeline, so you should ideally override these and use them appropriately.

If you want repaint panel on MouseMove event, call the Invalidate() method and do the draw logic on Paint event.

The Invalidate() method marks the panel "dirty" and the painting will be caused from winforms message-loop.

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