2010-10-30 7 views
8

Je ne suis pas sûr de savoir comment dessiner un Rectangle (non rempli) quand je fais glisser mon mousedown tout en faisant un clic gauche sur la souris.Comment dessiner un rectangle sur MouseDown/Move C#

J'ai ce jusqu'à

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

Mais les problèmes-ce que je ne veux pas que tous les rectangles apparaissent

Répondre

19

code pour aller avec la réponse correcte Ed:

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

Pour obtenir un 'Canevas' qui a une double mémoire tampon sous tension , donc la peinture ne scintille pas, utilisez Projet + Ajouter un nouvel élément, sélectionnez "Classe" et collez ce code:

using System; 
using System.Windows.Forms; 

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

Compile. Faites glisser le nouveau contrôle depuis le haut de la boîte à outils sur votre formulaire, en remplaçant les canevas d'origine. Mettez à jour les gestionnaires d'événements en conséquence.

+1

merci, je l'ai eu correctement mais ça m'a aidé avec la traînée inversée. :) – Burnzy

+0

Tout semble ok jusqu'ici, sauf le scintillement, des idées? – Burnzy

+0

J'ai laissé un commentaire, utilisez-vous e.Graphics dans l'événement Paint? J'ai testé ce code, il est sans scintillement même sans double tampon. –

5

Ne pas appeler CreateGraphics. Dans MouseDown, stockez la position de départ et un drapeau pour indiquer que vous dessinez. Dans MouseMove, vérifiez le drapeau. Si vous dessinez, créez le rectangle par rapport à la position de départ et stockez-le (ce que vous faites déjà), puis appelez Invalidate(). Tout votre code de dessin sera dans OnPaint() (canvas.Paint de l'extérieur de la classe, bien que je créerais probablement ma propre classe pour éviter que votre code de formulaire ne soit détruit).

Le dessin doit être fait dans votre manipulateur de peinture (OnPaint). Si vous dessinez en dehors de cela, votre objet graphique n'est pas effacé (d'où les multiples rectangles) et tout ce que vous y dessinez peut/sera effacé à des moments apparemment bizarres lorsque votre fenêtre reçoit un message WM_PAINT.

EDIT: Maintenant que vous rencontrez des problèmes de performances, il existe quelques façons simples d'optimiser un peu la peinture. Tout d'abord, Invalidate prendra éventuellement un Rectangle comme argument afin que vous n'ayez pas à repeindre le contrôle entier. Deuxièmement, si vous dessinez sur MouseMove, vous allez dessiner un peu. L'utilisation de la double mise en mémoire tampon sera également très utile. Il suffit de définir la propriété DoubleBuffered sur true ou de l'ajouter à la valeur ControlStyles en appelant SetStyle sur le contrôle.

+0

btw, je ne suis pas sûr de ce qui est invalider pour – Burnzy

+0

@Burnzy, Invalidate innvalide les graphiques du contrôle de sorte que l'opération de peinture est invoquée à nouveau par Windows. (Fondamentalement, une fois le contrôle invalidé, il doit se redessiner) –

+0

une idée de comment résoudre le problème de scintillement? – Burnzy

0

Très bien maintenant j'ai ceci, son fonctionnement mais, il scintille beaucoup, même avec un double tampon.

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

Et puis sur la peinture

  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

* N'utilisez pas * CreateGraphics(). Utilisez e.Graphics dans l'événement Paint. –

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

Ajoutez ce code à votre formulaire. Ceci peut réduire le scintillement!

Questions connexes