私は、TScrollingWinControl
(およびTScrollBox
からコピーされたコード)に基づいて、TImage
コントロールを使って簡単なコントロールを作成しています。私は幾分ズームが機能するようにしましたが、必ずしもフォーカスされたポイントにズームする必要はありません - スクロールバーはそれに応じて変更されず、中心ポイントにフォーカスが置かれます。TScrollBox内のTImageを特定のフォーカスにズームイン/ズームアウトしますか?
私は、このコントロールZoomTo(const X, Y, ZoomBy: Integer);
にフォーカスをどこにズームするかを教えてもらいたいと思います。だからそれがズームするとき、私が渡した座標は「中央に」留まります。同時に、現在のビューの中央に置くように指示するZoomBy(const ZoomBy: Integer);
も必要です。
例えば、マウスが画像の特定のポイントを指し示すシナリオがあり、コントロールを保持してマウスをスクロールすると、マウスポインタに注目してズームインする必要があります。一方、別のシナリオでは、現在のビューの中心(必ずしも画像の中心ではない)に焦点を合わせるだけで、ズームレベルを調整するコントロールをスライドさせることがあります。
問題は私の数学がこの時点で失われてしまい、これらのスクロールバーを調整する正しい数式がわからないということです。私はいくつかの計算方法を試しましたが、何も正しく動作しないようです。
私のコントロールは削除されています。私は関連するものだけにほとんどを削除し、元のユニットは600行以上のコードです。以下の最も重要な手順は、それはあなたが「ZoomBy()」に渡すときにX、Yのために参照してくださいしたいと思いますどのようなはっきりしていないSetZoom(const Value: Integer);
unit JD.Imaging;
interface
uses
Windows, Classes, SysUtils, Graphics, Jpeg, PngImage, Controls, Forms,
ExtCtrls, Messages;
type
TJDImageBox = class;
TJDImageZoomEvent = procedure(Sender: TObject; const Zoom: Integer) of object;
TJDImageBox = class(TScrollingWinControl)
private
FZoom: Integer; //level of zoom by percentage
FPicture: TImage; //displays image within scroll box
FOnZoom: TJDImageZoomEvent; //called when zoom occurs
FZoomBy: Integer; //amount to zoom by (in pixels)
procedure MouseWheel(Sender: TObject; Shift: TShiftState;
WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
procedure SetZoom(const Value: Integer);
procedure SetZoomBy(const Value: Integer);
public
constructor Create(AOwner: TComponent); override;
published
property Zoom: Integer read FZoom write SetZoom;
property ZoomBy: Integer read FZoomBy write SetZoomBy;
property OnZoom: TJDImageZoomEvent read FOnZoom write FOnZoom;
end;
implementation
{ TJDImageBox }
constructor TJDImageBox.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
OnMouseWheel:= MouseWheel;
ControlStyle := [csAcceptsControls, csCaptureMouse, csClickEvents,
csSetCaption, csDoubleClicks, csPannable, csGestures];
AutoScroll := True;
TabStop:= True;
VertScrollBar.Tracking:= True;
HorzScrollBar.Tracking:= True;
Width:= 100;
Height:= 100;
FPicture:= TImage.Create(nil);
FPicture.Parent:= Self;
FPicture.AutoSize:= False;
FPicture.Stretch:= True;
FPicture.Proportional:= True;
FPicture.Left:= 0;
FPicture.Top:= 0;
FPicture.Width:= 1;
FPicture.Height:= 1;
FPicture.Visible:= False;
FZoom:= 100;
FZoomBy:= 10;
end;
destructor TJDImageBox.Destroy;
begin
FImage.Free;
FPicture.Free;
inherited;
end;
procedure TJDImageBox.MouseWheel(Sender: TObject; Shift: TShiftState;
WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
var
NewScrollPos: Integer;
begin
if ssCtrl in Shift then begin
if WheelDelta > 0 then
NewScrollPos := Zoom + 5
else
NewScrollPos:= Zoom - 5;
if NewScrollPos >= 5 then
Zoom:= NewScrollPos;
end else
if ssShift in Shift then begin
NewScrollPos := HorzScrollBar.Position - WheelDelta;
HorzScrollBar.Position := NewScrollPos;
end else begin
NewScrollPos := VertScrollBar.Position - WheelDelta;
VertScrollBar.Position := NewScrollPos;
end;
Handled := True;
end;
procedure TJDImageBox.SetZoom(const Value: Integer);
var
Perc: Single;
begin
FZoom := Value;
if FZoom < FZoomBy then
FZoom:= FZoomBy;
Perc:= FZoom/100;
//Resize picture to new zoom level
FPicture.Width:= Trunc(FImage.Width * Perc);
FPicture.Height:= Trunc(FImage.Height * Perc);
//Move scroll bars to properly position the center of the view
//This is where I don't know how to calculate the 'center'
//or by how much I need to move the scroll bars.
HorzScrollBar.Position:= HorzScrollBar.Position - (FZoomBy div 2);
VertScrollBar.Position:= VertScrollBar.Position - (FZoomBy div 2);
if assigned(FOnZoom) then
FOnZoom(Self, FZoom);
end;
procedure TJDImageBox.SetZoomBy(const Value: Integer);
begin
if FZoomBy <> Value then begin
FZoomBy := EnsureRange(Value, 1, 100);
Paint;
end;
end;
end.
"ズーム"ポイントが何をするのか想像もできません。私は、点ではなく四角形を「ズーム」します。あなたのクラスの実装がどのように見えるのか推測できませんので、必要な数学を推測することはできません。 –
@ WarrenP複数人の写真が表示されているとします。マウスは人の顔の中央に向けられています。ユーザーがコントロールキーを押したままマウスホイールをスクロールすると、マウスポインタが画像の同じ位置にあるまま、その人の顔が拡大されます。これが私が「Rect」ではなく「Point」にズームしている理由です。私は、マウスイベントをどのように処理するかを示すために上記の関連するコードをすべて含んでいることは確かです。 –