### Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

### Author Topic: Using the Mouse Wheel to Zoom  (Read 696 times)

#### J-G

• Hero Member
• Posts: 931
##### Using the Mouse Wheel to Zoom
« on: August 13, 2022, 12:17:06 pm »
I've not looked at the [OnMouseWheel] event previously and was surprized how easy it was to impliment a [Zoom] facility. I had prevously set up a TTrackBar to deal with the Zoom but the idea of using the MouseWheel seemed to be more 'intuitive' for the end user.

The proc for the TTrackBar is very simple :
Code: Pascal  [Select][+][-]
1. procedure TForm1.ZoomChange(Sender: TObject);
2. begin
3.   Mag := Zoom.Position/100;
4.   if Mag < 0.1 then
5.     Mag := 0.1;
6.   Calc(self);
7. end;
You'll see that it just checks for a minimum size.

For the MouseWheel event it's very similar :
Code: Pascal  [Select][+][-]
1. procedure TForm1.DisplayMouseWheel(Sender: TObject; Shift: TShiftState;
2.   WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
3. begin
4.   Mag := Mag*(WheelDelta/100);
5.   if Mag < 0.1 then
6.     Mag := 0.1;
7.   Zoom.Position := Round(Mag*100);
8.   Calc(self);
9. end;
It still checks for the Min but also sets the TTrackBar position - just to keep the two 'in sync'.

The (WheelDelta/100) was decided empirically - starting with /1 then /1000  -    /100 seems OK but further tests may change that.

This works as anticipated ---  but only when enlarging  ie. pushing the Wheel forward  -- as soon as I pull the wheel back - just one click - the Magnification becomes the Min (0.1)

Assuming that WheelDelta might become negative, I tried ABS(WheelDelta/100) but that made the 'negative' Zoom maximize.  ???

I can see from the description of the TMouseWheelEvent that WheelDelta is "How many notches the wheel has been turned" but there doesn't appear to be a 'direction' parameter which I might be able to use.

Can anyone shed some light on how I might better determine the level of magnification - specifically in the negative direction?

FPC 3.0.0 - Lazarus 1.6 &
FPC 3.2.2  - Lazarus 2.2.0
Win 7 Ult 64

#### bytebites

• Hero Member
• Posts: 523
##### Re: Using the Mouse Wheel to Zoom
« Reply #1 on: August 13, 2022, 02:01:06 pm »
sign(WheelDelta) tells the direction.

#### jamie

• Hero Member
• Posts: 4922
##### Re: Using the Mouse Wheel to Zoom
« Reply #2 on: August 13, 2022, 04:54:24 pm »
wheel delta is 120 by standard.

Not sure how you want to handle that, but I guess one could query that info at will.

The only true wisdom is knowing you know nothing

#### J-G

• Hero Member
• Posts: 931
##### Re: Using the Mouse Wheel to Zoom
« Reply #3 on: August 13, 2022, 07:20:23 pm »
sign(WheelDelta) tells the direction.
Thanks @bytebits  -  very useful.

I still needed to put my thinking cap on though and eventually came up with :
Code: Pascal  [Select][+][-]
1. procedure TForm1.DisplayMouseWheel(Sender: TObject; Shift: TShiftState;
2.   WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
3. Var
4.   ZD : Single;       // Zoom Direction / Magnitude
5. begin
6.   ZD := WheelDelta/110;
7.   if Sign(ZD) = -1 then
8.     Mag := ABS(Mag/ZD)
9.   else
10.     Mag := Mag*ZD;
11.
12.   if Mag < 0.1 then
13.     Mag := 0.1;
14.
15.   if Mag > MaxZoom then
16.     Mag := MaxZoom;
17.
18.   Zoom.Position := Round(Mag*100);
19.   Calc(self);
20. end;
It hadn't previously occured to me to DIVIDE by the WheelDelta if Zooming out - nor to check if it was negative - the 'Sign' is certainly a useful test which I hadn't found before.

Empirically I've found that dividing the WheelDelta by 110 gives good control and now appreciate that that number essentially controls the 'sensitivity' of the Mouse Wheel. I tried it at 120 and of course found that there was no 'zoom' !!   but I found little real difference if I used 60 - yes it was 'faster' but not massively, and 118 was perceptably slower.

@jamie  -  Yes, as you can see that is exactly what I do.

FPC 3.0.0 - Lazarus 1.6 &
FPC 3.2.2  - Lazarus 2.2.0
Win 7 Ult 64

#### jamie

• Hero Member
• Posts: 4922
##### Re: Using the Mouse Wheel to Zoom
« Reply #4 on: August 13, 2022, 08:21:58 pm »
Hmm..
Would this be easier to calculate ?

Code: Pascal  [Select][+][-]
1.   WheelDelta := Sign(WheelDelta)+Abs(WheelDelta)-120;
2.    Width := Width+WheelDelta;
3.    Height := height+WheelDelta;
4.

that simply reduces it down but still, this only works if all widgets' fallows and there is a chance of different micky resolutions where in some cases drafters use a highres joystick etc.
The only true wisdom is knowing you know nothing

#### J-G

• Hero Member
• Posts: 931
##### Re: Using the Mouse Wheel to Zoom
« Reply #5 on: August 13, 2022, 09:02:19 pm »
Thanks for the input @jamie but since I only need to know the magnification factor - not width/height - I don't really see where your code has a benefit.
FPC 3.0.0 - Lazarus 1.6 &
FPC 3.2.2  - Lazarus 2.2.0
Win 7 Ult 64

#### jamie

• Hero Member
• Posts: 4922
##### Re: Using the Mouse Wheel to Zoom
« Reply #6 on: August 14, 2022, 02:27:22 am »
You can't see the benefit ?

With only one line of code, I reduce the + or - down to a -1 or 1 which can be used following without checking for the < 1 and > 0 etc.

You can use your MAG multiplier afterwards on that same value.

Also, you should test the size of the DeltaWheel because it can change, and your program will be left acting like a clown. There is an API for that too.

Do whatever makes your boat float as I say.
The only true wisdom is knowing you know nothing

#### dje

• Full Member
• Posts: 124
##### Re: Using the Mouse Wheel to Zoom
« Reply #7 on: August 14, 2022, 05:06:19 am »
Why not just add WheelDelta to TrackBar Position? First set the TrackBar's max to 1000. Then:

Code: Pascal  [Select][+][-]
1. procedure TForm1.Panel1MouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: integer;
2.   MousePos: TPoint; var Handled: boolean);
3. begin
4.   TrackBar1.Position := TrackBar1.Position + WheelDelta;
5. end;

Setting TrackBar Position via code will trigger a OnChange event. Inside TTrackBar OnChange, calculate the percentage using:
Code: Pascal  [Select][+][-]
1. TrackBar1.Position * 100 div TrackBar1.Max

« Last Edit: August 14, 2022, 05:11:21 am by derek.john.evans »

#### J-G

• Hero Member
• Posts: 931
##### Re: Using the Mouse Wheel to Zoom
« Reply #8 on: August 14, 2022, 08:05:56 pm »
You can't see the benefit ?

With only one line of code, I reduce the + or - down to a -1 or 1 which can be used following without checking for the < 1 and > 0 etc.

You can use your MAG multiplier afterwards on that same value.

Also, you should test the size of the DeltaWheel because it can change, and your program will be left acting like a clown. There is an API for that too.

Do whatever makes your boat float as I say.
Thanks @jamie but I'm obviously being a numbskull  - - -

I've just tried what I think you are suggesting :
Code: Pascal  [Select][+][-]
1. procedure TForm1.DisplayMouseWheel(Sender: TObject; Shift: TShiftState;
2.   WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
3. begin
4.   WheelDelta := Sign(WheelDelta)+Abs(WheelDelta)-120;
5.   Mag := Mag*WheelDelta;
6.
7.   if Mag < 0.1 then
8.     Mag := 0.1;
9.   if Mag > MaxZoom then
10.     Mag := MaxZoom;
11.
12.   Zoom.Position := Round(Mag*100);
13.   Calc(self);
14. end;
...but the result of that is again 'Zooming Out' puts 'Mag' at minimum only.

I also don't understand what you mean by "test the size of the DeltaWheel"  -  Unless you are saying that 120 just happens to be the figure that my current mouse has and is not an industry standard - perfectly possible of course, I haven't previously had a need to investigate such things.

FPC 3.0.0 - Lazarus 1.6 &
FPC 3.2.2  - Lazarus 2.2.0
Win 7 Ult 64

#### J-G

• Hero Member
• Posts: 931
##### Re: Using the Mouse Wheel to Zoom
« Reply #9 on: August 14, 2022, 08:27:31 pm »
@derek.john.evans
Depending upon many factors, the Maximum Zoom changes, and I currently set the Max TTrack Value once I know what the MaxZoom is :-
Code: Pascal  [Select][+][-]
1.       MaxZoom := 267/(Gear.OD*Scale-Gear.PCD*Scale)-0.1;
2.
3.       Form1.Zoom.Max := Round(MaxZoom*100);

Gear.OD & Gear.PCD are variable (not cosistently) but the display space available between them is a maximum of 267px (on an 800px Panel). I could of course make it even more 'general' by using 'Panel.Height DIV 3' rather than the specific 267 - then I could vary the size of the Panel and it would still 'work'
FPC 3.0.0 - Lazarus 1.6 &
FPC 3.2.2  - Lazarus 2.2.0
Win 7 Ult 64