我正在使用WinForms为模拟编写可视化工具。可视化涉及在网格周围移动的各种对象。
到目前为止,我使用的是扩展 Panel 的自定义控件,并在 Paint 事件期间使用 Graphics 类进行自定义绘制。但是,令人恼火的是,我经常不得不将事物从网格坐标缩放到控件。显示矩形坐标(换句话说,在网格中占据 2 个单元格的对象将占用 2 *(控件。绘制时显示矩形.宽度/水平网格宽度)像素)。
我想知道,有没有办法让 Graphics 对象为我进行这些转换,以便我可以在网格坐标中表达我的绘图并将其自动映射到物理坐标?
事实证明,矩阵确实是关键(见接受的答案)。这是让它工作的代码:
public SimulationPanel() {
this.DoubleBuffered = true;
this.SizeChanged += (o, e) => this.Invalidate();
this.Paint += this.PaintPanel;
}
private void Paint(object sender, PaintEventArgs e) {
e.Graphics.Clear(Color.Black);
var fromRectangle = GetSimulationWorldCoordinates();
var toRectangle = ScaleToFit(fromRectangle, this.DisplayRectangle);
using (var matrix = new Matrix(
fromRectangle,
new[] {
toRectangle.Location,
new Point(toRectangle.Right, toRectangle.Top),
new Point(toRectangle.Left, toRectangle.Bottom),
}))
{
// draw the simulation stuff here using simulation coordinates
e.Graphics.Transform = matrix;
e.Graphics.FillRectangle(Brushes.LightBlue, toRectangle);
e.Graphics.DrawLine(Pens.Red, toRectangle.Location, new Point(toRectangle.Right, toRectangle.Bottom));
}
}
这段代码怎么样?
我使用标签而不是网格,因为我无法知道您的网格。
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
GraphicsPath path = new GraphicsPath();
RectangleF pathRect;
public Form1()
{
InitializeComponent();
Location = new Point(0, 0);
Size = new System.Drawing.Size(500, 500);
Label lbl1 = new Label();
lbl1.Location = new Point(100, 100);
lbl1.Size = new System.Drawing.Size(200, 100);
lbl1.BorderStyle = BorderStyle.FixedSingle;
lbl1.Paint += new PaintEventHandler(lbl_Paint);
Label lbl2 = new Label();
lbl2.Location = new Point(300, 200);
lbl2.Size = new System.Drawing.Size(100, 200);
lbl2.BorderStyle = BorderStyle.FixedSingle;
lbl2.Paint += new PaintEventHandler(lbl_Paint);
Controls.Add(lbl1);
Controls.Add(lbl2);
path.AddRectangle(new Rectangle(50, 50, 150, 150));
path.AddEllipse(new Rectangle(25, 50, 25, 50));
pathRect = path.GetBounds();
}
void lbl_Paint(object sender, PaintEventArgs e)
{
var rect = ((Control)sender).DisplayRectangle;
PointF[] plgpts = new PointF[] {
new PointF(rect.Left, rect.Top),
new PointF(rect.Right - 1, rect.Top),
new PointF(rect.Left, rect.Bottom - 1),
};
Graphics g = e.Graphics;
g.Clear(SystemColors.Control);
using (Matrix matrix = new Matrix(path.GetBounds(), plgpts))
{
g.Transform = matrix;
g.DrawPath(Pens.Red, path);
}
}
}
}