Мне нужен код, который способен перехватить несколько нажатий на планшет в тот же момент. В previous question относительно того, как обращаться с несколькими OnMouseDown в тот же момент (не представляется возможным), был предоставлен link, который ответил на вопрос о том, как обрабатывать клики с несколькими касаниями в Delphi-Android. Однако этот код возвращает (x, y) позиции в координатах экрана, и я не знаю, как их перевести в локальные координаты конкретного элемента управления. Delphi documentation относится к функции ScreenToClient, но это только преобразует координаты экрана для формирования координат, что вряд ли полезно в Android (документация о XE2, но функция все еще существует в XE5, но функция была удалена с FMX.Platform на FMX. Форма).Как преобразовать координаты экрана в координаты управления
Есть ли простой способ преобразования координат экрана в координаты TControl в FMX, например, в VCL? Конечно, я могу «де-родитель» контролировать, обозначать его верхние левые координаты и делать это для каждого родителя, пока не достигнет базовой формы, но это довольно утомительно.
Edit 1
Мой текущий подход, чтобы получить вершину (х, у) Координаты TControl (а TPanel), который является родителем для управления должны быть резьбовыми (TRectangle-х на самом деле), и добавить их чтобы проверить, находится ли этот прямоугольник внутри этого прямоугольника. См. Пример кода ниже.
procedure TKeyBoard.process_touch (Event: TTouchEvent; status_byte: Int32);
var
key: TKey;
p, q: TPointF;
i: Integer;
x, y: single;
begin
// Check whether at least one event is present. If so, i points to the last event
i := Length (Event.Points) - 1;
if i < 0 then Exit;
// Get (x, y) coordinates from event. It's in screen coordinates
x := Event.Points [i].Position.X;
y := Event.Points [i].Position.Y;
// FControl is a reference to the panel holding the keys
// Find its rectangle position and convert to screen coordinates
p := TPointF.Create (FControl.Position.X, FControl.Position.Y);
q := TPointF.Create (p.X + FControl.Width, p.Y + FControl.Height);
p := Application.MainForm.ClientToScreen (p);
q := Application.MainForm.ClientToScreen (q);
logd ('control [%.0f %.0f - %.0f, %.0f]', [FControl.Position.X, FControl.Position.Y, FControl.Width, FControl.Height]);
logd ('to screen [%.0f %.0f - %.0f, %.0f]', [p.X, p.Y, q.X, q.Y]);
// Determine whether a black key has been pressed
for i := Low (Fkeys) to High (FKeys) do
begin
if not cOctave_Major [i mod nOctave] then
begin
key := FKeys [i];
logd ('%d (%.0f, %.0f) - (%.0f, %.0f) (%.0f, %.0f)', [i, x, y,
key.Position.X + p.X, key.Position.Y + p.Y,
key.Position.X + P.X + Key.Width, key.Position.Y + p.Y + key.Height]);
if (x >= key.Position.X + p.X) and (x <= key.Position.X + p.X + Key.Width) and
(y >= key.Position.Y + p.Y) and (y <= key.Position.Y + p.Y + key.Height)
then break;
key := nil;
end; // if
end; // for
// if not, check whether a white key has been pressed
if key = nil then
begin
logd ('Major');
for i := Low (Fkeys) to High (FKeys) do
begin
if cOctave_Major [i mod nOctave] then
begin
key := FKeys [i];
logd ('%d (%.0f, %.0f) - (%.0f, %.0f) (%.0f, %.0f)', [i, x, y,
key.Position.X + p.X, key.Position.Y + p.Y,
key.Position.X + P.X + Key.Width, key.Position.Y + p.Y + key.Height]);
if (x >= key.Position.X + p.X) and (x <= key.Position.X + p.X + Key.Width) and
(y >= key.Position.Y + p.Y) and (y <= key.Position.Y + p.Y + key.Height)
then break;
key := nil;
end; // if
end; // for
end; // if
if key <> nil
then putShort (status_byte, key.Note, 127);
if key <> nil
then logd (' found %s', [key.Text.Text]);
end; // process_touch //
Этот код на самом деле очень неопрятно, потому что она предполагает, что контроль Родитель имеет Application.MainForm в качестве родителя, который не нужно быть. Другое замечание состоит в том, что краны могут все еще быть немного неправильными в Y-положении. По этой причине я хочу передать координаты экрана непосредственно в координаты элемента управления.
Edit 2
Я пытался использовать чек IsMouseOver для каждого ключа управления, как предложено @Sentient, но как ни странно, что только дает истинное, когда событие MouseUp обрабатывается.
бы с помощью .IsMouseOver из ваших управления работают? Я не знаю, правильно ли это регистрируется, когда есть несколько касаний одновременно. – Sentient
Увы, это не работает на Android. Он запускается во время события MouseUp, а не во время MouseDown. – Arnold