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

时间:2009-07-16 20:25:05

标签: c# winforms

首先,我是C#真正的初学者,所以请保持温和。

我正试图跟着我的光标圈。我不希望留下任何“痕迹”。

private void Form1_MouseMove(object sender, MouseEventArgs e)
{

    drawCircle(e.X, e.Y);

}

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而且没有保留过去所有的圆圈?

6 个答案:

答案 0 :(得分:13)

您可以这样做:

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();
    }
}

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

答案 1 :(得分:3)

这很有效 - 只是测试了它......

private int x = 0;
private int y = 0;

private void Form1_MouseMove(object sender, MouseEventArgs e)
{
    x = e.X;
    y = e.Y;

    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);

}

答案 2 :(得分:1)

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

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

答案 3 :(得分:1)

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

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

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

答案 4 :(得分:1)

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

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

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

答案 5 :(得分:0)

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

基本上,您不是在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。它将处理在屏幕上绘制图像。不需要油漆处理程序。

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