Graphics32: панорамирование с помощью перетаскивания мышью, масштабирование до курсора мыши с помощью колесика мыши

Мне нужно реализовать панорамирование, когда я щелкаю и перетаскиваю мышь, и увеличиваю / уменьшаю масштаб в направлении / от курсора мыши, который использует колесо мыши. (В Delphi 2010 изображение привязано слева, справа, сверху и снизу к форме.)

Я только что установил Graphics32 и увидел, как встроенные полосы прокрутки и.Scale позволяют это делать. Соблазнительно легко, по крайней мере, зайти так далеко.

Вопросы:

Является ли Graphics32 хорошим инструментом для такого рода вещей? Существуют ли другие (возможно, более простые?) Инструменты, на которые я мог бы посмотреть?

У кого-нибудь есть какие-либо указатели или примеры кода о том, как реализовать вышеизложенное?

Благодарю.

1 ответ

Решение

Graphics32 предоставляет компонент с именем TImgView32, который можно масштабировать, установив свойство Scale. Надлежащий способ сделать это - использовать события OnMouseWheelUp и -Down. Установите TabStop на True для запуска этих событий и установите Centtered на False. Но масштабирование таким образом не соответствует вашему желанию центрировать операцию масштабирования на курсоре мыши. Таким образом, изменение положения и изменение размера в этой точке - более хорошее решение. Кроме того, как я понимаю, изображение всегда выравнивается в верхнем левом углу компонента, поэтому панорамирование также должно выполняться путем изменения положения компонента.

uses
  Windows, Classes, Controls, Forms, GR32_Image, GR32_Layers, Jpeg;

type
  TForm1 = class(TForm)
    ImgView: TImgView32;
    procedure FormCreate(Sender: TObject);
    procedure ImgViewMouseWheel(Sender: TObject; Shift: TShiftState;
      WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
    procedure ImgViewMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    FDragging: Boolean;
    FFrom: TPoint;
  end;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  ImgView.Bitmap.LoadFromFile('D:\Pictures\Mona_Lisa.jpg');
  ImgView.TabStop := True;
  ImgView.ScrollBars.Visibility := svHidden;
  ImgView.ScaleMode := smResize;
end;

procedure TForm1.ImgViewMouseWheel(Sender: TObject; Shift: TShiftState;
  WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
const
  ZoomFactor: array[Boolean] of Single = (0.9, 1.1);
var
  R: TRect;
begin
  MousePos := ImgView.ScreenToClient(MousePos);
  with ImgView, MousePos do
    if PtInRect(ClientRect, MousePos) then
    begin
      R := BoundsRect;
      R.Left := Left + X - Round(ZoomFactor[WheelDelta > 0] * X);
      R.Top := Top + Y - Round(ZoomFactor[WheelDelta > 0] * Y);
      R.Right := R.Left + Round(ZoomFactor[WheelDelta > 0] * Width);
      R.Bottom := R.Top + Round(ZoomFactor[WheelDelta > 0] * Height);
      BoundsRect := R;
      Handled := True;
    end;
end;

procedure TForm1.ImgViewMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer);
begin
  FDragging := True;
  ImgView.Enabled := False; { Temporarily, to get MouseMove to the parent }
  FFrom := Point(X, Y);
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if FDragging then
    ImgView.SetBounds(X - FFrom.X, Y - FFrom.Y, ImgView.Width, ImgView.Height);
end;

procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  FDragging := False;
  ImgView.Enabled := True;
  ImgView.SetFocus;
end;

Изменить: Альтернатива с TImage вместо TImgView32:

uses
  Windows, Classes, Controls, Forms, Jpeg, ExtCtrls;

type
  TForm1 = class(TForm)
    Image: TImage;
    procedure FormCreate(Sender: TObject);
    procedure FormMouseWheel(Sender: TObject; Shift: TShiftState;
      WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure ImageDblClick(Sender: TObject);
    procedure ImageMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    FDragging: Boolean;
    FFrom: TPoint;
    FOrgImgBounds: TRect;
  end;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  DoubleBuffered := True;
  Image.Picture.LoadFromFile('D:\Pictures\Mona_Lisa.jpg');
  Image.Stretch := True;
  Image.Height := Round(Image.Width * Image.Picture.Height / Image.Picture.Width);
  FOrgImgBounds := Image.BoundsRect;
end;

procedure TForm1.FormMouseWheel(Sender: TObject; Shift: TShiftState;
  WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
const
  ZoomFactor: array[Boolean] of Single = (0.9, 1.1);
var
  R: TRect;
begin
  MousePos := Image.ScreenToClient(MousePos);
  with Image, MousePos do
    if PtInRect(ClientRect, MousePos) and ((WheelDelta > 0) and
      (Height < Self.ClientHeight) and (Width < Self.ClientWidth)) or
      ((WheelDelta < 0) and (Height > 20) and (Width > 20)) then
    begin
      R := BoundsRect;
      R.Left := Left + X - Round(ZoomFactor[WheelDelta > 0] * X);
      R.Top := Top + Y - Round(ZoomFactor[WheelDelta > 0] * Y);
      R.Right := R.Left + Round(ZoomFactor[WheelDelta > 0] * Width);
      R.Bottom := R.Top + Round(ZoomFactor[WheelDelta > 0] * Height);
      BoundsRect := R;
      Handled := True;
    end;
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if FDragging then
    Image.SetBounds(X - FFrom.X, Y - FFrom.Y, Image.Width, Image.Height);
end;

procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  Image.Enabled := True;
  FDragging := False;
end;

procedure TForm1.ImageDblClick(Sender: TObject);
begin
  Image.BoundsRect := FOrgImgBounds;
end;

procedure TForm1.ImageMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if not (ssDouble in Shift) then
  begin
    FDragging := True;
    Image.Enabled := False;
    FFrom := Point(X, Y);
    MouseCapture := True;
  end;
end;
Другие вопросы по тегам