2010-10-30 8 views
8

Ich bin nicht ganz sicher, wie ein Rectangle zeichnen (nicht gefüllt), wenn ich meine Maus nach unten ziehen, während Sie mit der linken Maustaste klicken.Wie zeichne Rechteck auf MouseDown/Move C#

Ich habe dies bisher

  private void canevas_MouseDown(object sender , MouseEventArgs e) 
      { 
        if(e.Button == MouseButtons.Left) 
        { 
          _topLeft = new Point(e.X , e.Y); 
          _drawing = true; 
        } 
      } 

      private void canevas_MouseMove(object sender , MouseEventArgs e) 
      { 
        if(_drawing) 
        { 
          Rectangle rec = new Rectangle(_topLeft.X , _topLeft.Y , (e.X - _topLeft.X) , (e.Y - _topLeft.Y)); 
          canevas.CreateGraphics().DrawRectangle(Pens.Black , rec); 
        } 
      } 

Aber die Probleme, die es, dass ich nicht wollen, alle Rechtecke

Antwort

19

Einige Codes mit Eds richtigen Antwort zu gehen:

Point startPos;  // mouse-down position 
    Point currentPos; // current mouse position 
    bool drawing;  // busy drawing 
    List<Rectangle> rectangles = new List<Rectangle>(); // previous rectangles 

    private Rectangle getRectangle() { 
     return new Rectangle(
      Math.Min(startPos.X, currentPos.X), 
      Math.Min(startPos.Y, currentPos.Y), 
      Math.Abs(startPos.X - currentPos.X), 
      Math.Abs(startPos.Y - currentPos.Y)); 
    } 

    private void canevas_MouseDown(object sender, MouseEventArgs e) { 
     currentPos = startPos = e.Location; 
     drawing = true; 
    } 

    private void canevas_MouseMove(object sender, MouseEventArgs e) { 
     currentPos = e.Location; 
     if (drawing) canevas.Invalidate(); 
    } 

    private void canevas_MouseUp(object sender, MouseEventArgs e) { 
     if (drawing) { 
      drawing = false; 
      var rc = getRectangle(); 
      if (rc.Width > 0 && rc.Height > 0) rectangles.Add(rc); 
      canevas.Invalidate(); 
     } 
    } 

    private void canevas_Paint(object sender, PaintEventArgs e) { 
     if (rectangles.Count > 0) e.Graphics.DrawRectangles(Pens.Black, rectangles.ToArray()); 
     if (drawing) e.Graphics.DrawRectangle(Pens.Red, getRectangle()); 
    } 

ein 'canevas' zu erhalten, die auf Double-Buffering gedreht hat , damit es nicht flackert, verwenden Sie Projekt + Neues Element hinzufügen, wählen Sie "Klasse" und fügen Sie diesen Code ein:

using System; 
using System.Windows.Forms; 

class Canvas : Panel { 
    public Canvas() { 
     this.DoubleBuffered = true; 
     this.SetStyle(ControlStyles.ResizeRedraw, true); 
    } 
} 

Kompilieren. Ziehen Sie das neue Steuerelement von der Oberseite der Toolbox auf Ihr Formular und ersetzen Sie die ursprünglichen "Canevas". Aktualisieren Sie die Ereignishandler entsprechend.

+1

danke, ich hatte es richtig aber es hat mir mit dem rückgängig gemachten ziehen geholfen. :) – Burnzy

+0

Alles scheint soweit in Ordnung, außer dem Flackern, irgendwelche Ideen? – Burnzy

+0

Ich habe einen Kommentar hinterlassen, verwenden Sie e.Graphics im Paint-Event? Ich habe diesen Code getestet, er ist auch ohne Doppelpufferung flimmerfrei. –

5

zu zeigen, nicht Create rufen Sie. Speichern Sie in MouseDown die Startposition und ein Flag, um anzuzeigen, dass Sie zeichnen. In MouseMove, überprüfen Sie die Flagge. Wenn Sie zeichnen, erstellen Sie das Rechteck relativ zur Startposition und speichern Sie es (was Sie bereits tun), und rufen Sie dann Invalidate() auf. Ihr gesamter Zeichencode wird in OnPaint() (canvas.Paint von außerhalb der Klasse sein, obwohl ich wahrscheinlich meine eigene Klasse dafür erstellen würde, um zu vermeiden, dass Ihr Formularcode mit diesem Zeug übersät ist).

