gpt4 book ai didi

android - 如何将屏幕坐标转换为控件坐标

转载 作者:塔克拉玛干 更新时间:2023-11-02 22:15:10 26 4
gpt4 key购买 nike

我需要能够同时拦截平板电脑上的多次点击的代码。在 previous question关于如何同时处理多个 OnMouseDown(不可能),一个 link提供了关于如何在 Delphi-Android 中处理多点触控点击的问题。但是,此代码返回屏幕坐标中的 (x, y) 位置,我不知道如何将这些位置转换为特定控件的本地坐标。德尔福documentation指的是一个 ScreenToClient 函数,但它只将屏幕坐标转换为表单坐标,这在 Android 中几乎没有用(文档是关于 XE2 但该函数仍然存在于 XE5 中,但该函数已从 FMX.Platform 移至 FMX.Form)。

有没有一种简单的方法可以像在 VCL 中一样将屏幕坐标转换为 FMX 中的 TControl 坐标?当然,我可以“取消父级”控件,标记其左上角坐标,并为每个父级执行此操作,直到到达基本表单,但这非常乏味。

编辑 1

我目前的方法是获取 TControl(一个 TPanel)的顶部(x,y)坐标,它是要点击的控件(实际上是 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 位置上可能仍然略有错误。出于这个原因,我想将屏幕坐标直接传输到控件的坐标。

编辑2

我尝试按照@Sentient 的建议对每个键控件使用 IsMouseOver 检查,但奇怪的是,只有在处理 MouseUp 事件时才会产生 true。

最佳答案

我是您正在使用的多点触控代码的作者。当我看到您在坐标上苦苦挣扎时,我查看了可以做什么并更新了代码,因此它现在为您提供了触摸控件和相对坐标。另外,如果您想知道如何让它变得简单。

关于它的博文在这里:

http://www.cromis.net/blog/2014/02/multi-touch-touched-control-and-relative-coordinates/

解决问题的代码如下:

  if Screen.ActiveForm <> nil then
begin
for I := 0 to Length(Event.Points) - 1 do
begin
Control := Screen.ActiveForm.ObjectAtPoint(Event.Points[I].Position);

if Control <> nil then
begin
Event.Points[I].Control := Control as TFmxObject;
Event.Points[I].RelPosition := Control.ScreenToLocal(Event.Points[I].Position);
end
else
begin
Event.Points[I].Control := Screen.ActiveForm;
Event.Points[I].RelPosition := Screen.ActiveForm.ScreenToClient(Event.Points[I].Position);
end;
end;
end;

关于android - 如何将屏幕坐标转换为控件坐标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21686949/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com