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

FMX TImageViewer获取原始位图鼠标像素坐标问题(含错误代码)

解决FMX TImageViewer中获取鼠标下原始位图像素坐标的问题

你的代码无法正确获取原始像素坐标,核心问题是忽略了TImageViewer的滚动偏移,且错误地自行计算缩放比例。以下是修正后的实现:

修正后的代码

procedure TmainForm.imgviewer_layoutMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Single);
var
  ImageViewer: TImageViewer;
  Image: TBitmap;
  LocalPos, ImagePos: TPointF;
  BitmapScale: Single;
begin
  ImageViewer := Sender as TImageViewer;
  Image := ImageViewer.Bitmap;
    
  if Assigned(Image) and not Image.IsEmpty then
  begin
    // 计算鼠标相对于图像显示区域的坐标(减去滚动偏移)
    LocalPos.X := X - ImageViewer.ViewPortPosition.X;
    LocalPos.Y := Y - ImageViewer.ViewPortPosition.Y;

    BitmapScale := Image.BitmapScale;
    // 转换为原始位图的像素坐标:结合组件缩放比例与高DPI适配因子
    ImagePos.X := LocalPos.X / (ImageViewer.Scale.X * BitmapScale);
    ImagePos.Y := LocalPos.Y / (ImageViewer.Scale.Y * BitmapScale);

    // 校验坐标是否在原始位图范围内
    if (ImagePos.X >= 0) and (ImagePos.X <= Image.Width) and
       (ImagePos.Y >= 0) and (ImagePos.Y <= Image.Height) then
    begin
      // 如需整数像素坐标,可使用Round或Trunc处理
      UpdateStatus(Format('INFO LAYOUT DOWN 原始像素坐标: (%.0f, %.0f)', [ImagePos.X, ImagePos.Y]));
    end
    else
    begin
      UpdateStatus('INFO LAYOUT DOWN: 不在图像范围内');
    end;
  end
  else
  begin
    UpdateStatus('INFO LAYOUT DOWN: 未加载图像');
  end;
end;

关键修正点

  • 滚动偏移处理:使用ViewPortPosition获取图像的滚动偏移量,鼠标坐标需先减去该值,才能得到相对于图像显示区域的位置。
  • 正确的缩放比例:直接使用TImageViewer内置的Scale属性,而非自行计算容器与图像的宽高比,该属性准确反映了当前图像的缩放状态。
  • 高DPI适配:结合位图的BitmapScale因子,确保在高分辨率屏幕下坐标转换的准确性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 08:47:10