You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C#中实现鼠标点击与绘制旋转矩形的关联及点击判定

实现旋转矩形的点击检测与交互

这个需求其实很常见,核心难点在于你绘制的是旋转后的矩形,普通的Rectangle.Contains()方法没法直接用——因为它只适用于轴对齐的矩形。下面我给你两种靠谱的实现思路,你可以根据自己的需求选:


方法一:坐标逆变换检测

思路很简单:既然绘制时给矩形做了「平移→旋转」的变换,那我们就对点击点做逆变换(旋转逆角度→平移逆距离),然后判断变换后的点是否落在原始未旋转的矩形((0,0,rectW,rectH))里。

步骤1:绑定MouseClick事件

首先给你的pbPicture控件绑定鼠标点击事件,你可以在设计器里双击控件的MouseClick事件,或者在窗体构造函数里手动添加:

public YourFormName()
{
    InitializeComponent();
    // 绑定点击事件
    pbPicture.MouseClick += pbPicture_MouseClick;
}

步骤2:实现点击检测逻辑

private void pbPicture_MouseClick(object sender, MouseEventArgs e)
{
    // 获取相对于PictureBox的点击坐标
    Point clickPos = e.Location;

    // 遍历所有矩形,逐个检测
    for (int i = 0; i < rectX.Length; i++)
    {
        // 创建变换矩阵,执行绘制变换的逆过程
        using (Matrix inverseMatrix = new Matrix())
        {
            // 逆变换顺序:先旋转负角度,再平移负坐标(和绘制顺序相反)
            inverseMatrix.Rotate(-rectRot[i]);
            inverseMatrix.Translate(-rectX[i], -rectY[i]);

            // 将点击点应用逆变换
            Point[] transformedPoints = new[] { clickPos };
            inverseMatrix.TransformPoints(transformedPoints);
            Point transformedPos = transformedPoints[0];

            // 判断变换后的点是否在原始矩形范围内
            if (transformedPos.X >= 0 && transformedPos.X <= rectW &&
                transformedPos.Y >= 0 && transformedPos.Y <= rectH)
            {
                // 找到被点击的矩形,执行你的自定义动作
                MessageBox.Show($"你点击了第{i+1}个矩形!");
                // 示例:显示额外信息,比如弹出详情面板、更新标签文本等
                // infoLabel.Text = $"矩形{i+1}的参数:X={rectX[i]}, Y={rectY[i]}, 旋转角度={rectRot[i]}";
                break;
            }
        }
    }
}

方法二:用GraphicsPath创建旋转区域检测

这种方法更直观:直接创建和绘制时完全一致的旋转矩形路径,然后用路径的IsVisible()方法判断点击点是否在区域内。

实现代码

private void pbPicture_MouseClick(object sender, MouseEventArgs e)
{
    Point clickPos = e.Location;

    for (int i = 0; i < rectX.Length; i++)
    {
        // 使用using自动释放资源,避免内存泄漏
        using (GraphicsPath rectPath = new GraphicsPath())
        using (Matrix transformMatrix = new Matrix())
        {
            // 添加原始未旋转的矩形到路径
            rectPath.AddRectangle(new Rectangle(0, 0, rectW, rectH));

            // 应用和绘制时完全相同的变换:平移→旋转
            transformMatrix.Translate(rectX[i], rectY[i]);
            transformMatrix.Rotate(rectRot[i]);
            rectPath.Transform(transformMatrix);

            // 判断点击点是否在旋转后的矩形路径内
            if (rectPath.IsVisible(clickPos))
            {
                MessageBox.Show($"你点击了第{i+1}个矩形!");
                // 这里添加你的自定义动作,比如显示ToolTip
                // toolTip1.Show($"旋转角度:{rectRot[i]}°", pbPicture, clickPos.X + 10, clickPos.Y + 10);
                break;
            }
        }
    }
}

注意事项

  • 确保rectX、rectY、rectRot这些数组是窗体类的成员变量,而不是Paint事件里的局部变量,否则点击事件里访问不到。
  • 如果你的PictureBox设置了非Normal的SizeMode(比如Zoom、StretchImage),还需要把点击坐标转换为实际图像的坐标——如果需要这部分逻辑可以告诉我,我再补充。
  • 两种方法都记得用using包裹Matrix和GraphicsPath,或者手动调用Dispose(),避免GDI+资源泄漏。

内容的提问来源于stack exchange,提问作者INCyr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 16:47:34