Как нарисовать прямоугольник на MouseDown / Move c # - PullRequest
9 голосов
/ 31 октября 2010

Я не совсем уверен, как нарисовать прямоугольник (не заполненный), когда я перетаскиваю мой мусс, когда щелкаю левой кнопкой мыши.

Пока у меня есть это

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

Нопроблемы в том, что я не хочу, чтобы все прямоугольники показывались

Ответы [ 4 ]

20 голосов
/ 31 октября 2010

Код для правильного ответа Эда:

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

Чтобы получить 'canevas' с включенной двойной буферизацией, чтобы рисование не мерцало, используйте Project + Add New Item, выберите «Class» и вставьте этот код:

using System;
using System.Windows.Forms;

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

Compile. Перетащите новый элемент управления из верхней части панели инструментов на форму, заменив оригинальные «canevas». Обновите обработчики событий соответственно.

5 голосов
/ 31 октября 2010

Не вызывайте CreateGraphics. В MouseDown сохраните начальную позицию и флаг, чтобы указать, что вы рисуете. В MouseMove проверьте флаг. Если вы рисуете, создайте прямоугольник относительно начальной позиции и сохраните его (что вы уже делаете), а затем вызовите Invalidate (). Весь ваш код для рисования будет в OnPaint () (canvas.Paint вне класса, хотя я бы, вероятно, создал свой собственный класс для этого, чтобы не засорять ваш код формы этим материалом).

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

РЕДАКТИРОВАТЬ: Теперь, когда у вас проблемы с производительностью, есть несколько простых способов немного оптимизировать рисование. Во-первых, Invalidate может принять Rectangle в качестве аргумента, чтобы вам не пришлось перекрашивать весь элемент управления. Во-вторых, если вы рисуете в MouseMove, вы будете рисовать совсем немного. Использование двойной буферизации также очень поможет, просто установите для свойства DoubleBuffered значение true или добавьте его к значению ControlStyles, вызвав SetStyle для элемента управления.

0 голосов
/ 17 июня 2011
    public Form1()
    {
        InitializeComponent();
        // Use the cross "+" cursor
        this.Cursor = System.Windows.Forms.Cursors.Cross;
        // This will reduce flicker (Recommended)
        this.DoubleBuffered = true;
    }

Добавьте этот код в форму. Это может уменьшить мерцание!

0 голосов
/ 31 октября 2010

Хорошо, теперь у меня есть это, оно работает, но оно много мигает, даже с двойной буферизацией.

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

А потом по краске

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