Recent

Author Topic: [SOLVED] Keep an action repeating while a TButton is pressed.  (Read 15146 times)

CM630

  • Hero Member
  • *****
  • Posts: 1521
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
[SOLVED] Keep an action repeating while a TButton is pressed.
« on: January 07, 2014, 05:03:00 pm »
The task is to change the values of a an element  (a variable or a visual control, like for example SpinEdit) while a button is pressed. One of the buttons shall increase the value and the other one should decrease it.
So for an example I created a TSpinEdit, two buttons (ButtonUp and ButtonDown) and a Timer1, disabled by default, and I declared a SpinInc: Integer;

First obstacle is that I could not find how to detect if the button is pressed.
I did :
Code: [Select]
procedure TForm1.ButtonUpClick(Sender: TObject);
begin
  SpinEdit1.Value:=SpinEdit1.Value+1;
end;

procedure TForm1.ButtonUpMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
    SpinInc:=1;
    Timer1.Enabled:=True;
end;

procedure TForm1.ButtonUpMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
   Timer1.Enabled:=False;
end;

procedure TForm1.ButtonDownClick(Sender: TObject);
begin
    SpinEdit1.Value:=SpinEdit1.Value-1;
end;

procedure TForm1.ButtonDownMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  SpinInc:=-1;
  Timer1.Enabled:=True;
end;

procedure TForm1.ButtonDownMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  Timer1.Enabled:=False;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  SpinEdit1.Value:=SpinEdit1.Value + SpinInc;
end;
It sort of works, with the exception when the button is clicked by the keyboard (TAB to it and press spacebar).
In order to do it, I have to use also OnKeyDown and OnKeyUp, checking if the key is Spacebar.
Maybe there is a simpler solution?
I tried BitButton and SpeedButton, but they have no pressed property neither.
« Last Edit: January 10, 2014, 10:17:16 am by paskal »
Лазар 4,2 32 bit (sometimes 64 bit); FPC3,2,2

wp

  • Hero Member
  • *****
  • Posts: 13192
Re: Keep an action repeating while a TButton is pressed.
« Reply #1 on: January 07, 2014, 05:21:09 pm »
Isn't this behavior built into TSpinEdit and TFloatSpinEdit?

CM630

  • Hero Member
  • *****
  • Posts: 1521
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Keep an action repeating while a TButton is pressed.
« Reply #2 on: January 07, 2014, 05:57:28 pm »
I actually mean to use this for something else (moving a point in TAChart), but SpinEdit was the first numeric control that occurred to me.
Лазар 4,2 32 bit (sometimes 64 bit); FPC3,2,2

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Keep an action repeating while a TButton is pressed.
« Reply #3 on: January 07, 2014, 06:21:53 pm »
The Common Controls page also offers TTrackBar and TUpDown, either of which might suit your purpose.

CM630

  • Hero Member
  • *****
  • Posts: 1521
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Keep an action repeating while a TButton is pressed.
« Reply #4 on: January 08, 2014, 08:21:34 am »
Now I realize that my example is too specific, while I am searching a more general purpose solution, so I edited my first post
Maybe another example will explain things more globally.
I have 9 buttons, for each direction and I have a button with an asterisk on it (see image attached). How am I to move the button with the asterisk while a button for the corresponding direction is pressed (button is pressed- asterisk moves, an it will stop moving when the button is released).

I cannot use track bar, because it is something else, and I cannot use TUpDown, because I need to change the image on the button.
EDIT: Now I checked to find that I am using TArrows (so it occurs it cannot handle keyboard clicks), but I'd prefer to switch to TSpeedButtons.
« Last Edit: January 08, 2014, 08:31:46 am by paskal »
Лазар 4,2 32 bit (sometimes 64 bit); FPC3,2,2

wp

  • Hero Member
  • *****
  • Posts: 13192
Re: Keep an action repeating while a TButton is pressed.
« Reply #5 on: January 08, 2014, 09:10:35 am »
TSpeedButton doesn't handle the keyboard either...

The only solution that I see is using a Timer which activates at MouseDown on a button and which moves the target with each OnTimer event. Taking the Sender parameter of the MouseDown event of the button allows you to determine the button clicked and the direction to go. This shouldn't be too hard.