Die Zeichnung sollte in Ihrem Farbroller (OnPaint) erstellt werden. Wenn Sie darüber hinaus zeichnen, wird Ihr Grafikobjekt nicht gelöscht (daher die mehreren Rechtecke) und alles, was Sie zeichnen, kann/wird zu scheinbar ungleichen Zeiten gelöscht, wenn Ihr Fenster eine WM_PAINT-Nachricht erhält.

EDIT: Jetzt, da Sie Leistungsprobleme haben, gibt es ein paar einfache Möglichkeiten, um die Malerei ein wenig zu optimieren. Zuerst nimmt Invalidate optional ein Rectangle als Argument, sodass Sie das gesamte Steuerelement nicht neu streichen müssen. Zweitens, wenn Sie auf MouseMove zeichnen, werden Sie ziemlich viel zeichnen. Die Verwendung der doppelten Pufferung wird ebenfalls sehr hilfreich sein. Setzen Sie einfach die DoubleBuffered-Eigenschaft auf true oder fügen Sie sie dem ControlStyles-Wert hinzu, indem Sie SetStyle für das Steuerelement aufrufen.

+0

BTW, ich bin mir nicht ganz sicher, was ungültig ist für – Burnzy

+0

@Burnzy, Invalidate innvalidates die Grafiken des Steuerelements, so dass die Paint-Operation erneut von Windows aufgerufen wird. (Im Grunde, sobald das Steuerelement ungültig ist, muss es sich neu zeichnen) –

+0

eine Idee, wie das Flimmern Problem beheben? – Burnzy

0

Okay jetzt habe ich das, es funktioniert aber es flackert viel, sogar mit Doppelpufferung.

  private void canevas_MouseDown(object sender , MouseEventArgs e) 
      { 
        _topLeft = new Point(e.X , e.Y); 
        if(e.Button == MouseButtons.Left) 
        { 
          _topLeft = new Point(e.X , e.Y); 
          _drawing = true; 
        } 
      } 

      private void canevas_MouseUp(object sender , MouseEventArgs e) 
      { 
        _drawing = false; 
        _bottomRight = new Point(e.X , e.Y); 
        int newX = _topLeft.X - (_bottomRight.X - _topLeft.X)/2; 
        int newY =_topLeft.Y + (_bottomRight.Y - _topLeft.Y)/2; 
        MouseEventArgs me = new MouseEventArgs(MouseButtons.Left , 1 , newX , newY , 0); 

        canevas_MouseClick(canevas , me); 
      } 

      private void canevas_MouseMove(object sender , MouseEventArgs e) 
      { 
        if(_drawing) 
        { 
          _bottomRight = new Point(e.X , e.Y); 
          canevas.Invalidate(); 
        } 
      } 

Und dann auf Farbe

  private void canevas_Paint(object sender , PaintEventArgs e) 
      { 
        Graphics g = canevas.CreateGraphics(); 
        g.DrawImage(_buffer , new Rectangle(0 , 0 , canevas.Width , canevas.Height)); 
        g.DrawRectangle(Pens.White , new Rectangle(_topLeft.X , _topLeft.Y , (_bottomRight.X - _topLeft.X) , (_bottomRight.Y - _topLeft.Y))); 
      } 
+2

* Verwenden Sie nicht CreateGraphics(). Verwenden Sie e.Graphics im Paint-Ereignis. –

0
public Form1() 
    { 
     InitializeComponent(); 
     // Use the cross "+" cursor 
     this.Cursor = System.Windows.Forms.Cursors.Cross; 
     // This will reduce flicker (Recommended) 
     this.DoubleBuffered = true; 
    } 

Fügen Sie diesen Code zu Ihrem Formular hinzu. Dies kann das Flackern reduzieren!