问题描述
我有一个带有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;