Do OnMouseDown and OnMouseUp only work as a pair?
Asked Answered
A

2

2

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?

Andreaandreana answered 3/2, 2014 at 6:39 Comment(0)
C
2

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.

Cellini answered 5/2, 2014 at 23:53 Comment(5)
I will try this later on the day. And use OnMouseExit when lifting the finger? It appears to solve one potential problem: how to detect a finger that quickly moves over the keys.Andreaandreana
I assume OnMouseExist would work well, I haven't used it myself though. I was thinking about this later and realized it doesn't solve the multi-touch problem. You could look at this link that could might help you with the multi-touch.Cellini
I will try this as soon as I get every thing working for Android again :-( If the multi touch support does not work I'll try your link (nice link btw). Thanks a lot for your suggestions! If any of the two works I'll accept your answer (might take some time).Andreaandreana
Using OnMouseEnter with OnMouseLeave has the same problems with OnMouseUp/Down. It has one advantage, I can quickly move my finger along all keys :-) The link you provided is a good work-around for multi-touch. Thank you very much, now I'm able to play chords on my MIDI keyboard ;-)Andreaandreana
Just in case anyone is using the link I posted earlier for iOS: cromis.net/blog/2014/02/…Cellini
R
1

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.

Revoice answered 5/2, 2014 at 23:36 Comment(3)
My experiments led me to the same conclusion. That's why I am interested in a workaround. Is there any way to detect several mousedowns followed by several mouse ups?Andreaandreana
Not to my knowledge, because as I've explained, that's a physical impossibility. If the mouse can't physically generate a second mouse down from inside an existing mouse down (because the button can't physically move down without moving up first), it can't generate out of order events. (There may be other events you can use instead, depending on the behavior you're actually needing, but that isn't what you asked about here. Your question specifically was "Do OnMouseDown and OnMouseUp only work as a pair?", which is the question I answered. :-)Revoice
Mmmm, there was a sentence about a workaround ;-) Anyhow, Thanks for your thorough explanation. You are right as concerning the mouse. Point is, on an Android tablet a tap generates a mouse click and as one can use several fingers at the same time, several OnMouseDowns could be generated without an OnMouseUp. Cross platform ain't that easy :-)Andreaandreana

© 2022 - 2024 — McMap. All rights reserved.