最近,我显然开始在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函数以根据鼠标坐标使用width
和height
绘制矩形。我尝试了Google搜索并向好友寻求帮助,但到目前为止还没有运气。
那么如何调用带有坐标和DrawRect()
的{{1}}?
答案 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
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.Drawing
和Graphics
。
您的代码将如下所示:
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);
}
}