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

VB.NET中PictureBox设为StretchImage时绘图位置与鼠标偏移问题

解决PictureBox StretchImage模式下绘制位置与鼠标偏移的问题

当PictureBox的SizeMode设为StretchImage时,图片会被缩放以适配控件尺寸,此时鼠标的客户端坐标(e.X/e.Y)和图片原始像素坐标不匹配,直接使用这些坐标绘制就会出现偏移。

解决步骤:

  • 计算图片在PictureBox中的实际显示区域(考虑图片与控件的比例差异,避免黑边影响坐标转换)
  • 根据缩放比例,将鼠标的客户端坐标转换为图片的原始像素坐标
  • 使用转换后的坐标进行绘制

修改后的代码:

Sub drawBrush(ByVal e As System.Windows.Forms.MouseEventArgs)
    ' 确保PictureBox已加载图片
    If PictureBox1.Image Is Nothing Then Return

    Using g As Graphics = Graphics.FromImage(PictureBox1.Image)
        ' 计算图片在PictureBox中的显示区域
        Dim imageRect As Rectangle = GetImageDisplayRectangle(PictureBox1)
        
        ' 计算缩放比例
        Dim scaleX As Double = PictureBox1.Image.Width / imageRect.Width
        Dim scaleY As Double = PictureBox1.Image.Height / imageRect.Height
        
        ' 将鼠标坐标转换为图片原始像素坐标
        Dim imgX As Integer = CInt((e.X - imageRect.X) * scaleX)
        Dim imgY As Integer = CInt((e.Y - imageRect.Y) * scaleY)
        
        ' 确保坐标在图片范围内
        imgX = Math.Max(0, Math.Min(imgX, PictureBox1.Image.Width - 10))
        imgY = Math.Max(0, Math.Min(imgY, PictureBox1.Image.Height - 10))
        
        ' 绘制操作
        Dim brush As New SolidBrush(color)
        Dim pen1 As New Pen(color, 4)
        g.DrawRectangle(pen1, imgX, imgY, 10, 10)
        g.FillRectangle(brush, imgX, imgY, 10, 10)
        
        ' 释放资源
        pen1.Dispose()
        brush.Dispose()
    End Using
    PictureBox1.Invalidate()
End Sub

' 辅助方法:获取PictureBox中图片的实际显示区域
Private Function GetImageDisplayRectangle(pb As PictureBox) As Rectangle
    If pb.Image Is Nothing Then Return pb.ClientRectangle
    
    Dim imgRatio As Double = pb.Image.Width / pb.Image.Height
    Dim ctrlRatio As Double = pb.ClientSize.Width / pb.ClientSize.Height
    
    Dim displayWidth, displayHeight As Integer
    Dim x, y As Integer
    
    If imgRatio > ctrlRatio Then
        ' 图片更宽,按控件高度缩放
        displayHeight = pb.ClientSize.Height
        displayWidth = CInt(displayHeight * imgRatio)
        x = (pb.ClientSize.Width - displayWidth) \ 2
        y = 0
    Else
        ' 图片更高,按控件宽度缩放
        displayWidth = pb.ClientSize.Width
        displayHeight = CInt(displayWidth / imgRatio)
        x = 0
        y = (pb.ClientSize.Height - displayHeight) \ 2
    End If
    
    Return New Rectangle(x, y, displayWidth, displayHeight)
End Function

Private Sub PictureBox1_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
    If draw Then
        drawBrush(e)
    End If
End Sub

关键说明:

  • GetImageDisplayRectangle方法会根据图片和控件的宽高比,计算出图片在PictureBox中实际被拉伸显示的区域(排除上下/左右的黑边)
  • 通过scaleX和scaleY将鼠标在控件上的坐标反向缩放为图片原始像素坐标,确保绘制位置与鼠标光标对齐
  • 增加坐标范围校验,避免绘制超出图片边界

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 20:19:00