Maybe there are buttons with "autofire" capabilities somewhere (Rx?), but this usually comes with the burdon of installing an entire library needed for nothing else.

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Keep an action repeating while a TButton is pressed.
« Reply #6 on: January 08, 2014, 01:34:58 pm »
The attached project is one you can adapt using speedbuttons in the way I think you are looking for.

CM630

  • Hero Member
  • *****
  • Posts: 1521
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Keep an action repeating while a TButton is pressed.
« Reply #7 on: January 09, 2014, 01:37:28 pm »
Thanks for the ideas, they are quite similar to my code, so I know I'm on the right way.
Still I can't get how it is possible for the TButton not to have a pressed property, but I will put the blame on Delphi. ;D
Лазар 4,2 32 bit (sometimes 64 bit); FPC3,2,2

wp

  • Hero Member
  • *****
  • Posts: 13192
Re: Keep an action repeating while a TButton is pressed.
« Reply #8 on: January 09, 2014, 02:20:04 pm »
Why do you need a "pressed" property? You have the events OnMouseDown and OnMouseUp...

See this example where the Label1 counts up while the Mouse is held down on the button, but stops when it is released:

Code: [Select]
var
  Counter: Integer = 0;

procedure TForm1.Button1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  Timer1.Enabled := true;
end;

procedure TForm1.Button1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  Timer1.Enabled := false;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Label1.Caption := IntToStr(Counter);
  inc(Counter);
end;

CM630

  • Hero Member
  • *****
  • Posts: 1521
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Keep an action repeating while a TButton is pressed.
« Reply #9 on: January 10, 2014, 08:42:46 am »
@WP, you code is exactly the same as mine.
Pressed would be useful, because I could simply use a timer like


Code: [Select]
procedure TForm1.Timer1Timer(Sender: TObject);
begin
      if ButtonLeft.pressed then ...
       if ButtonRight.pressed then ...
end;
Maybe I'm used to other IDEs.

I will decide how exactly to I do it, I can emulate a pressed property, if I find it easier.
« Last Edit: January 10, 2014, 09:13:00 am by paskal »
Лазар 4,2 32 bit (sometimes 64 bit); FPC3,2,2

wp

  • Hero Member
  • *****
  • Posts: 13192
Re: Keep an action repeating while a TButton is pressed.
« Reply #10 on: January 10, 2014, 09:11:03 am »
Quote
      if ButtonLeft.pressed then ...
       if ButtonRight.pressed then ...

I still don't see the problem in typing 2-3 lines: It would be the first thing to log the button pressed in the MouseDown event

Code: [Select]
var
  StoredShift: TShiftState;

procedure TForm1.Button1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  StoredShift := Shift;
  Timer1.Enabled := true;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  if StoredShift = ssLeft then ...
  if StoredShift = ssRight then...
end

CM630

  • Hero Member
  • *****
  • Posts: 1521
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: [SOLVED] Keep an action repeating while a TButton is pressed.
« Reply #11 on: January 10, 2014, 10:22:06 am »
There is no problem in storing the shifts- you have emulated a pressed state. For some reason I expected that a more native existed. Everything can be solve by adding a few (thousand of) line, just too many times I've reimplemented existing features.
Anyway, here's my final solution, it works, so I won't touch it:
I had
Code: [Select]
TArrowStar= Record
ArrowLeftPressed: Boolean;
  ArrowUpPressed: Boolean;
  ArrowRightPressed: Boolean;
  ArrowDownPressed: Boolean;
end;
   


so I just added a few lines
 
Code: [Select]
TArrowStar= Record
  ArrowLeft:  TArrow;
  ArrowUp:    TArrow;
  ArrowRight: TArrow;
  ArrowDown:  TArrow;
  ArrowLeftPressed: Boolean;
  ArrowUpPressed: Boolean;
  ArrowRightPressed: Boolean;
  ArrowDownPressed: Boolean;
end;
Лазар 4,2 32 bit (sometimes 64 bit); FPC3,2,2

 

TinyPortal © 2005-2018