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

C# WinForms:获取光标相对于PictureBox图像的位置而非窗体

解决PictureBox绘图时鼠标坐标偏移问题

你的问题出在:当PictureBox的SizeMode为非Normal(比如StretchImage、Zoom)时,e.Location是相对于控件的坐标,但你直接在原始Image上绘图,两者的尺寸和显示比例不匹配,导致绘图位置偏移。

解决方案:将控件坐标转换为图像实际坐标

先实现一个坐标转换函数,根据PictureBox的SizeMode计算控件坐标对应的图像像素坐标:

private PointF GetImagePoint(PictureBox pb, Point controlPoint)
{
    var imageSize = pb.Image.Size;
    var displayRect = pb.ClientRectangle;

    float scaleX = 1f;
    float scaleY = 1f;
    PointF offset = PointF.Empty;

    switch (pb.SizeMode)
    {
        case PictureBoxSizeMode.StretchImage:
            scaleX = (float)imageSize.Width / displayRect.Width;
            scaleY = (float)imageSize.Height / displayRect.Height;
            break;
        case PictureBoxSizeMode.Zoom:
            float displayScale = Math.Min((float)displayRect.Width / imageSize.Width, (float)displayRect.Height / imageSize.Height);
            offset.X = (displayRect.Width - imageSize.Width * displayScale) / 2;
            offset.Y = (displayRect.Height - imageSize.Height * displayScale) / 2;
            scaleX = 1 / displayScale;
            scaleY = 1 / displayScale;
            break;
        case PictureBoxSizeMode.CenterImage:
            offset.X = (displayRect.Width - imageSize.Width) / 2;
            offset.Y = (displayRect.Height - imageSize.Height) / 2;
            break;
        // Normal和AutoSize模式下坐标无需转换,直接使用
        case PictureBoxSizeMode.Normal:
        case PictureBoxSizeMode.AutoSize:
        default:
            break;
    }

    float x = (controlPoint.X - offset.X) * scaleX;
    float y = (controlPoint.Y - offset.Y) * scaleY;

    // 确保坐标不超出图像范围
    x = Math.Clamp(x, 0, imageSize.Width - 1);
    y = Math.Clamp(y, 0, imageSize.Height - 1);

    return new PointF(x, y);
}

修改原有绘图代码

  1. 把lastPoint的类型改为PointF(转换后的坐标可能是浮点数,提升绘图精度):
private PointF? lastPoint;
private bool mouseDown;
  1. 修改MouseDown、MouseMove方法,使用转换后的坐标:
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
    lastPoint = GetImagePoint(pictureBox1, e.Location);
    mouseDown = true;
}

private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
    mouseDown = false;
}

private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
    if (mouseDown && lastPoint.HasValue)
    {
        PointF currentPoint = GetImagePoint(pictureBox1, e.Location);
        using (Graphics g = Graphics.FromImage(pictureBox1.Image))
        {
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            g.DrawLine(pen, lastPoint.Value, currentPoint);
        }

        pictureBox1.Invalidate();
        lastPoint = currentPoint;
    }
}

这样修改后,无论PictureBox用哪种SizeMode,鼠标位置都能准确对应到原始图像的像素位置,解决绘图偏移问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 02:05:20