Recent

Author Topic: [SOLVED] How to move (drag) a picture on a TScrollBox via mouse?  (Read 1827 times)

Hartmut

  • Hero Member
  • *****
  • Posts: 1153
My program can show a picture file with various scaling factors on a TScrollBox which resides on a TForm. If the (scaled) picture is bigger than the TForm, scrollbars from the TScrollBox appear. So you can move the visible part of the picture with the scrollbars in all 4 directions.

I want, that you can move (drag) the visible part of the picture also via left-mouse in all 4 directions. I'm a beginner to Graphics and have no idea to start.

Here are the details:
 - the picture file is loaded into a TPicture
 - this picture is streched by a selectable scaling factor and the result is stored into a TBitmap
 - there is a TPaintBox which displays the TBitmap via Event TPaintBox.OnPaint
 - the TPaintBox resides on a TScrollBox which has the same size as the TForm

I guess that I need some kind of Mouse-Event(s), but don't know which Event(s) and for which Control(s).

I want a solution for Windows and Linux. Thanks in advance.
« Last Edit: October 27, 2024, 06:56:52 pm by Hartmut »

jamie

  • Hero Member
  • *****
  • Posts: 7830
Re: How to move (drag) a picture on a TScrollBox via mouse?
« Reply #1 on: October 26, 2024, 03:53:27 pm »
You need to pan the picture I guess ?

using the MouseDown event, log the current X, Y position of the mouse and then while in the MouseMove event, take the current X, Y mouse position and create an offset value with the current location of the image and repaint it at that position.

 Basically, you are offsetting your image via the amount of offset from where you first initially logged the mouse in the mouse down and where you are now when the mouse move event occurs.

 also, make sure you test for the mouse button being down.

 The TPoint Class has members in it to help do the math.


 
The only true wisdom is knowing you know nothing

jamie

  • Hero Member
  • *****
  • Posts: 7830
Re: How to move (drag) a picture on a TScrollBox via mouse?
« Reply #2 on: October 26, 2024, 06:24:45 pm »
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Button1: TButton;
  16.     procedure Button1MouseDown(Sender: TObject; Button: TMouseButton;
  17.       Shift: TShiftState; X, Y: Integer);
  18.     procedure Button1MouseMove(Sender: TObject; Shift: TShiftState; X,
  19.       Y: Integer);
  20.   private
  21.  
  22.   public
  23.     ButtonDownAT:TPoint;
  24.   end;
  25.  
  26. var
  27.   Form1: TForm1;
  28.  
  29. implementation
  30.  
  31. {$R *.lfm}
  32.  
  33. { TForm1 }
  34.  
  35. procedure TForm1.Button1MouseDown(Sender: TObject; Button: TMouseButton;
  36.   Shift: TShiftState; X, Y: Integer);
  37. begin
  38.   ButtonDownAt:= TPoint.Create(X,Y); //Create a starting point.
  39. end;
  40.  
  41. procedure TForm1.Button1MouseMove(Sender: TObject; Shift: TShiftState; X,
  42.   Y: Integer);
  43. Var
  44.   P:TPoint;
  45. begin
  46.   If ssLeft in Shift then With  button1 do
  47.    Begin
  48.     P :=Point(ButtonDownAt.X-X,ButtonDownAt.Y-Y);//Get difference.
  49.     Left := Left-P.X;
  50.     Top := Top-P.Y;
  51.     ButtonDownAt := Point(X+P.X,Y+P.Y); //Update for next position;
  52.    end;
  53. end;
  54.  
  55. end.
  56.  
  57.  

This drags a button around the screen.
Should give you an idea.
The only true wisdom is knowing you know nothing

Hartmut

  • Hero Member
  • *****
  • Posts: 1153
Re: How to move (drag) a picture on a TScrollBox via mouse?
« Reply #3 on: October 26, 2024, 06:53:33 pm »
Thanks a lot jamie for your posts and the demo. I understand what you suggest. Now I have 2 questions left:

1) Are Events OnMouseDown and OnMouseMove easier / better than Events OnDragDrop / OnDragOver / OnEndDrag? Or are the last 3 Events for another purpose? (I don't understand their Help in the OI (too short for me) and did not have yet the time for further investigations).

2) Whichever Events I use: from which Control (TPicture / TBitmap / TPaintBox / TScrollBox / TForm) must I use them? (please see therefore clause "Here are the details:" in my 1st post).

jamie

  • Hero Member
  • *****
  • Posts: 7830
Re: How to move (drag) a picture on a TScrollBox via mouse?
« Reply #4 on: October 26, 2024, 07:11:28 pm »
I assume you are sliding the image around a little bit once dropped?

What I suggested is a simple way to create an offset value for you to reposition the image drawing Starting point.

So assuming you are using some sort of X,Y TPoint as the starting point during the Onpaint event, this X,Y is what you need to offset with the example code I showed you. The next painting cycle will use the new offset, so you get panning effect.

As for the Scrollbox, I am not sure what you are using that for? I assume maybe because the image is too large to show.


P..S
 Just a comment, you can adjust the position of the scrollbars to move the image around if that is what you mean?

Look at the properties of the scrollboxes scrollbars
« Last Edit: October 26, 2024, 07:13:34 pm by jamie »
The only true wisdom is knowing you know nothing

jamie

  • Hero Member
  • *****
  • Posts: 7830
