使用Stretch在TImage中获取鼠标下方的像素比例和中心都设置为true

问题描述

我有一个带有TImage的表格。将该TImage设置为Align = alClient,Stretch = True,Proportional = True和Center = True。

在运行时,我将一个位图加载到该TImage中。正如我所期望的那样,它的显示尺寸比原始尺寸要小一些,但不会变形。

现在,我想在按下“鼠标”按钮时获取鼠标下方像素的坐标。这是分配给im_Input.OnMouseDown的代码:

procedure Tf_ColorAdjustment.im_InputMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X,Y: Integer);
begin
  im_Input.Picture.Bitmap.Canvas.Pixels[X - 1,Y - 1] := clYellow;
  im_Input.Picture.Bitmap.Canvas.Pixels[X - 1,Y] := clYellow;
  im_Input.Picture.Bitmap.Canvas.Pixels[X - 1,Y + 1] := clYellow;
  im_Input.Picture.Bitmap.Canvas.Pixels[X,Y - 1] := clYellow;
  im_Input.Picture.Bitmap.Canvas.Pixels[X,Y] := clYellow;
  im_Input.Picture.Bitmap.Canvas.Pixels[X,Y + 1] := clYellow;
  im_Input.Picture.Bitmap.Canvas.Pixels[X + 1,Y - 1] := clYellow;
  im_Input.Picture.Bitmap.Canvas.Pixels[X + 1,Y] := clYellow;
  im_Input.Picture.Bitmap.Canvas.Pixels[X + 1,Y + 1] := clYellow;
end;

(这只是测试代码,以查看鼠标单击最终结束的位置。我知道使用Pixels属性非常慢,但这是使受影响的像素可见的最简单方法。)

如果将所有这些标志都设置为false,这将很好地工作,但是由于位图被缩小以匹配窗口,因此像素似乎向左和向上移动。

我知道我需要调整坐标,但是我该怎么做?是否有RTL / VCL支持?类似于TImage的CalcStretched方法(我找不到它,但也许只是忽略了它)。还是我真的必须自己编写计算程序?

(我不敢相信Google尚未为此找到现成的解决方案。这肯定是几十年来经常遇到的问题。)

解决方法

好吧,您只需要进行一些减法和除法运算即可:

function TForm1.ClientToBitmap(const P: TPoint): TPoint;
var
  cW,cH: Integer;       // width and height of control
  bW,bH: Integer;       // width and height of bitmap
  Origin: TPointF;       // top-left pixel of bitmap in the control
  ZoomW,ZoomH: Double;  // required zoom factor to make bitmap fit horisontally or vertically
  Zoom: Double;          // zoom factor
begin

  cW := Image1.Width;
  cH := Image1.Height;
  bW := Image1.Picture.Bitmap.Width;
  bH := Image1.Picture.Bitmap.Height;

  ZoomW := cW/bW;
  ZoomH := cH/bH;
  Zoom := Min(ZoomW,ZoomH);

  Origin.X := (cW - bW*Zoom) / 2;
  Origin.Y := (cH - bH*Zoom) / 2;

  Result.X := Round((P.X - Origin.X) / Zoom);
  Result.Y := Round((P.Y - Origin.Y) / Zoom);

end;

现在:

procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X,Y: Integer);
begin
  with ClientToBitmap(Point(X,Y)) do
  begin
    Image1.Picture.Bitmap.Canvas.Pixels[X - 1,Y - 1] := clBlack;
    Image1.Picture.Bitmap.Canvas.Pixels[X - 1,Y] := clBlack;
    Image1.Picture.Bitmap.Canvas.Pixels[X - 1,Y + 1] := clBlack;
    Image1.Picture.Bitmap.Canvas.Pixels[X,Y - 1] := clBlack;
    Image1.Picture.Bitmap.Canvas.Pixels[X,Y] := clBlack;
    Image1.Picture.Bitmap.Canvas.Pixels[X,Y + 1] := clBlack;
    Image1.Picture.Bitmap.Canvas.Pixels[X + 1,Y - 1] := clBlack;
    Image1.Picture.Bitmap.Canvas.Pixels[X + 1,Y] := clBlack;
    Image1.Picture.Bitmap.Canvas.Pixels[X + 1,Y + 1] := clBlack;
  end;
end;

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...