【问题标题】:How to draw rectangle on MouseDown/Move c#如何在 MouseDown/Move c# 上绘制矩形
【发布时间】:2010-10-30 20:04:07
【问题描述】:

当我在左键单击鼠标的同时向下拖动鼠标时,我不太确定如何绘制矩形(未填充)。

到目前为止我有这个

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

但问题是我不希望所有的矩形都显示出来

【问题讨论】:

    标签: c# drawing draw


    【解决方案1】:

    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”。相应地更新事件处理程序。

    【讨论】:

    • 谢谢,我做对了,但它帮助我恢复了拖动。 :)
    • 到目前为止一切正常,除了闪烁,有什么想法吗?
    • 我发表了评论,您在 Paint 事件中使用 e.Graphics 吗?我测试了这段代码,即使没有双缓冲也没有闪烁。
    • 是的,但是,闪烁可能取决于背景。如果它是灰色的,它不会闪烁,否则它会闪烁。编辑 nvm,即使背景很简单,它仍然会闪烁
    • 什么是“玩灰色”?背景是什么?
    【解决方案2】:

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

    绘图应在您的绘图处理程序 (OnPaint) 中完成。如果您在此范围之外绘制,则您的图形对象不会被清除(因此有多个矩形),并且当您的窗口收到 WM_PAINT 消息时,您绘制到它的任何东西都可能/将会在看似奇怪的时间被清除。

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

    【讨论】:

    • 顺便说一句,我不太确定什么是无效的
    • @Burnzy,Invalidate 使控件的图形无效,以便窗口再次调用绘制操作。 (基本上一旦控件失效,它就需要重绘自己)
    • 知道如何解决闪烁问题吗?
    • 我添加了一些提示。还要意识到,如果你确实调用了 CreateGraphics(无论如何你不应该在这里这样做),你也应该在返回的 Graphics 对象上调用 Dispose()。
    • 感谢您的提示,但我为什么要这样做?
    【解决方案3】:

    现在我有了这个,它可以工作了,但是它经常闪烁,即使是双缓冲。

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

    【讨论】:

    • 不要使用 CreateGraphics()。在 Paint 事件中使用 e.Graphics。
    【解决方案4】:
        public Form1()
        {
            InitializeComponent();
            // Use the cross "+" cursor
            this.Cursor = System.Windows.Forms.Cursors.Cross;
            // This will reduce flicker (Recommended)
            this.DoubleBuffered = true;
        }
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-03-31
      • 1970-01-01
      • 1970-01-01
      • 2019-03-11
      • 2021-11-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多