### Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

### Author Topic: [SOLVED] TPanel slider position  (Read 2101 times)

#### Pe3s

• Hero Member
• Posts: 533
##### [SOLVED] TPanel slider position
« on: November 28, 2023, 11:09:59 am »
Hello forum members, what do I need to correct in the code to make the adjustment range -100 - 0 - 100 work?
Code: Pascal  [Select][+][-]
1. procedure TForm1.Panel2MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
2. begin
3.   if not(ssLeft in Shift) then Exit;
4.   Pos := X + Panel2.Left;
5.   Max := Panel1.ClientWidth - Panel2.Width;
6.   if Pos < 0 then Pos := 0;
7.   if Pos > Max then Pos := Max;
8.   Panel2.Left := Pos;
9.
10.   BGProgress.Value := Round(100 * Pos / Max);
11.   Form1.Caption := IntToStr(BGProgress.Value);
12. end;
13.
14. procedure TForm1.Panel1MouseDown(Sender: TObject; Button: TMouseButton;
15.   Shift: TShiftState; X, Y: Integer);
16. begin
17.   if not (ssLeft in Shift) then Exit;
18.   Pos:= X;
19.   Max := Panel1.ClientWidth - Panel2.Width;
20.   if Pos < 0 then Pos := 0;
21.   if Pos > Max then Pos := Max;
22.   Panel2.Left:= Pos;
23.
24.   BGProgress.Value := Round(100 * Pos / Max);
25.   Form1.Caption := IntToStr(BGProgress.Value);
26. end;
« Last Edit: December 03, 2023, 05:47:08 pm by Pe3s »

#### Handoko

• Hero Member
• Posts: 5106
• My goal: build my own game engine using Lazarus
##### Re: TPanel slider position
« Reply #1 on: November 28, 2023, 01:59:47 pm »
Done.

This is the correct formula:
BGProgress.Value := Round(200 * Pos / Max) - 100;
« Last Edit: November 28, 2023, 02:07:07 pm by Handoko »

#### Pe3s

• Hero Member
• Posts: 533
##### Re: TPanel slider position
« Reply #2 on: November 28, 2023, 04:20:03 pm »
@Handoko, Thank you for your help

• Hero Member
• Posts: 13991
• Probably until I exterminate Putin.
##### Re: [SOLVED] TPanel slider position
« Reply #3 on: November 29, 2023, 09:21:09 am »
I believe the correct formula to be BGProgress.Value := (200 * Pos  div Max) - 100;, Handoko.
That processes completely in the integer domain.
« Last Edit: November 29, 2023, 09:24:00 am by Thaddy »
Specialize a type, not a var.

#### Handoko

• Hero Member
• Posts: 5106
• My goal: build my own game engine using Lazarus
##### Re: [SOLVED] TPanel slider position
« Reply #4 on: November 30, 2023, 04:07:12 am »
Yes, you're right.

I forgot that div is more efficient than / for result in integer.

#### Pe3s

• Hero Member
• Posts: 533
##### Re: [SOLVED] TPanel slider position
« Reply #5 on: December 02, 2023, 07:19:15 pm »
I have one more question why the code works with Panel components but not with Image ?

Code: Pascal  [Select][+][-]
1. procedure TForm1.Panel2MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
2. var
3.   NewX, Max: Integer;
4. begin
5.   if not(ssLeft in Shift) then Exit;
6.   NewX := X + Panel2.Left -20;
7.   Max := Panel1.ClientWidth - Panel2.Width;
8.   if NewX < 0 then NewX := 0;
9.   if NewX > Max then NewX := Max;
10.   Panel2.Left := NewX;
11.
12.   Label1.Caption := GetPosition.ToString;
13. end;

#### Handoko

• Hero Member
• Posts: 5106
• My goal: build my own game engine using Lazarus
##### Re: TPanel slider position
« Reply #6 on: December 02, 2023, 07:50:21 pm »
I modified your code by renaming Panel2 to Image1, it works.

If you can't make it works, please provide a demo so I can download and inspect the problem.

#### Pe3s

• Hero Member
• Posts: 533
##### Re: TPanel slider position
« Reply #7 on: December 02, 2023, 09:19:05 pm »
TImage counts Positions differently

#### Handoko

• Hero Member
• Posts: 5106
• My goal: build my own game engine using Lazarus
##### Re: TPanel slider position
« Reply #8 on: December 03, 2023, 04:08:45 am »
Done!

