[英]How do I associate a mouse click with a drawn object in C#?
我有一个画框,上面画着一堆矩形(突出显示图像的一些特征)。 我想确定我的用户是否在给定的矩形内单击,并添加特定于该矩形的操作(即显示附加信息)。 我该怎么做呢?
如果需要,我可以提供更多信息,我只是不确定此时哪些信息有用。
绘制矩形的当前代码。 rectX、rectY、rectRot、rectColor 目前都是 arrays。 rectW 和 rectH 是常数。
private void pbPicture_Paint(object sender, PaintEventArgs e)
{
for(int i = 0; i < rectX.Length; i++)
{
e.Graphics.ResetTransform();
e.Graphics.TranslateTransform(rectX[i], rectY[i]);
e.Graphics.RotateTransform(rectRot[i]);
e.Graphics.DrawRectangle(new Pen(rectColor[i], penWidth), 0, 0, rectW, rectH);
}
e.Graphics.ResetTransform();
}
编辑:添加图片链接,附加代码。
如果您应用并保留每个形状的转换数据会更容易,然后您可以在您的实现中使用它来绘制形状,与鼠标输入交互......等等。 无需执行任何额外的转换调用来绘制主要形状,也无需执行数学例程来确定形状/矩形是否包含给定的点。
请考虑此处的Shape
class,它封装了您在实现中需要的相关数据和功能。 使用GraphicsPath
class 保持形状并应用变换,以及使用GraphicsPath.IsVisible
方法确定形状是否包含给定点,以便您可以采取相应的操作。 保留和公开Matrix
实例是为了使用它来转换图形,以防您需要在形状上进行更多绘图,例如绘制文本、图像......等。
using System;
using System.Drawing;
using System.Drawing.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Collections.Generic;
public class Shape : IDisposable
{
private bool disposedValue;
private Matrix mx;
private GraphicsPath gp;
private Size sz;
private Point loc;
private float rot;
public string Text { get; set; }
public Size Size
{
get => sz;
set
{
if (sz != value)
{
sz = value;
CleanUp();
}
}
}
public Point Location
{
get => loc;
set
{
if (loc != value)
{
loc = value;
CleanUp();
}
}
}
public float Rotation
{
get => rot;
set
{
if (rot != value)
{
rot = value;
CleanUp();
}
}
}
public Matrix Matrix
{
get
{
if (mx == null)
{
mx = new Matrix();
// According to your code snippet, you don't need to offset here.
// mx.Translate(Location.X, Location.Y);
mx.RotateAt(Rotation, Center);
}
return mx;
}
}
public GraphicsPath GraphicsPath
{
get
{
if (gp == null)
{
gp = new GraphicsPath();
gp.AddRectangle(Rectangle);
gp.Transform(Matrix);
}
return gp;
}
}
public Point Center
{
get
{
var r = Rectangle;
return new Point(r.X + r.Width / 2, r.Y + r.Height / 2);
}
}
public Rectangle Rectangle => new Rectangle(Location, Size);
public bool Selected { get; set; }
public Color BorderColor { get; set; } = Color.Black;
// Add more, ForeColor, BackColor ...etc.
public bool Contains(Point point) => GraphicsPath.IsVisible(point);
private void CleanUp()
{
gp?.Dispose();
gp = null;
mx?.Dispose();
mx = null;
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing) CleanUp();
disposedValue = true;
}
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
有了这个,你的实现应该很简单:
private readonly List<Shape> shapes = new List<Shape>();
private const int recW = 100;
private const int recH = 20;
// A method to create the list...
private void SomeMethod()
{
shapes.ForEach(s => s.Dispose());
shapes.Clear();
// In some loop...
var shape = new Shape
{
Text = "Shape...",
Size = new Size(recW, recH),
Location = new Point(some.X, some.Y),
Rotation = someAngle
};
shapes.Add(shape);
// Add the reset...
pbox.Invalidate();
}
// And to dispose of them...
protected override void OnFormClosed(FormClosedEventArgs e)
{
base.OnFormClosed(e);
shapes.ForEach(x => x.Dispose());
}
绘图部分:
private void pbox_Paint(object sender, PaintEventArgs e)
{
var g = e.Graphics;
using (var sf = StringFormat.GenericTypographic)
{
sf.Alignment = sf.LineAlignment = StringAlignment.Center;
shapes.ForEach(s =>
{
using (var pnBorder = new Pen(s.BorderColor))
{
g.SmoothingMode = SmoothingMode.AntiAlias;
g.PixelOffsetMode = PixelOffsetMode.Half;
if (s.Selected) g.FillPath(Brushes.DarkOrange, s.GraphicsPath);
g.DrawPath(pnBorder, s.GraphicsPath);
if (!string.IsNullOrEmpty(s.Text))
{
g.SmoothingMode = SmoothingMode.None;
g.PixelOffsetMode = PixelOffsetMode.Default;
g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
g.Transform = s.Matrix;
g.DrawString(s.Text, Font, Brushes.Black, s.Rectangle, sf);
g.ResetTransform();
}
}
});
}
}
与鼠标事件交互:
private void pbox_MouseDown(object sender, MouseEventArgs e)
{
foreach (var shape in shapes)
shape.Selected = shape.Contains(e.Location);
pbox.Invalidate();
}
我创建了带有随机值的矩形(形状对象)来演示。
注意:此处也应用了一些偏移量( Matrix.Translate(...)
)以在形状之间留出一些空间。
\您可以使用事件参数e来获取鼠标坐标
private void pictureBox1_Click(object sender, EventArgs e)
{
MouseEventArgs me = (MouseEventArgs)e;
Point coordinates = me.Location;
}
还有一个链接可以帮助您识别形状上的点击事件 -
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.