C#绘画处理程序中的绘图问题 [英] C# Problem with drawing in Paint handler
问题描述
我试图在我的C#Windows Form应用程序中使用DrawString.在程序启动时,将触发三个绘画事件.在第一个事件中,字符串将以正确的位置写在表单上.在第二次和第三次绘画事件中,字符串写在正确位置的上方和左侧.
之后,程序将按预期运行. (先最小然后再最大,或者重新调整表单大小,然后正确绘制屏幕.)
DrawLine,DrawRectangle等会发生这种情况.
这是C#的错误,还是我很明显地遗漏了一些东西?这是整个应用程序.感谢您的帮助.
I am trying to use DrawString in my C# Windows Form application. On program startup, three paint events are fired. On the first event, the string is written on the form in the correct position. On the 2nd and 3rd paint events, the string is written above and to the left of the correct position.
After that, the program runs as expected. (Min and then max, or resize the form and the screen is drawn correctly.)
This happens with DrawLine, DrawRectangle, etc.
Is this a bug with C# or am I missing something VERY obvious? Here''s the WHOLE application. Thanks for any help you can give.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Junk
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
System.Drawing.Graphics graphicsObj;
graphicsObj = this.CreateGraphics();
Font myFont = new System.Drawing.Font("Helvetica", 40, FontStyle.Italic);
Brush myBrush = new SolidBrush(System.Drawing.Color.Red);
graphicsObj.DrawString("Hello C#", myFont, myBrush, 30, 100);
}
}
}
推荐答案
这不是整个应用程序.您如何知道Form1_Paint
是添加到事件Paint
的调用列表中的处理程序.依靠设计师?在许多情况下,Designer只会使开发变慢.
您已经有了Form
类,为什么还要处理该事件?只是覆盖OnPaint
会做完全相同的事情.现在,错误在哪里?这是使用其构造函数创建System.Drawing.Graphics
实例的过程.您应该使用已经在Paint
或OnPaint
的处理程序方法中传递给您的实例.它在事件参数parameter中传递.
更多错误:Font
和Brush
未处理,因此您将有永久性的非托管资源泄漏.这很重要,因此它也应该处理可能的异常.通常,它是使用try-finally完成的,但是等效行为是使用using
语句实现的(不要与using
子句混淆,请参阅http://msdn.microsoft.com/en-us/library/yh598w02.aspx [
This is not a whole application. How do you know thatForm1_Paint
is a handler added to an invocation list of the eventPaint
. Relying on the Designer? There are many cases when the Designer only makes development slower.
As you already have yourForm
class, why handling the event at all? Just overridingOnPaint
does exact same thing. Now, where is the mistake? This is creation of the instance ofSystem.Drawing.Graphics
using its constructor. You should use the instance which is already passed to you in the handler method ofPaint
orOnPaint
; it is passed in event arguments parameter.
More mistakes:Font
andBrush
are not disposed, so you will have a permanent unmanaged resource leak. This is important enough, so it should also handle possible exceptions. Normally, it is done using try-finally, but the equivalent behavior is achieved usingusing
statement (not to by confused withusing
clause, see http://msdn.microsoft.com/en-us/library/yh598w02.aspx[^]).
Also, there is not need to create a solid brush of an well-known color.
After all fixes:
protected override void OnPaint(PaintEventArgs eventArgs) {
using (Font myFont = new System.Drawing.Font("Helvetica", 40, FontStyle.Italic)) {
e.Graphics.DrawString("Hello C#", myFont, System.Drawing.Brushes.Red, 30, 100);
} //myFont is automatically disposed here, even if an exception was thrown
}
如果需要移动图形并更改OnPaint
使用的数据,则需要调用Control.Invalidate
.您可以尝试使用带有参数(Region
或Rectange
)的Control.Invalidate
来仅刷新场景的一部分来提高性能.
另请参阅我过去的答案:
Paint是一种哪种好玩的方法? (DataGridViewImageCell.Paint(...)) [在mdi子窗体之间画线 [在面板上捕获图形 [如何从旧图纸中清除面板 [ ^ ](这有助于防止常见的PictureBox
滥用).
If you need graphics to move, and change data used by OnPaint
, you need to call Control.Invalidate
. You can try to improve performance using Control.Invalidate
with parameters (Region
or Rectange
) to refresh only the part of the scene.
See also my past answers:
What kind of playful method is Paint? (DataGridViewImageCell.Paint(...))[^],
Drawing Lines between mdi child forms[^],
capture the drawing on a panel[^],
How do I clear a panel from old drawing[^] (this one helps to prevent the very common abuse of PictureBox
).
这篇关于C#绘画处理程序中的绘图问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!