Code: Pascal  [Select][+][-]
1. unit Unit1;
2.
3. {\$mode objfpc}{\$H+}
4.
5. interface
6.
7. uses
8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls;
9.
10. type
11.
12.   { TForm1 }
13.
14.   TForm1 = class(TForm)
15.     Image1: TImage;
16.     Image2: TImage;
17.     Label1: TLabel;
18.     procedure Image2MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer
19.       );
20.   end;
21.
22. var
23.   Form1: TForm1;
24.
25. implementation
26.
27. {\$R *.lfm}
28.
29. { TForm1 }
30.
31. procedure TForm1.Image2MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
32. const
33.   ResultMin = 0;
34.   ResultMax = 100;
35. var
36.   AllowedMin,
37.   AllowedMax,
38.   Result:      Integer;
39. begin
40.
41.   if not(ssLeft in Shift) then Exit;
42.
43.   AllowedMin := Image1.Left;
44.   AllowedMax := Image1.Left + Image1.Width - Image2.Width;
45.
46.   Image2.Left := Image2.Left + X - (Image2.Width div 2);
47.   if Image2.Left < AllowedMin then Image2.Left := AllowedMin;
48.   if Image2.Left > AllowedMax then Image2.Left := AllowedMax;
49.
50.   Result := ((ResultMax-ResultMin) *
51.             (Image2.Left-AllowedMin) div
52.             (AllowedMax-AllowedMin)) + ResultMin;
53.   Label1.Caption := Result.ToString;
54.
55. end;
56.
57. end.

• First of all, lets talk about moving the handle. See line #46. That may seem complicated. But actually the basic formula is very simple:
Image2.Left := Image2.Left + X;
• Now, see the img2 below. Because the handle has width, to make the the pointer to detect the center of the handle, it needs to do:
- (Image2.Width div 2)
• Now back to the formula you already know:
= Round(100 * Pos / Max)
• Actually the main formula is something like this:
= ( the_range * position / maximum_allowed ) + starting_value
• If you want to have -100.0.100 in the result, change the values in the lines #33..#34, and run the code. Now look at the line #50, you can see why the_range becomes ResultMax-ResultMin. And because you want the -100 as the starting_value, you have to do +ResultMin as you see in the line #52.
• About the div in the formula. Div runs faster than /. And div always gives integer result, so you don't have to do Round.

#### Pe3s

• Hero Member
• Posts: 533
##### Re: TPanel slider position
« Reply #9 on: December 03, 2023, 10:03:06 am »
@Handoko, I have one more question regarding the onMouseDown procedure, how can I modify the code to move the dot on mouse click?
Change the code on line 46
Code: Pascal  [Select][+][-]
1. Image2.Left := X;
does not place the dot in the correct position

#### Handoko

• Hero Member
• Posts: 5106
• My goal: build my own game engine using Lazarus
##### Re: TPanel slider position
« Reply #10 on: December 03, 2023, 10:19:18 am »

Code: Pascal  [Select][+][-]
1. procedure TForm1.Image1Click(Sender: TObject);
2. var
3.   NewPos:TPoint;
4. begin
5.   NewPos := ScreenToClient(Mouse.CursorPos);
6.   Image2.Left := NewPos.X - (Image2.Width div 2);
7. end;

You can get the mouse pointer position by using Mouse.CursorPos. But before you can use that values, you need to convert it by using ScreenToClient function.

#### Pe3s

• Hero Member
• Posts: 533
##### Re: TPanel slider position
« Reply #11 on: December 03, 2023, 10:30:24 am »
@Handoko, I am grateful for your help. Thank you
Greetings with a smile

#### Pe3s

• Hero Member
• Posts: 533
##### Re: [SOLVED] TPanel slider position
« Reply #12 on: December 03, 2023, 12:47:50 pm »
Code: Pascal  [Select][+][-]
1. Image2.Left := image1.Width * POS div ResultMax;

#### Handoko

• Hero Member
• Posts: 5106
• My goal: build my own game engine using Lazarus
##### Re: TPanel slider position
« Reply #13 on: December 03, 2023, 02:41:25 pm »
Not sure what did you mean. Maybe something like this:

