2009-07-16 26 views
3

首先,我是一个真正的开始在C#所以请温柔。想要一个绘制的圆圈跟随我的鼠标在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();”是错的。它在每次运动之后都会“解开”形状,所以我只能看到它的一瞥。但是,不包括它会导致每个绘制的圆圈都保留在屏幕上。

我该如何获得一个圆圈,以“优雅地”跟随我的鼠标周围,而不会太过激动,并且不会保留所有过去的圆圈?

回答

14

你可以做这样的事情:

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

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

+2

您可以添加“this.DoubleBuffered = true;”作为ctor的一部分,它也可能有助于一些闪烁。 – 2009-07-16 20:42:51

+0

这就是我需要的一切吗?我粘贴了它,它实际上并没有做任何事情,当我跑,除了调出窗体/窗口... – cksubs 2009-07-16 20:53:40

1

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

我确信有更高效的方式来使用双缓冲来做到这一点,但是我没有一个例子来说明我的头脑。

+0

没有什么区别。提供相同的闪烁效果。 – 2009-07-16 20:33:56

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

} 
0

画的东西,变化快,最好的方法是使用被称为双缓冲的概念。这真的很容易做到的自己,你不必依靠双缓冲标志自己动手给你完全的自由和控制,

基本上,而不是在窗体本身上绘图,而是在离屏位图上执行所有绘图。只有当你知道某些东西已经改变时(在你的情况下,在鼠标移动事件上),你才会绘制。只有当您知道必须(在鼠标移动或引发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 
} 

这样做是简单地一个图片的图片属性分配给您绘制的图像,并调用刷新的图片框的另一种“欺骗”的方式。它会处理你的屏幕上的图像。不需要Paint处理程序。

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

1

尝试添加以下行表单中的构造函数:

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

这将告诉表单只当你告诉它这样做重绘。它也将提供双缓冲。祝你好运!