Почему нарисованная линия исчезает при отпускании кнопки мыши?

1

Я играю с 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;
        }
    }
}
Теги:
winforms
gdi+

2 ответа

3

Вы просите код вести себя так. Так оно делает то же самое.

Вы устанавливаете mouseDown в false в событии Form1_MouseUp.

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.

Не знаете, каковы ваши намерения. Если вам нужна дополнительная помощь, напишите комментарий ниже ответа.

  • 0
    Спасибо, Шрирам, это ответило на мой вопрос. Мое намерение состоит в том, чтобы иметь возможность перетаскивать линию вокруг, и когда я отпускаю кнопку, оставляю линию там, как она была нарисована.
  • 0
    @ Аэрон Посмотрите, поможет ли мой связанный ответ . Вы просто объявляете точки как Nullable<T> проверяете ли nullable.HasValue и рисуете ли вы его. Вам не нужно проверять if (mouseDown) .
1

Вероятно, вы хотите сохранить список всех рисованных линий в отдельном поле, чтобы иметь возможность их перерисовывать по мере необходимости. Другими словами, если вы определяете класс следующим образом:

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 Form.SetStyles форму самостоятельно. Это означает, что ваш конструктор формы должен выглядеть примерно так:

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

Сохранение списка строк намного лучше, чем просто рисование их на поверхности, поскольку оно позволяет:

  1. Сохраняйте формат данных в виде векторов, а не как растровое изображение (допускает масштабирование с высоким разрешением),
  2. Добавьте функциональность редактирования (т.е. Выберите существующую строку, переместите ее, измените ее цвет и аналогичные материалы).
  • 1
    Кроме того, расширение этого для рисования различных типов геометрических объектов является обычным упражнением в ООП: у вас будет базовый класс Shape (или интерфейс IShape ), который будет представлять его метод Draw(Graphics g) и рисовать сам. Это означает, что вместо линии будет список фигур и текущая фигура, и вы, вероятно, выберете тип фигуры из меню.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню