我需要的代码能够拦截平板电脑上同时发生的多次点击。在一篇关于如何处理多个OnMouseDown同时发生的问题(不可能)的之前的问题中,提供了一个链接来解决Delphi-Android中如何处理多点触控的问题。然而,这段代码返回屏幕坐标系下的(x, y)位置,我不知道如何将其转换为特定控件的本地坐标系。Delphi的文档提到了一个ScreenToClient函数,但它只能将屏幕坐标系转换为窗体坐标系,对于Android来说几乎没什么用处(文档是关于XE2的,但该函数仍存在于XE5中,但已经从FMX.Platform移动到了FMX.Form)。
在FMX中是否有将屏幕坐标转换为TControl坐标的简单方法,就像在VCL中一样?当然,我可以“去除”控件的父级,记录其左上角坐标,并对每个父级重复此操作,直到到达基础表单,但这相当繁琐。
我的当前方法是获取TControl(实际上是TPanel)的顶部(x,y)坐标,该TControl是要被点击的控件(实际上是TRectangle's的子项),并将这些坐标加起来以检查单击是否在该矩形内。请参见下面的示例代码。
这段代码实际上很混乱,因为它假设父控件的父级是Application.MainForm,但这并不一定是正确的。另一个观察结果是,标签可能在Y轴方向上仍然略有偏差。因此,我想直接将屏幕坐标转换为控件坐标以解决这个问题。
编辑2: 我尝试使用@Sentient建议的IsMouseOver检查每个关键控件,但奇怪的是,只有在处理MouseUp事件时才会产生真值。
在FMX中是否有将屏幕坐标转换为TControl坐标的简单方法,就像在VCL中一样?当然,我可以“去除”控件的父级,记录其左上角坐标,并对每个父级重复此操作,直到到达基础表单,但这相当繁琐。
我的当前方法是获取TControl(实际上是TPanel)的顶部(x,y)坐标,该TControl是要被点击的控件(实际上是TRectangle's的子项),并将这些坐标加起来以检查单击是否在该矩形内。请参见下面的示例代码。
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轴方向上仍然略有偏差。因此,我想直接将屏幕坐标转换为控件坐标以解决这个问题。
编辑2: 我尝试使用@Sentient建议的IsMouseOver检查每个关键控件,但奇怪的是,只有在处理MouseUp事件时才会产生真值。