FNC Maps Issue

Hi,

Yes, this is possible with the following code:

  //requesting departure time zone
  TMSFNCTimeZone1.GetTimeZone(CoordRecD, DateD, '1252', mlmDefault,
  procedure(const ARequest: TTMSFNCTimeZoneRequest; const ARequestResult: TTMSFNCCloudBaseRequestResult)
  begin
    //request departure time zone finished
    //work with ARequest.Items to get the requested time zone for the departure time
    //request arrival time zone
    TMSFNCTimeZone1.GetTimeZone(CoordRecA, DateA, '1252', mlmDefault,
    procedure(const ARequest: TTMSFNCTimeZoneRequest; const ARequestResult: TTMSFNCCloudBaseRequestResult)
    begin
      //request arrival time zone finished
      //work with ARequest.Items to get the requested time zone for the arrival time
    end
    , '1', nil);
  end
  , '0', nil);

That's just what I wanted, thanks - yet again - for your help Pieter.

Regards, Andrew

1 Like

Your code works fine in a form containing FNCGoogleMap and TMSFNCTimeZone components. However, when I try to use this code in a utilities unit - so that I can get time offsets from various other units in my app - it doesn't work:
...
TMSFNCGoogleMaps1:= TTMSFNCGoogleMaps.Create(nil);
TMSFNCTimeZone1:= TTMSFNCTimeZone.Create(nil);
TMSFNCTimeZone1.Service:= tzsGoogle;
...
TMSFNCTimeZone1.GetTimeZone(CoordRecD, DateD, '1252', mlmDefault,
procedure (const ARequest: TTMSFNCTimeZoneRequest; const ARequestResult: TTMSFNCCloudBaseRequestResult)
begin
vcl.Dialogs.ShowMessage('Here');
GMTOffset:= StrToFloat(ARequest.Items[0].Offset); vcl.Dialogs.ShowMessage(ARequest.Items[0].Offset);
if (GMTOffset >= 0) then
Times[1]:= 1 //'+'
else
Times[1]:= 0; //'-';
Times[0]:= GMTOffset;

      //request departure time zone finished

      //request arrival time zone
      TMSFNCTimeZone1.GetTimeZone(CoordRecA, DateA, '1252', mlmDefault,
      procedure(const ARequest: TTMSFNCTimeZoneRequest; const ARequestResult: TTMSFNCCloudBaseRequestResult)
      begin
        GMTOffset:= StrToFloat(ARequest.Items[0].Offset);
         if (GMTOffset >= 0) then
            Times[3]:= 1 //'+'
         else
            Times[3]:= 0; //'-';
        Times[2]:= GMTOffset;
      end
      , '1', nil);  <---  There is no overloaded version of GetTimeZone that can be called with these args
    end
    , '0', nil);  <---  There is no overloaded version of GetTimeZone that can be called with these args

Now both the FNCMaps form and this code compiles ok with these errors, and works on the form but not in the utility procedure - 'Here' is never seen. All the FNC units have been added to the utilities unit's Uses. Can you see what I'm doing wrong?

Please send us a reproducible sample. It's unclear without being able to compile this ourselves.

Ok, herewith a simplified sample project which illustrates the issue. No doubt I have forgotten something basic!
[Attachment removed because of API keys]

The reason for the code not running is because you are freeing the component before it has a chance to launch the request. Please note that the request that is being executed is asynchronous, which means that the result is retrieved in the callback, but the routine that has called the GetTimeZone will continue to execute. You cannot immediately return the value. You need to await the result:

function GetTimeZone(const Lat,Long: double ): double ;
var

    TMSFNCGoogleMaps1: TTMSFNCGoogleMaps;  //<???
    TMSFNCTimeZone1: TTMSFNCTimeZone;
    //TMSFNCTimeZoneRequest1: TTMSFNCTimeZoneRequest; //<???
    CoordRec: TTMSFNCMapsCoordinateRec;

    Time,GMTOffset: Double;
    t: double;
