4
votes

Using Delphi XE 2 I've trying to identify the zoom direction to apply the zoom efect to an image (TImage) but didnt find an function to do it and the EventInfo property in the event OnGesture of the Image didnt have this information.

I've seen a lote of samples using Direct2d to zoom in and zoom out but it uses the wp_touch messages direct to do it and the zoom effects are performed using transform matrix scale functions from direct 2d but i dont want to use direct2d to this project as it will only have this zoom in and out effect based on touch, the other things is simple clicks.

It could be possible to identify the in/out storing the first direction and comparing to the current one since the EventInfo parameter has an property Direction but i dont think this is the nice way to do it or i'm wrong ?

So after that is there any recomendations or examples on how to perform the zoom effect in a TImage ? I've already done that but it does not pan with when zooming to give the pinch efect that every application does.

2

2 Answers

2
votes

After reading a lote of documentations I found out that the right way to do is:

Intercept the EventInfo.GestureID to identify the command desired in my case the zoom command, after that you should read the EventInfo.Flags and to identify if it is the gfBegin so you can cache the first location point (x,y) and the first distance and when the flag is diferent then gfBegin you perform your calculations using the firstpoint and the currentpoint (EventInfo.Location)

Basic the command should be like that:

 case EventInfo.GestureID of
  igiZoom:
   begin
     if (EventInfo.Flags = [gfBegin]) then
      begin
        FLastDistance := EventInfo.Distance;
        FFirstPoint.X := EventInfo.Location.X;
        FFirstPoint.Y := EventInfo.Location.Y;
        FFirstPoint := ScreenToClient(FFirstPoint);

        if (FSecondPoint.X = 0) and (FSecondPoint.Y = 0) then
         begin
          FSecondPoint.X := EventInfo.Location.X + 10;
          FSecondPoint.Y := EventInfo.Location.Y + 10;
          FSecondPoint := ScreenToClient(FSecondPoint);
         end;
        //ZoomCenter is a local TPoint var 
        ZoomCenter.Create(((FFirstPoint.X + FSecondPoint.X) div 2),
                          ((FFirstPoint.Y + FSecondPoint.Y) div 2));
        //Apply the zoom to the object  
        FDrawingObject.Zoom(EventInfo.Distance / FLastDistance, ZoomCenter.X, ZoomCenter.Y);

        Invalidate;
      end
       else
         begin
            FSecondPoint.X := EventInfo.Location.X;
            FSecondPoint.Y := EventInfo.Location.Y;
            FSecondPoint := ScreenToClient(FSecondPoint);

            ZoomCenter.Create(((FFirstPoint.X + FSecondPoint.X) div 2),
                              ((FFirstPoint.Y + FSecondPoint.Y) div 2));

            FDrawingObject.Zoom(EventInfo.Distance / FLastDistance, ZoomCenter.X, ZoomCenter.Y);

            Invalidate;
            //Update with the new values for next interaction
            FFirstPoint := FSecondPoint;
            FLastDistance := EventInfo.Distance;
         end;

There is a sample code write in c# available in the Windows v7.0 SDK that can be used as reference and helps me a lote.

0
votes

For recent Delphi release, EventInfo has a Distance property. We don't have to calculate it.

For interactive gesture like zoom, look at the sample code in docwiki : http://docwiki.embarcadero.com/CodeExamples/Tokyo/en/FMXInteractiveGestures_(Delphi)

    procedure TForm36.handleZoom(EventInfo: TGestureEventInfo);
var
  LObj: IControl;
  image: TImage;
begin
  LObj := Self.ObjectAtPoint(ClientToScreen(EventInfo.Location));
  if LObj is TImage then
  begin
    if not(TInteractiveGestureFlag.gfBegin in EventInfo.Flags) then
    begin
      image := TImage(LObj.GetObject);
      image.Width := image.Width + (EventInfo.Distance - FLastDIstance)/2;
      image.Height := image.Height + (EventInfo.Distance - FLastDIstance)/2;
      image.Position.X := image.Position.X - (EventInfo.Distance - FLastDIstance)/2;
      image.Position.Y := image.Position.Y - (EventInfo.Distance - FLastDIstance)/2;
    end;
  end;
  FLastDIstance := EventInfo.Distance;
end;