首先,我是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而且没有保留过去所有的圆圈?
答案 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 一遍又一遍地重新声明钢笔和其他图形对象。它们应该在程序启动时声明一次。并在程序结束时正确处理它们。