begin

    TMSFNCGoogleMaps1:= TTMSFNCGoogleMaps.Create(nil);  //<???
    TMSFNCTimeZone1:=  TTMSFNCTimeZone.Create(nil);
    TMSFNCTimeZone1.Service:= tzsGoogle;
    TMSFNCGoogleMaps1.APIKey:= 'API KEY';
    TMSFNCTimeZone1.APIKey:= 'API KEY';

    Try
        t:= 0;
        CoordRec:= CreateCoordinate(Lat, Long);//vcl.Dialogs.ShowMessage(FloatToStr(CoordRecD.Latitude));

        TMSFNCTimeZone1.GetTimeZone(CoordRec, now, '1252', mlmDefault,
        procedure (const ARequest: TTMSFNCTimeZoneRequest; const ARequestResult: TTMSFNCCloudBaseRequestResult)
        begin
            //vcl.Dialogs.ShowMessage('Here');
            if ARequest.Items.Count > 0 then
              GMTOffset:= StrToFloat(ARequest.Items[0].Offset);
            //vcl.Dialogs.ShowMessage(ARequest.Items[0].Offset);
            Time:= GMTOffset;

         //request departure time zone finished
          t := Time;

        end
        , '0', nil);

    Finally
      while t = 0 do
      begin
        Application.ProcessMessages;
        sleep(1);
      end;

      Result := t;

        TMSFNCTimeZone1.Free;
        TMSFNCGoogleMaps1.Free;   //<???
    End;
end;

Thank you Pieter, I never thought of that! Thank you for your patience. BTW, I did buy Dr Flick's book, but it doesn't cover time zones yet.

As the book was published in August last year, the feature was not available yet. At least I have a nice visual in there how you can show the different time zones :-)

Indeed, I realised that. Yes, I saw that - very nice. A small comment: when you do include the feature, an example or two showing usage at runtime in the way discussed in this thread would be useful. I am learning a lot from the book though - thank you.

I'm getting a runtime error 216 at 0040AC72 when I close the form which calls function GetTimeZone in the Utilities unit - as discussed previously. The Finally section refers:

Finally
      while t = 0 do
      begin
        Application.ProcessMessages;
        sleep(1);
      end;

      Result := t;

        TMSFNCTimeZone1.Free;
     end;

If I comment out line: *TMSFNCTimeZone1.Free*;, there is no AV. It looks as though the TTMSFNCTimeZoneGoogleTimeZone.Destroy destructor in Unit VCL.TMSFNCTimeZone.Google is trying to destroy TMSFNCTimeZone1 which has already been freed as shown in the attached screenshot. Perhaps I don't need to free the component?

![TimeZoneAV|658x500](upload://lnexdEIXL5Mw7Jk6kifRqoDZqu2.png)

We have investigated this here and couldn't reproduce the issue, it could be possible that this is related to the maps instead of the timezone, can you verify? We have fixed an issue related to access violation in TTMSFNCMaps.

I don't think so. In one of my usage scenarios (discussed above), I don't display a map - simply the GMT offset times - and I have removed the Google Maps creation code and the AV still occurs. One point I haven't mentioned is that the AV only occurs when I run another unit in the app after running the 'GMT Offsets' function and before closing the app (which closes the form which called the 'GMT Offsets' function). It would appear that freeing TMSFNCTimeZone1 component also frees the TMSFNCTimeZoneGoogleTimeZone component which causes the AV later on?

Could you provide a very basic reproducible sample? This would help us in identifying the issue.

Well, I've tried, but I can't reproduce the issue in a very basic sample. So it looks like a problem in my very large and complex app. I'll continue investigating and let you know if I find anything. Thanks for looking at this.

1 Like

Cannot find the problem and the only way to stop the AV on app shutdown is to make the following changes to the previous example :

//TMSFNCTimeZone1:= TTMSFNCTimeZone.Create(nil)
TMSFNCTimeZone1:= TTMSFNCTimeZone.Create(application);
TMSFNCTimeZone1.Service:= tzsGoogle;
Try
.............
Finally
while t = 100000 do begin
Application.ProcessMessages;
sleep(1);
end;

  Result := Times;

  //TMSFNCTimeZone1.Free;

end;

and get the application to free the TMSFNCTimeZone component. Can you see a problem with this?

Hi,

Can you try with the latest version?

Hi,

Yes, that appears to fix that issue - many thanks. However, I can't immediately see how to apply the Geodesic property during runtime using:

SetLength(ary, 2);
ary[0] := CoordRecD;
ary[1] := CoordRecA;
TMSFNCGoogleMaps1.BeginUpdate;
pl := TMSFNCGoogleMaps1.AddPolyline(ary);
pl.Geodesic := true; <--- [dcc32 Error] LogFNCMaps.pas(174): E2003 Undeclared identifier: 'Geodesic'
pl.StrokeColor:= clred;
pl.Visible:= True;

as used in WebGMaps. How do I use the property in FNC Maps?

Hi, the base class is TTMSFNCMapsPolyLine, but you need to typecast this to TTMSFNCGoogleMapsPolyLine to access the Geodesic property.

fyi , I moved this thread to the TMS FNC Maps category as it did not belong to TMS VCL UI Pack.

1 Like