如何调用使用PaintEventArgs和坐标变量的方法

时间:2018-12-10 13:33:08

标签: c# .net winforms paint

最近,我显然开始在C#中进行编程,并试图做一个简单的WinForms应用,该应用可以获取鼠标坐标并根据坐标缩放矩形。
我面临的问题是我不知道如何调用使用更多参数的方法(在这种情况下为x,y和PaintEventArgs)。或者我确实知道,但是我不知道如何处理PaintEvent

这是整个代码,因为它很短而且很简单:

using System;
using System.Drawing;
using System.Windows.Forms;

public partial class Form1 : Form
{
    public void Form1_MouseMove(object sender, MouseEventArgs e)
    {
        int x = e.X; 
        int y = e.Y;
        String data = (x.ToString() + " " + y.ToString());
        DrawRect(Something, x, y);
    }

    PaintEventArgs pEventArgs;
    private void Form1_Paint(object sender, PaintEventArgs e)
    {

    }

    public void DrawRect(PaintEventArgs e, int rey, int rex)
    {
        Graphics gr = e.Graphics;
        Pen pen = new Pen(Color.Azure, 4);
        Rectangle rect = new Rectangle(0, 0, rex, rey);
        gr.DrawRectangle(pen, rect);
    }
}

我正在尝试调用DrawRect函数以根据鼠标坐标使用widthheight绘制矩形。我尝试了Google搜索并向好友寻求帮助,但到目前为止还没有运气。
那么如何调用带有坐标和DrawRect()的{​​{1}}?

4 个答案:

答案 0 :(得分:2)

在控件的表面上绘制时,请始终使用该控件的Paint事件。
永远不要尝试存储它的Graphics对象(一旦Control失效(重新绘制),它就不再有效)。
请勿尝试以其他方式使用其PaintEventArgs。仅在Graphics事件内使用它引用的Paint对象。

当需要更复杂的过程来绘制更多不同的形状时,可以将e.Graphics事件提供的Paint对象传递给不同的方法,这些方法将使用e.Graphics对象来执行专门的图纸。


在该示例中,我将每个绘制的Rectangle的坐标存储在一个专门的类(DrawingRectangle,这里是简化的结构)中,并使用List<DrawingRectangle>()访问这些引用。
< / p>

MouseDown事件报告控件的表面上按下了向左按钮时,e.Location将存储为DrawingRectangle.Location(此值可以更改,具体取决于鼠标指针的方向)和DrawingRectangle.StartPoint(不变的参考指标)。

移动鼠标时,将从存储的Rectangle起点坐标中减去当前e.Location坐标值(加上一些允许从所有侧面绘制Rectangle的计算)。此度量是矩形的大小。

每次检测到左MouseDown时,都会向列表中添加一个新的类元素。

要从工程图中移除矩形,只需从列表和提供工程图表面的控件Invalidate()中移除其引用。
要清除绘图表面,请清除List<DrawingRectangle>()DrawingRects.Clear())并调用Invalidate()

此处还有一些其他示例:
Transparent Overlapping Circular Progress Bars
GraphicsPath and Matrix classes
Connecting different shapes
Drawing Transparent/Translucent Custom Controls

Drawing Rectangles

List<DrawingRectangle> DrawingRects = new List<DrawingRectangle>();

public class DrawingRectangle
{
    public Point Location { get; set; }
    public Size Size { get; set; }
    public Point StartPosition { get; set; }
    public Color DrawingcColor { get; set; } = Color.LightGreen;
    public float PenSize { get; set; } = 3f;

}

private void form1_MouseDown(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left) {
        DrawingRects.Add(new DrawingRectangle() {
            Location = e.Location, Size = Size.Empty, StartPosition = e.Location
        });
    }
}

private void form1_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        DrawingRectangle rect = DrawingRects.Last();
        if (e.Y < rect.StartPosition.Y) { rect.Location = new Point(rect.Location.Y, e.Y); }
        if (e.X < rect.StartPosition.X) { rect.Location = new Point(e.X, rect.Location.Y); }

        rect.Size = new Size(Math.Abs(rect.StartPosition.X - e.X), Math.Abs(rect.StartPosition.Y - e.Y));
        DrawingRects[DrawingRects.Count - 1] = rect;
        this.Invalidate();
    }
}

private void form1_Paint(object sender, PaintEventArgs e)
{
    if (DrawingRects.Count == 0) return;
    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

    foreach (var rect in DrawingRects) {
        using (Pen pen = new Pen(rect.DrawingcColor, rect.PenSize)) {
            e.Graphics.DrawRectangle(pen, new Rectangle(rect.Location, rect.Size));
        };
    }
}

private void btnClear_Click(object sender, EventArgs e)
{
    DrawingRects.Clear();
    this.Invalidate();
}

答案 1 :(得分:1)

  

使用鼠标坐标并根据坐标缩放矩形的应用

我希望看到这样的东西(伪代码):

Point _point;

void Form1_MouseMove(object sender, MouseEventArgs e)
{
    ... // calculate new coordinates/scale factor/whatever here
    _point = ... ; // store results in fields
    Invalidate(); // this will cause repaint every time you move mouse
}

void Form1_Paint(object sender, PaintEventArgs e)
{
    ... // take values from fields
    e.Graphics.DrawRectangle(pen, rect); // draw
}

这很简单。绘画是Invalidate()调用的组合,这些调用会引发绘画事件。您使用字段传递的变量。

答案 2 :(得分:0)

PaintEventArgs允许您访问Graphics对象,您需要该对象来绘制对象。

如果您不想使用PaintEventArgs,我建议您调用CreateGraphics()的{​​{1}}方法,它将允许您绘制矩形。

为了提高性能,我建议您使用using(...){}键盘,以便处理Form对象和Graphics对象。

您需要包括Pen才能使用System.DrawingGraphics

您的代码将如下所示:

Pen

答案 3 :(得分:0)

在WinForms应用程序中绘图的工作方式与您可能期望的略有不同。如果您将屏幕上的所有内容都视为暂时的,最小化并恢复您的窗口,屏幕上的内容将被删除,并且将要求您重新绘制窗口(系统将触发窗口的Paint事件)。

这就是为什么DrawRect方法需要PaintEventArgs参数的原因:应该仅在您的Paint事件处理程序中调用它。如果您从外部调用它(如其他答案中所建议的那样),则矩形的行为可能会不一致。

我建议您记住一些内部变量中的矩形,然后在系统要求时重新绘制它们:

private Point pointToDrawRect = new Point(0,0);
public void Form1_MouseMove(object sender, MouseEventArgs e)
    {
        int x = e.X;
        int y = e.Y;
        String data = (x.ToString() + " " + y.ToString());
        pointToDrawRect= new Point(x, y);
        Invalidate();
    }

    private void Form1_Paint(object sender, PaintEventArgs e)
    {
         if(pointToDrawRect.X != 0 || pointToDrawRect.Y != 0)
         {
             DrawRect(e, pointToDrawRect.X, pointToDrawRect.Y);
         }
    }

    public void DrawRect(PaintEventArgs e, int rey, int rex)
    {
            using (Pen pen = new Pen(Color.Azure, 4))
            {
                Rectangle rect = new Rectangle(0, 0, rex, rey);
                e.Graphics.DrawRectangle(pen, rect);
            }
    }