Question

My application has a lot of TRectangle's acting as keys of a keyboard. When one is clicked you hear a sound. This is done by handling the OnMouseDown and OnMouseUp event. OnMouseDown: send a sound and OnMouseUp: switch it off. All works fine, except for one thing.

On Android I can use several fingers to press several keys. When one OnMouseDown has been processed, no other OnMouseDown Events will be processed until an OnMouseUp event has been processed. It needn't be the OnMouseUp of the key that blocked the other OnMouseDown, it may be any OnMouseUp event. Sample code:

procedure TKeyBoard.note_down (Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
var
   key: TKey;
begin
   key := Sender as TKey;
   logd ('Entering OnMouseDown event handler: %d', [key.Note]);
   PutShort ($90, key.Note, 127);
   logd ('Exiting OnMouseDown event handler: %d', [key.Note]);
end; // note_down //

procedure TKeyBoard.note_up (Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
var
   key: TKey;
begin
   key := Sender as TKey;
   logd ('Entering OnMouseUp event handler: %d', [key.Note]);
   PutShort ($80, Key.Note, 127);
   logd ('Exiting OnMouseUp event handler: %d', [key.Note]);
end; // note_up //
...
Rectangle [i].OnMouseDown := note_down;
Rectangle [i].OnMouseUp   := note_up;

Where the note_down and note_up routines are entered and exited immediately according to the debug code. Is it right to assume that when an OnMouseDown has been processed, no OnMouseDown's can be processed until an OnMouseUp has been handled? If so, is there a workaround?

Was it helpful?

Solution

Give OnMouseEnter a shot for mobile. I'm working on a project with lots of rectangles and in my code I have

{$ifdef MSWINDOWS}
lRect.OnClick := ClickEvent;
{$else}
lRect.OnMouseEnter := ClickEvent;
{$endif}

What this allows me to do is drag my finger across a grid of rectangles and have it call my ClickEvent for each rectangle I pass over.

OTHER TIPS

By logic, a MouseDown event has to be followed by (paired) with a MouseUp event. It's the way the mouse physically operates.

The mouse button is pressed (which means it becomes "down"). It can't be pressed again until it is released and goes back to the "up" state. (There is no such thing as a "mouse partially down", "mouse a little further down", "mouse down even a little bit more" state; the mouse button is either pressed ("down") or unpresssed ("up").

The only reasonable progression is MouseDown followed by a corresponding (paired) MouseUp. The Sender for both messages may not be the same control - the mouse can become pressed over one control, moved while the button remains down, and then released over a different control (or even outside the application itself) - but the sequence must be "down, then up" in that order.

Here's a quick way to demonstrate that behavior and logic.

  1. Create a new VCL Forms application (or FMX application - replace TShape with TMemo or any other control with an OnMouseDown and OnMouseUp event in the following steps)
  2. Drop a TShape on the left side of the form.
  3. Drop a TLabel to the right of that TShape

Click on the TShape, switch to the Events tab in the Object Inspector, and add the following event handlers for the Shape1.OnMouseDown and Shape1.OnMouseUp events:

procedure TForm1.Shape1MouseDown(Sender: TObject);
begin
  Label1.Caption := 'Mouse down';
  Label1.Update;
end;

procedure TForm1.Shape1MouseUp(Sender: TObject);
begin
  Label1.Caption := 'Mouse up';
  Label1.Update;
end;

Run the app. Put the mouse over Shape1 and press the button. Notice the text of the label, which displays "Mouse down". Release it and the caption of the label changes to "Mouse up".

Experiment with pressing the mouse button over the shape to set the label's caption to "Mouse down" and then moving the mouse to various locations and releasing the button, watching the label change to "Mouse up" each time the button is released regardless of the location of the mouse pointer.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top