Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Using Microsoft Location api (locationapi.dll) in Delphi 5

Posted on 2013-10-28
10
Medium Priority
?
1,188 Views
Last Modified: 2013-10-31
Hi,

First post by a newbie, so please be gentle.

Tablet type notebooks (like the Microsoft Surface Pro) can contain an inbuilt GPSr and I believe access to it is via the Microsoft Location api

I am wanting to get the current location (latitude,longitude) from the GPSr using Delphi (V5) and believe my only option is via a Com object (Remember, I am using Delphi 5). I have very little experience using such objects so I am looking for the complete code to make this work. So I guess I am after the sample code of a small program that would do this.
0
Comment
Question by:Clyde24
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 5
10 Comments
 

Author Comment

by:Clyde24
ID: 39607597
..., Also my understanding is that this DLL is only available on Windows 7 and above. So I need corresponding error checking to make sure the code is only run on systems that have this DLL
0
 
LVL 27

Expert Comment

by:Sinisa Vuk
ID: 39608501
Easiest way is to try load dll (LocationAPI.dll) like:

function IsLocationAPIAvailable: Boolean;
var
  hDllHandle: THandle;
begin
  Result := False;
  
  hDllHandle:=LoadLibrary('LocationAPI.dll');
  if hDllHandle<>0 then
  begin
    Result := True;
    FreeLibrary(hDllHandle);
  end;
end;

Open in new window


Another way is to try create instance of object but using exception handler:
function IsLocationAPIAvailable: Boolean;
var
  loc: ILocation;
begin
  Result := False;
  
  try
    loc := CreateOleObject(LocationApiIntf) as ILocation;
    Result := True;
  exception
  end;

  loc := nil;
end;

Open in new window

0
 

Author Comment

by:Clyde24
ID: 39610183
The first  example works, but once loaded how do I actually use it to get the Latitude and longitude?

The second example wont compile as several undeclared identifiers - how do I declare them

Error screen shot
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
LVL 27

Expert Comment

by:Sinisa Vuk
ID: 39610405
Using Import Type Library in Delphi import Location Api interface. Similar like here:
Installing the Microsoft SAPI speech SDK in Delphi. Add created unit LocationApiLib_TLB and ActiveX too.

Location api description:
http://msdn.microsoft.com/en-us/library/windows/desktop/dd317674%28v=vs.85%29.aspx

I will try to make simple example...

this way is upper function:
function IsLocationAPIAvailable: Boolean;
var
  loc: ILocation;
begin
  Result := False;
  
  try
    loc := CreateComObject(CLASS_Location) as ILocation;
    Result := True;
  except
  end;

  loc := nil;
end;

Open in new window

0
 

Author Comment

by:Clyde24
ID: 39610476
Using Import Type Library in Delphi import Location Api interface

But how do I do that. When I take the option "Project=>Import type library" there is no corresponding entry for the Microsoft Location Api

If I click on the "Add" button and select the LocationAPi.dll I get the following errorError dialog
0
 
LVL 27

Accepted Solution

by:
Sinisa Vuk earned 1500 total points
ID: 39611233
Strange. But if you cannot access to typelib here is created unit: LocationApiLib-TLB.pas

Example:
uses ..., LocationApiLib_TLB, ActiveX, Comobj;
...
function IsLocationAPIAvailable: Boolean;
var
  loc: ILocation;
begin
  Result := False;

  try
    loc := CreateComObject(CLASS_Location) as ILocation;
    Result := True;
  except
  end;

  loc := nil;
end;

function LocReportStatus(status: LOCATION_REPORT_STATUS): String;
begin
  Result := '';
  case status of
    REPORT_RUNNING:
      Result := 'Report received!';
    REPORT_NOT_SUPPORTED:
      Result := 'No devices detected!';
    REPORT_ERROR:
      Result := 'Report error!';
    REPORT_ACCESS_DENIED:
      Result := 'Access denied!';
    REPORT_INITIALIZING:
      Result := 'Report is initializing!';
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
type
  PILocationReport = ^ILocationReport;
var
  loc: ILocation;
  rep: ILocationReport;
  LatLongRep: ILatLongReport;
  status: LOCATION_REPORT_STATUS;
  hres: HRESULT;
  fLat, fLon: double;
begin
  if IsLocationAPIAvailable then
  begin
    loc := CreateComObject(CLASS_Location) as ILocation;
    try
      status := REPORT_NOT_SUPPORTED;
      //have permission?
                                                                            // 0 for asynchronous calls
      if loc.RequestPermissions(_RemotableHandle(nil^), IID_ILatLongReport, 1, Integer(True))  = S_OK then
      begin
        hres := loc.GetReportStatus(IID_ILatLongReport, status);
        if hres = S_OK then
        begin
          if status = REPORT_RUNNING then //report is ok?
          begin
            hres := loc.GetReport(IID_ILatLongReport, rep);
            if (hres = S_OK) and (rep<>nil) then
            begin
              hres := rep.QueryInterface(IID_ILatLongReport, LatLongRep);
              if (hres = S_OK) and (LatLongRep<>nil) then
              begin
                fLat := 0;
                fLon := 0;
                LatLongRep.GetLatitude(fLat);
                LatLongRep.GetLongitude(fLon);
                Edit1.Text := FloatToStr(fLat);
                Edit2.Text := FloatToStr(fLon);
              end;
            end;
          end
          else
            ShowMessage(LocReportStatus(status));
        end
        else
          ShowMessage(IntToStr(Integer(hres)));
      end;
    finally
      LatLongRep := nil;
      rep := nil;
      loc := nil;
    end;
  end;
