想要在C#中使用绘制的圆圈跟随我的鼠标

首先,我是C#的真正开始,所以请温柔。

我正试图跟着我的光标圈。 我不希望任何“小道”落在后面。

private void Form1_MouseMove(object sender, MouseEventArgs e) { drawCircle(eX, eY); } private void drawCircle(int x, int y) { Pen skyBluePen = new Pen(Brushes.DeepSkyBlue); Graphics graphics = CreateGraphics(); graphics.DrawEllipse( skyBluePen, x - 150, y - 150, 300, 300); graphics.Dispose(); this.Invalidate(); } 

这样可以正常工作,因为它绘制它并以鼠标为中心进行每次鼠标移动。 但是,“this.Invalidate();” 是错的。 它在每次运动后“展开”形状,所以我只能看到它的一瞥。 但是,不包括它会导致每个绘制的圆圈保留在屏幕上。

我如何让一个圆圈“优雅地”跟随我的鼠标,而不是太过jump and而且没有保留所有过去的圆圈?

你可以这样做:

 public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Paint(object sender, PaintEventArgs e) { Point local = this.PointToClient(Cursor.Position); e.Graphics.DrawEllipse(Pens.Red, local.X-25, local.Y-25, 20, 20); } private void Form1_MouseMove(object sender, MouseEventArgs e) { Invalidate(); } } 

基本上,在鼠标移动时,无效。 在画上,画出你的圆圈。

这工作 – 只是测试它…

 private int x = 0; private int y = 0; private void Form1_MouseMove(object sender, MouseEventArgs e) { x = eX; y = eY; this.Invalidate(); } private void Form1_Paint(object sender, PaintEventArgs e) { Pen skyBluePen = new Pen(Brushes.DeepSkyBlue); e.Graphics.DrawEllipse(skyBluePen, x - 150, y - 150, 300, 300); } 

在绘制圆圈之前,您需要使表单无效。

我很肯定有更多有效的方法可以使用双缓冲来实现这一点,但我没有一个例子。

您通常不希望在绘制处理程序之外执行任何绘制,因为每当绘制处理程序执行时(可能在任何时间)它将覆盖您所做的任何事情。

最终你需要考虑很多事情(比如当鼠标移出你的表格时会发生什么,但这应该让你开始。

 using System; using System.Drawing; using System.Windows.Forms; class C:Form { static void Main(){Application.Run(new C());} private Point? _MousePosition = null; protected override void OnMouseMove(MouseEventArgs e) { _MousePosition = e.Location; this.Invalidate(); } protected override void OnPaint(PaintEventArgs e) { if(_MousePosition.HasValue) { using(Pen skyBluePen = new Pen(Brushes.DeepSkyBlue)) { e.Graphics.DrawEllipse(skyBluePen, _MousePosition.Value.X - 150, _MousePosition.Value.Y - 150, 300, 300); } } } } 

尝试在Form构造函数中添加以下行:

 this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); this.SetStyle(ControlStyles.UserPaint, true); 

这将告诉表单只有在您告诉它时才会重新绘制。 它还将提供双缓冲。 祝好运!

绘制快速变化的东西的最佳方法是使用称为双缓冲的概念。 这样做很容易,你不必依赖双缓冲标志。 自己动手为您提供完全的自由和控制。

基本上,您不是在Form本身上绘图,而是在屏幕外的Bitmap上完成所有绘图。 您只有在知道某些内容发生变化时才会绘制(在您的情况下,在鼠标移动事件中)。 只有在您知道必须时(在鼠标移动之后或者引发Paint事件时),您才会在屏幕上绘图。

 private void DrawScene(Point mouseLocation) { myGraphics.Clear(Color.White) myGraphics.DrawEllipse(skyBluePen, mouseLocation.X - 150, mouseLocation.Y - 150, 300, 300); myDrawingSurface.Refresh(); //myDrawingSurface can be a Form or a PictureBox or whatever you'd like. Normally, you'd only Invalidate areas that have changed } private void myDrawingSurface_MouseMove(object sender, MouseEventArgs e) { DrawScene(e.Location); } private void myDrawingSurface_Paint(object sender, PaintEventArgs e) { e.Graphics.DrawImage(myBitmap, 0, 0); //Can't remember the exact signature } 

另一种“作弊”方式是简单地将PictureBox的Image属性分配给您正在绘制的图像,并在PictureBox上调用Refresh。 它将处理在屏幕上绘制图像。 不需要Paint处理程序。

注意。 您需要声明myBitmap和myGraphics一次。 当绘图表面改变大小时,必须以适当的大小重新创建位图。 另外,不要一遍又一遍地重新声明笔和其他图形对象。 它们应该在程序启动时声明一次。 并在程序关闭时正确处理它们。