The Windows 7 Location API

This article was originally included in the MapPoint Programming section of the HowTo pages. The MapPoint programming pages are being removed, but this page does not directly refer to MapPoint and remains relevant. The Location & Sensors API remains available, but Windows 10 also introduced a new Windows.Devices.GeoLocation API.

Probably one of the most interesting additions in Windows 7 for application developers, is the addition of a Location and Sensors API. This provides a common interface for a wide range of sensor devices – i.e. similar to a device driver for a printer. This will be very useful where such peripherals are often shackled to vendor-only applications and/or ancient serial (RS-232) connections.

Closer to home, the geospatial world is still encumbered by the NMEA-0183 standard which is based on a serial (“COM port”) connection although it is usually implemented virtually. You only need to search a forum like Laptop GPS World to see the problems caused by this virtual COM port arrangement: users have to install a USB driver and configure “non-existent” settings like COM port and baud rate. They rightly expect to be able to plug their GPS device in and it “just works” — like a printer or any other USB device. These problems should go away as more people adopt Windows 7 and vendors roll out Location API drivers for their devices. This article shows you how to use the new Location API in your own application.

The suppliers of the MapPoint and Streets & Trips GPS devices, U-Blox, already supply a Windows 7 driver that supports the new API. For this page, a BU-353 device was used. No vendor driver was available, but the generic GPSDirect Virtual Sensor Driver was used instead. This maps any generic NMEA-0183 device to the new Location API. You still have to configure the COM settings and I found it could do with some polish. This free driver should be good enough for development, but I would hesitate to use it in a production environment.

Although most readers will be interested in using the Location API with GPS devices, the API can also support other location services such as WiFi base station setting, and cell-phone triangulation. It can also provide location reports as street addresses if the device (real or virtual) supports this information.

Using the Location API

Okay, so let’s look at the actual Location API. The API is implemented using COM. A .NET COM Interop wrapper is available, but for this sample we shall use MFC. You will also need Microsoft Visual Studio 2008 and the Windows 7 SDK. The Windows 7 SDK is a free download.

After installing your Location API driver and the Windows 7 SDK, you can configure Visual Studio. The SDK comes with a configuration tool that should be able to do this for you. If not, you will have to manually add the SDK to the standard paths for include files and library (lib) files. In a standard install, they will be something like this:

I found I had to put these paths at the top of path listings for includes and libs to avoid an incompatible mix of different files from different versions.

Next, create a new project using the multi-threading options. For this sample I have chosen an MFC dialog box application. Add “LocationAPI.lib” to the Additional Dependencies setting in the project property pages (Linker->Input). This library provides the new API. You will also need to include LocationAPI.h which provides the interface prototypes.

The API can work in two modes: Synchronous and Asynchronous. I found the synchronous API to be quick enough for my needs. The asynchronous method is multi-threaded, and the call-back function is called on a different thread. This will be preferable for a large application, but it adds complications which are beyond the scope of this article. An asynchronous example that uses the console for output can be found on the Microsoft website here. A GUI interface (as used here) would require thread locking mechanisms to work properly.

So let’s start coding! Our program will request location updates every half a second, and measure the distance travelled between each update.

Our dialog box class’s include file (LocationDemoDlg.h) consists of mainly MFC boilerplate, but we do have some implementation specific definitions:

LOCATION_REPORT_STATUS is an enum that stores the status of the latest location report request. We simply use a class-level variable as a part of the text mapping. This could be made more efficient and stored as a location variable that is mapped as a function parameter. spLoc is the pointer to our main Location interface. The remaining variables simply keep track of the current location, previous location (i.e. 0.5 seconds ago), and a cumulative distance calculated from these differences.

Next we move to the implementation of CLocationDemoDlg. Again, I shall skip the bulk of the MFC boilerplate, but the following snippet should help to explain how the dialog box GUI is hooked up. The dialog box (CLocationDemoDlg) has four text labels which are used to display information at 0.5 second intervals. These four labels are hooked up to four CString definitions:

Beyond the automatically generated call backs produced by MFC, we need to add two event handlers. ON_WM_TIMER handles the timer events, and a second handler handles the OK button press (to shut things down).

Next we move to our OnInitDialog() definition: This starts the Location API, gets a status, and an initial location:

The above is a simple example of using the location API in a synchronous manner. We only fetch the location’s longitude and latitude, but other parameters such as estimated error and altitude are available.

We fetched the status but left it to the function SetStatusString() to process it. This simply maps the status enum into a human-readable label. Here is the definition:

The call back for the OK button stops the timer and closes the dialog box:

Next we define the actual timer call back. This is almost a complete copy of the above synchronous location code. We fetch a new report, the report’s status, and longitude,latitude coordinate. The distance between the previous coordinate and the new coordinate is calculated and added to lfDistance – a cumulative distance.

Finally we need to implement CalcDistance(). This calculates the straight line (great circle) distance between the latest coordinate and the previous coordinate. Distances less than 1 metre are returned as 0 metres.

And that is it! I have left out a lot of MFC boilerplate, but the functioning location-specific content is fully covered above. The full VS2008 project including all source code can be downloaded here. This is what the functioning program looks like:

The working demo dialog box showing the current location

Note that a GPS device has errors and the precise coordinate will typically “wander” by a few metres back and forth. This program picks up these “wanderings” if they are larger than 1 metre per 0.5 second interval. These can quickly accumulate if reception is particularly poor.

Further Information

MSDN has extensive information including a full API reference and samples for both the Location API and the Sensor API. The Windows 7 SDK also includes samples for both synchronous and asynchronous location calls.

Leave a Reply