我可以在除Paint事件之外的任何其他事件中使用Graphics对象吗?

时间:2015-11-17 14:21:00

标签: c# winforms gdi+

我有一个带有停靠面板的WinForm。 我超越了Panel的Paint事件。 我有一行设置_graphics对象:

private Graphics _graphics;

在覆盖中我初始化_graphics对象:

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

    <snip>
    …
    </snip>
}

这是愚蠢的部分,我可以在MouseMove等任何其他事件中使用这个_graphics对象吗?

4 个答案:

答案 0 :(得分:3)

这取决于“使用”是什么意思。

Graphics是一次性的。重新绘制后,控件处理Graphics实例,该实例已传递到Paint事件处理程序。从那时起,处置对象就没用了。但是缓存对该实例的引用是绝对合法的。

答案 1 :(得分:1)

您可以使用CreateGraphics方法使用控件的图形对象,当控件刷新时,您的绘画将消失。

所以最好根据某些逻辑在Paint事件中绘制您需要的内容,然后每次控件刷新时,您的绘制逻辑都将应用,并且绘图将显示在您的控制。

例如当你想在MouseMove事件中绘制一个矩形时,它足以将矩形存储在一个类成员变量中,并调用yourControl.Invalidate();然后使用Paint事件处理程序中的矩形并绘制它。 Invalidate使控件重绘,因此您的绘画逻辑将会运行。

答案 2 :(得分:1)

是的,你可以在Paint/PaintBackground事件之外使用图形,但你不应该也不需要它。

我的猜测是(假设你引用了MouseMove)你希望在控件上发生特定事件时发生一些绘画;有几个解决方案:

  • 子类化(对组件的更大控制,控制重用等)
  • 注册事件处理程序(适用于快速和脏的实现)

示例1 - 注册事件处理程序

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.....;
}

示例2 - 继承

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...;
    }
}

备注

  1. 一旦调用了OnPaint/Paint,就会处理e.Graphics,因此,设置对该对象的全局引用将毫无用处,因为一旦Paint事件完成,它将为null
  2. 如果您在CreateGraphics()方法/事件之外绝对需要Graphics,则可以使用Paint/PaintBackground,但不建议这样做。
  3. Paint/PaintBackground自然会落入WinForms事件/渲染管道中,因此理想情况下应覆盖这些并适当地使用它们。

答案 3 :(得分:1)

如果您想在MouseMove事件上重新绘制面板,请调用Invalidate()方法并在Paint事件上执行绘制逻辑。

Invalidate()方法将面板标记为“脏”,并且绘制将由winforms消息循环引起。