问题
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?
回答1:
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.
回答2:
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.
- Create a new VCL Forms application (or FMX application - replace
TShape
withTMemo
or any other control with anOnMouseDown
andOnMouseUp
event in the following steps) - Drop a
TShape
on the left side of the form. - Drop a
TLabel
to the right of thatTShape
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.
来源:https://stackoverflow.com/questions/21521151/do-onmousedown-and-onmouseup-only-work-as-a-pair