end;

procedure TForm1.Button3Click(Sender: TObject);
var
  loc: ILocation;
  rep: ILocationReport;
  CivRep: ICivicAddressReport;
  status: LOCATION_REPORT_STATUS;
  hres: HRESULT;
  sCity: WideString;
begin
  if IsLocationAPIAvailable then
  begin
    loc := CreateComObject(CLASS_Location) as ILocation;
    try
      status := REPORT_NOT_SUPPORTED;
      //have permission?
                                                                               // 0 for asynchronous calls
      if loc.RequestPermissions(_RemotableHandle(nil^), IID_ICivicAddressReport, 1, Integer(True))  = S_OK then
      begin
        hres := loc.GetReportStatus(IID_ICivicAddressReport, status);
        if hres = S_OK then
        begin
          if status = REPORT_RUNNING then //report is ok?
          begin
            hres := loc.GetReport(IID_ICivicAddressReport, rep);
            if (hres = S_OK) and (rep<>nil) then
            begin
              hres := rep.QueryInterface(IID_ICivicAddressReport, CivRep);
              if (hres = S_OK) and (CivRep<>nil) then
              begin
                sCity := '';
                CivRep.GetCity(sCity) ;
                Edit1.Text := sCity;
              end;
            end;
          end
          else
            ShowMessage(LocReportStatus(status));
        end
        else
          ShowMessage(IntToStr(Integer(hres)));
      end;
    finally
      CivRep := nil;
      rep := nil;
      loc := nil;
    end;
  end;
end;

initialization
  CoInitializeEx(nil, COINIT_APARTMENTTHREADED or COINIT_DISABLE_OLE1DDE);

finalization
  CoUninitialize;

Open in new window


on separate button I show procedure how to get Latitude and on another button how to get Address, City,...
Device (GPS?) should be available to get Latitude. It is recommended to wait for LatLongReport report until it is available.
0
 

Author Comment

by:Clyde24
ID: 39613233
Unfortunately I get the following compile errors:

compile error
I suspect this is because I am using Delphi5 (as specified in my question title). Probably the same reason why I didn't see the Location api when I tried to import the type library. Does this mean it is impossible to use the location api with Delphi5?. Unfortunately it is a legacy application written in Delphi 5 that I want to add this function to.

However, I do also have Delphi 10 and a quick mock up of your code appears to work - thanks.

So if it is impossible to use the location api in Delphi 5, then I guess the only way to move forward is to create a DLL in Delphi 10 with the required functions, and then use this DLL in Delphi5 to access those functions?
0
 
LVL 27

Expert Comment

by:Sinisa Vuk
ID: 39613451
Yes, dll in D10 will be solution here. Think Delphi is a problem. Upper unit (LocationApiLib) is generated in D6 (so, not a big step in version).

Another thought: try to import some another typelib (maybe ms speech activex control) and see a way how is this unit generated against LocationApiLib. Look in uses too.
0
 

Author Comment

by:Clyde24
ID: 39613498
OK, one last question before I accept your answer. You say:

It is recommended to wait for LatLongReport report until it is available.

Does your code above already do this wait or is this something extra I need to add to the code. If so please show an example.

Thanks
0
 
LVL 27

Expert Comment

by:Sinisa Vuk
ID: 39614309
Just simple request for state which must be: REPORT_RUNNING

function WaitForReport(loc: ILocation; reportType: TGUID): Boolean;
var
  status: LOCATION_REPORT_STATUS;
begin
  Result := False;

  while (loc.GetReportStatus(reportType, status) = S_OK) do
  begin
    if status = REPORT_RUNNING then //report ready!
    begin
      Result := True;
      Exit;
    end;

    if status <> REPORT_INITIALIZING then //wait for report!
    begin
      //error occured
      Exit;
    end;
    Sleep(200);
  end;
end;

Open in new window


usage:
...
if loc.RequestPermissions(_RemotableHandle(nil^), IID_ILatLongReport, 1, Integer(True))  = S_OK then
begin
   if not WaitForReport(loc, IID_ILatLongReport) then Exit;
....

Open in new window

0

Featured Post

[Webinar] Lessons on Recovering from Petya

Skyport is working hard to help customers recover from recent attacks, like the Petya worm. This work has brought to light some important lessons. New malware attacks like this can take down your entire environment. Learn from others mistakes on how to prevent Petya like worms.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
In this brief tutorial Pawel from AdRem Software explains how you can quickly find out which services are running on your network, or what are the IP addresses of servers responsible for each service. Software used is freeware NetCrunch Tools (https…
In this video, Percona Solution Engineer Rick Golba discuss how (and why) you implement high availability in a database environment. To discuss how Percona Consulting can help with your design and architecture needs for your database and infrastr…
Suggested Courses

704 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question