Хотите нарисованный круг, чтобы следовать за моей мышью в C # - PullRequest
4 голосов
/ 17 июля 2009

Прежде всего, я настоящий новичок в 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 ();" неправильно. Он «растягивает» форму после каждого движения, так что я могу видеть только его проблески. Однако, не считая его, каждый нарисованный круг остается на экране.

Как мне заставить один круг "изящно" следовать за моей мышью, не слишком нервничая и не сохраняя все предыдущие круги?

Ответы [ 6 ]

14 голосов
/ 17 июля 2009

Вы можете сделать что-то вроде этого:

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

В основном, при перемещении мыши, сделать недействительным. На краске нарисуй свой круг.

3 голосов
/ 17 июля 2009

Это работает - только что проверил ...

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

}
1 голос
/ 17 июля 2009

Попробуйте добавить следующие строки в конструкторе форм:

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

Это скажет Форме перекрасить только тогда, когда вы скажете это сделать. Это также обеспечит двойную буферизацию. Удачи!

1 голос
/ 17 июля 2009

Обычно вы не хотите рисовать вне обработчика рисования, потому что всякий раз, когда обработчик рисования выполняется (что может быть в любое время), он будет перезаписывать все, что вы делали.

Есть куча вещей, о которых вам в конечном итоге придется подумать (например, то, что происходит, когда мышь выходит за пределы вашей формы, но это должно помочь вам начать работу.

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);
  }
 }
}
}
1 голос
/ 17 июля 2009

Вам нужно сделать форму недействительной ДО ТОГО, как вы нарисуете свой круг.

Я уверен, что есть более эффективные способы сделать это, используя двойную буферизацию, но у меня нет примера с головы до головы.

0 голосов
/ 17 июля 2009

Лучший способ нарисовать что-то быстро меняющееся - использовать концепцию, известную как двойная буферизация. Это действительно легко сделать самостоятельно, и вам не нужно полагаться на флаг двойной буферизации. Делая это самостоятельно, вы получаете полную свободу и контроль.

По сути, вместо того, чтобы рисовать на самой Форме, вы делаете все свои рисунки на закадровом растровом изображении. Вы рисуете только тогда, когда знаете, что что-то изменилось (в вашем случае это событие перемещения мыши). Вы рисуете на экране только тогда, когда знаете, что это нужно (после перемещения мыши или когда возникает событие 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 для изображения, на котором вы рисуете, и вызвать команду «Обновить» в PictureBox. Он будет обрабатывать рисование своего изображения на экране для вас. Обработчик рисования не требуется.

Примечание. Вам нужно объявить myBitmap и myGraphics один раз. Растровое изображение должно быть воссоздано в соответствующем размере, когда поверхность чертежа изменит размер. Кроме того, НЕ продолжайте повторно объявлять перья и другие графические объекты снова и снова. Они должны быть объявлены один раз, когда ваша программа запускается. И утилизируйте их правильно, когда ваша программа закрывается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...