Search code examples
delphiwinapiwindows-7delphi-xe2gesture

How to identify zoom direction (in/out) using gestures and apply the zoom effect?


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.


Solution

  • 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.