Re: How to move (drag) a picture on a TScrollBox via mouse?
« Reply #5 on: October 26, 2024, 09:41:16 pm »
Look at this code for panning a TPaintBox around in a scrollbox.

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs,lclIntf, ExtCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     PaintBox1: TPaintBox;
  16.     ScrollBox1: TScrollBox;
  17.     procedure FormCreate(Sender: TObject);
  18.     procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
  19.       Shift: TShiftState; X, Y: Integer);
  20.     procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
  21.       Y: Integer);
  22.     procedure PaintBox1Paint(Sender: TObject);
  23.   private
  24.  
  25.   public
  26.    B:TBitmap;
  27.    P:TPoint;
  28.    StartPT :TPoint;
  29.   end;
  30.  
  31. var
  32.   Form1: TForm1;
  33.  
  34. implementation
  35.  
  36. {$R *.lfm}
  37.  
  38. { TForm1 }
  39.  
  40. procedure TForm1.FormCreate(Sender: TObject);
  41. Var
  42.   A:TBitmap;
  43. begin
  44.   A := Tbitmap.Create;
  45.   A.LoadFromDevice(GetDC(0));
  46.   B:= TBitMap.Create;
  47.   B.SetSize(320,256);
  48.   B.Canvas.StretchDraw(Rect(0,0,B.Width,B.Height),A);
  49.   B.canvas.Pen.Color := clBlack;
  50.   B.Canvas.Brush.Style := bsClear;
  51.   B.Canvas.Rectangle(0,0,320,256);
  52.   A.Free;
  53.   PaintBox1.Width :=320;
  54.   PaintBox1.Height := 256;
  55. end;
  56.  
  57. procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
  58.   Shift: TShiftState; X, Y: Integer);
  59. begin
  60.    StartPT := Point(X,Y);
  61. end;
  62.  
  63. procedure TForm1.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
  64.   Y: Integer);
  65. begin
  66.    if ssleft in Shift then With PaintBox1 do
  67.    Begin
  68.      Left := Left-(StartPT.X-X);
  69.      Top :=  Top-(startPt.Y-Y);
  70.    end;
  71. end;
  72.  
  73. procedure TForm1.PaintBox1Paint(Sender: TObject);
  74. begin
  75.   PaintBox1.Canvas.Draw(P.X,P.Y,B);
  76. end;
  77.  
  78. end.
  79.  
  80.  
The only true wisdom is knowing you know nothing

Hartmut

  • Hero Member
  • *****
  • Posts: 1153
Re: How to move (drag) a picture on a TScrollBox via mouse?
« Reply #6 on: October 27, 2024, 12:54:18 pm »
I think I've got it. This is my code:

Code: Pascal  [Select][+][-]
  1. var mausStart: TPoint; {Mouse-Coordinates from the start of panning the picture}
  2.  
  3. procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
  4.                                     Shift: TShiftState; X, Y: Integer);
  5.    var P: TPoint;
  6.    begin
  7.    P:=Mouse.CursorPos; {get absolute Mouse-Coordinates}
  8.    if Button=mbLeft then mausStart:=P;
  9.    end;
  10.  
  11. procedure TForm1.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState;
  12.                                     X, Y: Integer);
  13.    var SB: TControlScrollBar;
  14.        P: TPoint;
  15.        d: integer;
  16.    begin
  17.    P:=Mouse.CursorPos; {get absolute Mouse-Coordinates}
  18.    if not (ssLeft in Shift) then exit;
  19.  
  20.    SB:=ScrollBox1.HorzScrollBar; {abbreviation}
  21.    d:=mausStart.X-P.X;           {horizontal distance}
  22.    SB.Position:=SB.Position+d;
  23.  
  24.    SB:=ScrollBox1.VertScrollBar; {abbreviation}
  25.    d:=mausStart.Y-P.Y;           {vertical distance}
  26.    SB.Position:=SB.Position+d;
  27.  
  28.    mausStart:=P;
  29.    end;
  30.  
  31. procedure TForm1.PaintBox1Paint(Sender: TObject);
  32.    begin
  33.    if Bitmap1 <> nil then
  34.       Paintbox1.Canvas.Draw(0,0,Bitmap1);
  35.    end;

I wanted that Event PaintBox1MouseMove() changes also the visible positions of the scrollbars (which are displayed when the (scaled) picture is bigger than the Form) instead of only changing the starting point of the PaintBox.

And I had to use absolute Mouse-Coordinates instead of PaintBox-relative coordinates, because PaintBox-relative coordinates *change*, when you pan the picture and that gave a strange effect.

Thank you very much jamie for your valuable help.

Only one point is left:
While the picture is panned, I want to show a different type of mouse cursor, e.g. a hand-symbol or a quad-arrow (which has an arrow left and right and up and down). How can I achieve this? I assume that some predifined mouse cursor types for such purposes exist?

jamie

  • Hero Member
  • *****
  • Posts: 7830
Re: How to move (drag) a picture on a TScrollBox via mouse?
« Reply #7 on: October 27, 2024, 01:55:41 pm »
You can change the cursor during the mouseDown event of the paintbox and reset it back to default on mouse up or mousemove if the keys are not down.


TPaintBox.Cursor := ???

Look at the TScreen class in the help for the list of cursors.

You can also make your own custom cursors.
The only true wisdom is knowing you know nothing

Hartmut

  • Hero Member
  • *****
  • Posts: 1153
Re: How to move (drag) a picture on a TScrollBox via mouse?
« Reply #8 on: October 27, 2024, 06:56:00 pm »
Thanks jamie again. This 2 commands did the job:

Code: Pascal  [Select][+][-]
  1. PaintBox1.Cursor:=crSize; {quad-arrow cursor = arrow left and right and up and down}
  2. ...
  3. PaintBox1.Cursor:=crDefault; {default mouse-cursor again}

 

TinyPortal © 2005-2018