我可以在“绘制”事件之外的任何其他事件中使用Graphics对象吗
本文关键字:事件 其他 对象 Graphics 任何 绘制 我可以 | 更新日期: 2023-09-27 18:22:17
我有一个带有停靠面板的WinForm。我否决了Panel的Paint事件。我有一行设置图形对象(_G):
private Graphics _graphics;
在覆盖中,我初始化图形对象(_G):
private void GridPanel_Paint(object sender, PaintEventArgs e)
{
_graphics = e.Graphics;
<snip>
…
</snip>
}
愚蠢的部分来了,我可以在像MouseMove这样的任何其他事件中使用这个_graphics对象吗?
这取决于你所说的"使用"是什么意思。
Graphics
是一次性的。重新绘制后,控件将处理传递给Paint
事件处理程序的Graphics
实例。从这一点来看,已处理的对象是无用的。但是缓存对该实例的引用是绝对合法的。
是的,您可以在Paint/PaintBackground
事件之外使用Graphics,但您不应该这样做,也不建议这样做。
我的猜测是(假设您引用了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...;
}
}
票据
- 调用
OnPaint/Paint
后,e。图形将被释放,因此,设置对该对象的全局引用将是无用的,因为一旦绘制事件完成,它将是null
- 如果在
Paint/PaintBackground
方法/事件之外绝对需要Graphics
,则可以使用CreateGraphics()
,但不建议这样做 Paint/PaintBackground
自然地属于WinForms事件/呈现管道,因此理想情况下应该覆盖它们并适当地使用它们
如果您想在MouseMove事件上重新绘制面板,请调用Invalidate()
方法并在Paint
事件上执行绘制逻辑。
Invalidate()
方法将面板标记为"脏",并且绘画将由winforms消息循环引起。
您可以使用CreateGraphics
方法在需要的地方使用控件的图形对象,但当控件刷新时,您的绘画将消失。
因此在Paint
事件中,最好根据某些逻辑绘制您需要的内容,然后每次刷新控件时,您的绘制逻辑都会应用,并且绘图将显示在控件上。
例如当您想在MouseMove
事件中绘制矩形时,只需将矩形存储在类成员变量中,然后调用yourControl.Invalidate();
,然后在Paint
事件处理程序中使用矩形并绘制即可。Invalidate
会重新绘制控件,因此绘制逻辑将运行。