Code: Pascal  [Select][+][-]
1. unit Unit1;
2.
3. {\$mode objfpc}{\$H+}
4.
5. interface
6.
7. uses
8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls;
9.
10. type
11.
12.   { TForm1 }
13.
14.   TForm1 = class(TForm)
15.     Image1: TImage;
16.     Image2: TImage;
17.     Label1: TLabel;
18.     lbeGoto: TLabeledEdit;
19.     lbeResultMax: TLabeledEdit;
20.     lbeResultMin: TLabeledEdit;
21.     procedure FormCreate(Sender: TObject);
22.     procedure Image1Click(Sender: TObject);
23.     procedure Image2MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer
24.       );
25.     procedure lbeGotoEditingDone(Sender: TObject);
26.     procedure lbeResultMaxEditingDone(Sender: TObject);
27.     procedure lbeResultMinEditingDone(Sender: TObject);
28.   private
29.     FResultMin: Integer;
30.     FResultMax: Integer;
31.     procedure CalculatePosition;
32.     procedure GotoPosition(Pos: Integer);
33.   end;
34.
35. var
36.   Form1: TForm1;
37.
38. implementation
39.
40. {\$R *.lfm}
41.
42. { TForm1 }
43.
44. procedure TForm1.lbeResultMaxEditingDone(Sender: TObject);
45. var
46.   NewValue: Integer;
47. begin
48.   if not(TryStrToInt(lbeResultMax.Text, NewValue)) then
49.   begin
50.     lbeResultMax.Text := IntToStr(FResultMax);
51.     Exit;
52.   end;
53.   if NewValue <= FResultMin then
54.   begin
55.     lbeResultMax.Text := IntToStr(FResultMax);
56.     Exit;
57.   end;
58.   FResultMax := NewValue;
59.   CalculatePosition;
60. end;
61.
62. procedure TForm1.lbeResultMinEditingDone(Sender: TObject);
63. var
64.   NewValue: Integer;
65. begin
66.   if not(TryStrToInt(lbeResultMin.Text, NewValue)) then
67.   begin
68.     lbeResultMin.Text := IntToStr(FResultMin);
69.     Exit;
70.   end;
71.   if NewValue >= FResultMax then
72.   begin
73.     lbeResultMin.Text := IntToStr(FResultMin);
74.     Exit;
75.   end;
76.   FResultMin := NewValue;
77.   CalculatePosition;
78. end;
79.
80. procedure TForm1.lbeGotoEditingDone(Sender: TObject);
81. var
82.   NewValue: Integer;
83. begin
84.   if not(TryStrToInt(lbeGoto.Text, NewValue)) then Exit;
85.   if (NewValue < FResultMin) or (NewValue > FResultMax) then Exit;
86.   lbeGoto.Text := '';
87.   GotoPosition(NewValue);
88. end;
89.
90. procedure TForm1.Image1Click(Sender: TObject);
91. var
92.   NewPos:TPoint;
93. begin
94.   NewPos      := ScreenToClient(Mouse.CursorPos);
95.   Image2.Left := NewPos.X - (Image2.Width div 2);
96.   CalculatePosition;
97. end;
98.
99. procedure TForm1.Image2MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
100. var
101.   AllowedMin,
102.   AllowedMax : Integer;
103. begin
104.
105.   if not(ssLeft in Shift) then Exit;
106.
107.   AllowedMin := Image1.Left;
108.   AllowedMax := Image1.Left + Image1.Width - Image2.Width;
109.
110.   Image2.Left := Image2.Left + X - (Image2.Width div 2);
111.   if Image2.Left < AllowedMin then Image2.Left := AllowedMin;
112.   if Image2.Left > AllowedMax then Image2.Left := AllowedMax;
113.
114.   CalculatePosition;
115.
116. end;
117.
118. procedure TForm1.FormCreate(Sender: TObject);
119. begin
120.   FResultMin := StrToInt(lbeResultMin.Text);
121.   FResultMax := StrToInt(lbeResultMax.Text);
122. end;
123.
124. procedure TForm1.CalculatePosition;
125. var
126.   Result: Integer;
127. begin
128.   Result := ((FResultMax-FResultMin) *
129.             (Image2.Left-Image1.Left) div
130.             (Image1.Width-Image2.Width)) + FResultMin;
131.   Label1.Caption := Result.ToString;
132. end;
133.
134. procedure TForm1.GotoPosition(Pos: Integer);
135. begin
136.   Image2.Left := Round((Pos-FResultMin) * (Image1.Width-Image2.Width) /
137.                  (FResultMax-FResultMin) + Image1.Left);
138.   Label1.Caption := Pos.ToString;
139. end;
140.
141. end.

#### Pe3s

• Hero Member
• Posts: 533
##### Re: TPanel slider position
« Reply #14 on: December 03, 2023, 04:45:31 pm »
I meant how to calculate the progress of the bar with automatic progress, e.g. time elapsed, as is the case in players.

Code: Pascal  [Select][+][-]
1. Image2.Left := AParam * (Image1.Width -image2.Width div 2) div ResultMax;

AParam(current position)

the above line of code counts the time correctly, but at startup it goes back to the left side, so I would like to correct it
I am attaching a screenshot video of the bar