在面板中通过鼠标绘制线条

时间:2014-02-04 21:20:41

标签: c# winforms drawing panel

我想通过鼠标绘制一条线(交互式),我使用C#和WinForm,该线应该在任何时候从起点(当鼠标按在面板上时)到鼠标的当前位置时出现比如在画图程序中画一条线。

但代码产生了很多行,我知道为什么,但我不知道如何克服这个问题

enter image description here

这是我的代码:

namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    Graphics g;
    Pen myPen = new Pen(Color.Red);
    Point p = new Point();
    bool flag = false;


    private void panel1_MouseDown(object sender, MouseEventArgs e)
    {
        flag = true;
        p = e.Location;
    }

    private void panel1_MouseMove(object sender, MouseEventArgs e)
    {
        if (flag)
        {
            g = panel1.CreateGraphics();
            myPen.Width = 3;

            Point p2 = new Point();
            p2 = e.Location;

            g.DrawLine(myPen, p, p2);

        }
    }

    private void panel1_MouseUp(object sender, MouseEventArgs e)
    {
        flag = false;
    }

}}

任何帮助?我想绘制很多行并尽可能简化代码!

2 个答案:

答案 0 :(得分:1)

您需要更好地管理绘图。一些指示:

  1. 请勿使用CreateGraphics。相反,请使用控件已提供的Paint事件。
  2. 将您的绘图放在您自己的继承类中。除非您在表单上绘制,否则不要在Form类中绘图。
  3. 这是一个示例类。它继承自Panel。只需将其添加到表单中,例如在Form的构造函数中使用this.Controls.Add(new PanelWithMouseDraw());

    之类的内容

    注意:这使用Tuple我认为需要.NET 4.0或更高版本。你可以用其他东西替换这个结构,如果需要的话......你只需要保留一个Point对列表。

    namespace WindowsFormsApplication1
    {
        public class PanelWithMouseDraw : Panel
        {
            private Point _origin = Point.Empty;
            private Point _terminus = Point.Empty;
            private Boolean _draw = false;
            private List<Tuple<Point, Point>> _lines = new List<Tuple<Point, Point>>();
    
            public PanelWithMouseDraw()
            {
                Dock = DockStyle.Fill;
                DoubleBuffered = true;
            }
    
            protected override void OnMouseDown(MouseEventArgs e)
            {
                base.OnMouseDown(e);
                if (e.Button == MouseButtons.Left)
                {
                    _draw = true;
                    _origin = e.Location;
                }
                else
                {
                    _draw = false;
                    _origin = Point.Empty;
                }
    
                _terminus = Point.Empty;
                Invalidate();
            }
    
            protected override void OnMouseUp(MouseEventArgs e)
            {
                base.OnMouseUp(e);
                if (_draw && !_origin.IsEmpty && !_terminus.IsEmpty)
                    _lines.Add(new Tuple<Point, Point>(_origin, _terminus));
                _draw = false;
                _origin = Point.Empty;
                _terminus = Point.Empty;
                Invalidate();
            }
    
            protected override void OnMouseMove(MouseEventArgs e)
            {
                base.OnMouseMove(e);
                if (e.Button == MouseButtons.Left)
                    _terminus = e.Location;
                Invalidate();
            }
    
            protected override void OnPaint(PaintEventArgs e)
            {
                foreach (var line in _lines)
                    e.Graphics.DrawLine(Pens.Blue, line.Item1, line.Item2);
                if (!_origin.IsEmpty && !_terminus.IsEmpty)
                    e.Graphics.DrawLine(Pens.Red, _origin, _terminus);
            }
        }
    }
    

答案 1 :(得分:0)

简单修复,按如下方式更改方法panel1_MouseMove

private void panel1_MouseMove(object sender, MouseEventArgs e)
{
    if (flag)
    {
        g = panel1.CreateGraphics();
        myPen.Width = 3;

        Point p2 = new Point();
        p2 = e.Location;

        g.DrawLine(myPen, p, p2);
        p = p2; // just add this

    }
}

请记住,这对任何鼠标按钮都有效,左或右无关紧要。

EDIT1:

这应画一条直线和之前的所有。

namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
    public struct Line
    {
        public Point start;
        public Point end;
    }

    public Form1()
    {
        InitializeComponent();
    }

    Pen erasePen = new Pen(Color.White, 3.0F);
    Pen myPen = new Pen(Color.Red, 3.0F);
    Point p = new Point();
    Point endPoint = new Point();
    bool flag = false;
    List<WindowsFormsApplication2.Form1.Line> lines = new List<WindowsFormsApplication2.Form1.Line>();


    private void panel1_MouseDown(object sender, MouseEventArgs e)
    {
        flag = true;
        p = e.Location;
        endPoint = p;
    }

    private void panel1_MouseMove(object sender, MouseEventArgs e)
    {
        if (flag)
        {
            Graphics g = panel1.CreateGraphics();

            Point p2 = e.Location;

            EraseLine(p, endPoint, g);

            DrawAllLines(lines, g);

            DrawLine(p, p2, g);

            endPoint = p2;

            g.Dispose();
        }
    }

    private void panel1_MouseUp(object sender, MouseEventArgs e)
    {
        // redraw for one last time...
        Graphics g = panel1.CreateGraphics();

        Point p2 = e.Location;

        lines.Add(new Line { start = p, end = p2} );

        EraseLine(p, endPoint, g);

        DrawAllLines(lines, g);

        flag = false;

        g.Dispose();
    }

    private void DrawLine(Point start, Point end, Graphics g)
    {
        g.DrawLine(myPen, start, end);
    }

    private void DrawLine(WindowsFormsApplication2.Form1.Line line, Graphics g)
    {
        g.DrawLine(myPen, line.start, line.end);
    }

    private void DrawAllLines(List<WindowsFormsApplication2.Form1.Line> allLines, Graphics g)
    {
        foreach(WindowsFormsApplication2.Form1.Line l in allLines)
        {
            g.DrawLine(myPen, l.start, l.end);
        }
    }

    private void EraseLine(Point start, Point end, Graphics g)
    {
        g.DrawLine(erasePen, start, end);
    }

}}