title: How to convert screen coordinates to control coordinates
body: <p>I need code that is able to intercept several taps on a tablet at the same moment. In a <a href="https://stackoverflow.com/questions/21521151/do-onmousedown-and-onmouseup-only-work-as-a-pair">previous question</a> concerning how to handle several OnMouseDown's at the same moment (not possible), a <a href="http://www.delphifeeds.com/go/s/112564" rel="nofollow noreferrer">link</a> was provided that answered the question on how to handle multi touch clicks in Delphi-Android. However, this code returns (x, y) positions in screen coordinates and I don't know how to translate these to local coordinates of a specific control. The Delphi <a href="http://docwiki.embarcadero.com/Libraries/XE2/en/FMX.Platform.TPlatform.ScreenToClient" rel="nofollow noreferrer">documentation</a> refers to a ScreenToClient function but that only translates screen coordinates to form coordinates, which is hardly useful in Android (the documentation is about XE2 but the function still exists in XE5 but the function has been removed from FMX.Platform to FMX.Form). </p>
  
  <p>Is there a simple way to convert screen coordinates to TControl coordinates in FMX like in VCL? Of course I can 'de-parent' a control, notate its top-left coordinates and do so for each parent until arrived at the base form, but that's quite tedious. </p>
  
  <p><strong>Edit 1</strong></p>
  
  <p>My current approach is to get the top (x, y) coordinates of the TControl (a TPanel) that is parent to the controls to be tapped (TRectangle's in fact) and add these to check whether a click is inside that rectangle. See sample code below. </p>
  
  <pre><code>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 &lt; 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 &gt;= key.Position.X + p.X) and (x &lt;= key.Position.X + p.X + Key.Width) and
              (y &gt;= key.Position.Y + p.Y) and (y &lt;= 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 &gt;= key.Position.X + p.X) and (x &lt;= key.Position.X + p.X + Key.Width) and
                 (y &gt;= key.Position.Y + p.Y) and (y &lt;= key.Position.Y + p.Y + key.Height)
                 then break;
              key := nil;
           end; // if
        end; // for
     end; // if
  
  
     if key &lt;&gt; nil
        then putShort (status_byte, key.Note, 127);
     if key &lt;&gt; nil
        then logd (' found %s', [key.Text.Text]);
  end; // process_touch //
  </code></pre>
  
  <p>This code is in fact very untidy because it assumes that the Parent control has the Application.MainForm as its parent which need not be the case. Another observation is that the taps might still be slightly wrong in the Y-position. For that reason i'd like to transfer the screen coordinates directly to the control's coordinates.</p>
  
  <p><strong>Edit 2</strong></p>
  
  <p>I tried to use the IsMouseOver check for each key control as suggested by @Sentient but strangely enough that only yields true when a MouseUp event is being processed.</p>