如何在MouseDown / Move c#上绘制矩形

时间:2010-10-30 20:04:07

标签: c# drawing draw

当我在左键单击鼠标时拖动我的mousedown时,我不太确定如何绘制一个Rectangle(未填充)。

到目前为止我有这个

            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 个答案:

答案 0 :(得分:20)

一些代码与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());
    }

要获得打开双缓冲的'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);
    }
}

编译。将新控件从工具箱顶部拖到窗体上,替换原始的“canevas”。相应地更新事件处理程序。

答案 1 :(得分:5)

不要调用CreateGraphics。在MouseDown中,存储起始位置和一个标志以指示您正在绘制。在MouseMove中,检查标志。如果要绘图,请相对于起始位置创建矩形并将其存储(您已经在进行),然后调用Invalidate()。你的所有绘图代码都将在OnPaint()中(canvas.Paint来自类外部,但我可能会为此创建自己的类,以避免乱丢你的表单代码)。

绘图应该在您的绘图处理程序(OnPaint)中完成。如果你在那之外绘制,你的图形对象不会被清除(因此多个矩形),当你的窗口收到一个WM_PAINT消息时,你在它上面绘制的任何东西都会被看似奇怪的时候消灭掉。

编辑:既然你遇到了性能问题,可以通过几种简单的方法来优化绘画。首先,Invalidate可选择将Rectangle作为其参数,这样您就不必重新绘制整个控件。其次,如果你正在使用MouseMove,那么你将会画出相当多的东西。使用双缓冲也会有很多帮助,只需将DoubleBuffered属性设置为true,或者通过调用控件上的SetStyle将其添加到ControlStyles值。

答案 2 :(得分:0)

好吧,现在我有了这个,它的工作但是,它闪烁很多,即使是双缓冲。

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

答案 3 :(得分:0)

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

将此代码添加到您的表单中。这可能会减少闪烁!