为什么松开鼠标按钮后画的线会消失?

本文关键字:消失 鼠标 按钮 为什么 | 更新日期: 2023-09-27 18:18:42

我一直在玩System.Drawing,我已经得到了我想要的工作方式,除了一件事。当我松开鼠标按钮时,这条线就消失了。

我如何确保行保持在我离开它的地方?

using System;
using System.Drawing;
using System.Windows.Forms;
namespace DrawingSample
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            this.DoubleBuffered = true;
        }
        Graphics graphics;
        Random
            color = new Random(1);
        Int32
            penThickness = 1;
        Point
            currentCursorLocation, initialTouchLocation, touchOffset;
        Boolean
            mouseDown;
        protected override void OnPaint(PaintEventArgs e)
        {
            graphics = e.Graphics;
            if (mouseDown)
            {
                graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                //DrawRectangle(graphics);
                //DrawEllipse(graphics);
                DrawLine(graphics);
            }
        }
        private void DrawRectangle(Graphics graphics)
        {
            graphics.DrawRectangle(new Pen(
                Color.FromArgb((color.Next(1, 
                255)), 
                (color.Next(1, 
                255)), 
                (color.Next(1, 
                255)))
                , 
                penThickness),
                currentCursorLocation.X,
                currentCursorLocation.Y,
                (this.Width / 2),
                (this.Height / 2)
                );
        }
        private void DrawEllipse(Graphics graphics)
        {
            graphics.DrawEllipse(new Pen(
                Color.FromArgb((color.Next(1, 255)),
                (color.Next(1, 255)),
                (color.Next(1, 255))), penThickness), 
                new RectangleF(currentCursorLocation, new Size(100, 100)));
        }
        private void DrawLine(Graphics graphics)
        {
            graphics.DrawLine(new Pen(
                Color.FromArgb((color.Next(1, 255)), 
                (color.Next(1, 255)), 
                (color.Next(1, 255))), penThickness),
                currentCursorLocation.X,
                currentCursorLocation.Y,
                touchOffset.X,
                touchOffset.Y
                );
        }
        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            currentCursorLocation = e.Location;
            this.Refresh();
        }
        private void Form1_MouseDown(object sender, MouseEventArgs e)
        {
            if (!mouseDown)
            {
                touchOffset = e.Location;
                mouseDown = true;
            }
        }
        private void Form1_MouseUp(object sender, MouseEventArgs e)
        {
            mouseDown = false;
        }
    }
}

为什么松开鼠标按钮后画的线会消失?

您要求代码这样做。所以它做同样的事情

Form1_MouseUp事件中设置mouseDown为false。

private void Form1_MouseUp(object sender, MouseEventArgs e)
{
    mouseDown = false; //<--Here
}

那么你在画线之前检查if (mouseDown)

protected override void OnPaint(PaintEventArgs e)
{
    graphics = e.Graphics;
    if (mouseDown)//<--Here
    {
        graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
        //DrawRectangle(graphics);
        //DrawEllipse(graphics);
        DrawLine(graphics);
    }
}

我猜你不需要if (mouseDown)检查OnPaint方法。

不确定你的意图是什么,如果你需要更多的帮助,在答案下面留言。

您可能希望在一个单独的字段中保留所有已绘制的线的列表,以便能够在必要时重新绘制它们。换句话说,如果像这样定义一个类:

class Line
{
    public Point Start { get; set; }
    public Point End { get; set; }
}

这允许你同时拥有已经绘制的线和当前绘制的线的列表(当鼠标被按住时):

// this is the line currently being drawn (i.e. a temporary line)
private Line _currentLine = null;
// this is the list of all finished lines
private readonly List<Line> _lines = new List<Line>();

鼠标处理程序现在很简单:

protected override void OnMouseDown(MouseEventArgs e)
{
    // when button is pressed, create a new _currentLine instance
    _currentLine = new Line() { Start = e.Location, End = e.Location };
    Invalidate();
    base.OnMouseDown(e);
}
protected override void OnMouseMove(MouseEventArgs e)
{
    // when mouse is moved, update the End position
    if (_currentLine != null)
    {
        _currentLine.End = e.Location;
        Invalidate();
    }
    base.OnMouseMove(e);
}
protected override void OnMouseUp(MouseEventArgs e)
{
    // when button is released, add the line to the list
    if (_currentLine != null)
    {
        _lines.Add(_currentLine);
        _currentLine = null;
        Invalidate();
    }
    base.OnMouseUp(e);
}

OnPaint方法看起来像这样:

protected override void OnPaint(PaintEventArgs e)
{
    // if you want smoother (anti-aliased) graphics, set these props
    e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
    e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
    // draw all existing lines from the list
    using (var p = new Pen(Color.Black, 2f))
        foreach (var line in _lines)
            e.Graphics.DrawLine(p, line.Start, line.End);
    // if mouse is down, draw the dashed line also
    if (_currentLine != null)
        using (var p = new Pen(Color.Salmon, 2f))
        {
            p.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
            e.Graphics.DrawLine(p, _currentLine.Start, _currentLine.End);
        }
    base.OnPaint(e);
}

另外,如果你在构造函数中使用Form.SetStyles方法来表明你将自己完成所有的绘画,并且不希望Windows自己清除窗体,那么闪烁就会少得多。这意味着表单的构造函数应该看起来像这样:

public Form1()
{
    InitializeComponent();
    SetStyle(
       ControlStyles.AllPaintingInWmPaint | 
       ControlStyles.OptimizedDoubleBuffer | 
       ControlStyles.ResizeRedraw | 
       ControlStyles.UserPaint,
       true);
}

保留行列表比简单地将它们绘制到表面上要好得多,因为它允许您:

  1. 保持数据格式为矢量,而不是作为位图(允许高分辨率缩放),
  2. 添加编辑功能(即选择现有的行,移动它,改变它的颜色,和类似的东西)。