Solved

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

Posted on 2013-10-28
10
1,067 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
  • 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 25

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
 
LVL 25

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
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 
LVL 25

Accepted Solution

by:
Sinisa Vuk earned 500 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 25

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 25

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

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

Suggested Solutions

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

706 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

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now