
確保未連接實體/虛擬位置感應器,避免覆蓋預設位置導致錯誤結果。透過「位置與其他感應器」控制台項目檢查。


LocationHOL,路徑:C:\Templocationapi.lib#include <windows.h>
#include <atlbase.h>
#include <atlcom.h>
#include <LocationAPI.h>
IID REPORT_TYPES[] = { IID_ILatLongReport, IID_ICivicAddressReport };
class CInitializeATL : public CAtlExeModuleT<CInitializeATL> {};
CInitializeATL g_InitializeATL;
int _tmain()
{
CComPtr<ILocation> spLocation;
if (FAILED(spLocation.CoCreateInstance(CLSID_Location))) {
wprintf(L"Failed to create Location COM object.\n");
return 1;
}
if (FAILED(spLocation->RequestPermissions(NULL, REPORT_TYPES, ARRAYSIZE(REPORT_TYPES), TRUE))) {
wprintf(L"Warning: Unable to request permissions.\n");
}
...
}
void PrintReportStatus(LOCATION_REPORT_STATUS status)
{
switch (status) {
case REPORT_RUNNING: wprintf(L"Report ready.\n"); break;
case REPORT_NOT_SUPPORTED: wprintf(L"No devices detected.\n"); break;
case REPORT_ERROR: wprintf(L"Report error.\n"); break;
case REPORT_ACCESS_DENIED: wprintf(L"Access denied to report.\n"); break;
case REPORT_INITIALIZING: wprintf(L"Report is initializing.\n"); break;
}
}
LOCATION_REPORT_STATUS status = REPORT_NOT_SUPPORTED;
if (FAILED(spLocation->GetReportStatus(IID_ILatLongReport, &status))) {
wprintf(L"Error: Unable to obtain lat/long report status.\n");
return 1;
}
wprintf(L"Lat./long. Report status: "); PrintReportStatus(status);
if (status == REPORT_RUNNING) {
CComPtr<ILocationReport> spLocationReport;
CComPtr<ILatLongReport> spLatLongReport;
if (SUCCEEDED(spLocation->GetReport(IID_ILatLongReport, &spLocationReport)) &&
SUCCEEDED(spLocationReport->QueryInterface(IID_PPV_ARGS(&spLatLongReport))) &&
spLatLongReport.p != NULL) {
SYSTEMTIME st;
if (SUCCEEDED(spLatLongReport->GetTimestamp(&st))) PrintTimestamp(st);
GUID sensorID = {0};
if (SUCCEEDED(spLatLongReport->GetSensorID(&sensorID))) {
wprintf(L"SensorID: "); PrintGUID(sensorID);
}
wprintf(L"\nReport:\n");
PrintLatLongReport(spLatLongReport);
}
}
void PrintLatLongReport(ILatLongReport* pReport)
{
DOUBLE lat, lon, alt, errRad, altErr;
if (SUCCEEDED(pReport->GetLatitude(&lat))) wprintf(L"Latitude: %f\n", lat);
if (SUCCEEDED(pReport->GetLongitude(&lon))) wprintf(L"Longitude: %f\n", lon);
if (SUCCEEDED(pReport->GetAltitude(&alt))) wprintf(L"Altitude: %f\n", alt);
else wprintf(L"Altitude: Not available.\n");
if (SUCCEEDED(pReport->GetErrorRadius(&errRad))) wprintf(L"Error Radius: %f\n", errRad);
if (SUCCEEDED(pReport->GetAltitudeError(&altErr))) wprintf(L"Altitude Error: %f\n", altErr);
else wprintf(L"Altitude Error: Not available.\n");
}
void PrintGUID(const GUID guid) { ... }
void PrintTimestamp(const SYSTEMTIME time) { ... }


// LocationEvents.h
#pragma once
#include "StdAfx.h"
class CLocationEvents : public CComObjectRoot, public ILocationEvents
{
public:
DECLARE_NOT_AGGREGATABLE(CLocationEvents)
BEGIN_COM_MAP(CLocationEvents)
COM_INTERFACE_ENTRY(ILocationEvents)
END_COM_MAP()
STDMETHOD(OnLocationChanged)(REFIID reportType, ILocationReport* pLocationReport);
STDMETHOD(OnStatusChanged)(REFIID reportType, LOCATION_REPORT_STATUS status);
private:
void PrintCivicAddress(ICivicAddressReport* pReport);
};
// LocationEvents.cpp
#include "LocationEvents.h"
STDMETHODIMP CLocationEvents::OnLocationChanged(REFIID reportType, ILocationReport* pLocationReport)
{
if (IID_ICivicAddressReport == reportType) {
CComPtr<ICivicAddressReport> spReport;
if (SUCCEEDED(pLocationReport->QueryInterface(IID_PPV_ARGS(&spReport))) && spReport.p) {
wprintf(L"Civic address location changed:\n\n");
PrintCivicAddress(spReport);
}
}
return S_OK;
}
STDMETHODIMP CLocationEvents::OnStatusChanged(REFIID reportType, LOCATION_REPORT_STATUS status)
{
if (IID_ICivicAddressReport == reportType) {
switch (status) {
case REPORT_NOT_SUPPORTED: wprintf(L"\nNo devices detected.\n"); break;
case REPORT_ERROR: wprintf(L"\nReport error.\n"); break;
case REPORT_ACCESS_DENIED: wprintf(L"\nAccess denied to reports.\n"); break;
case REPORT_INITIALIZING: wprintf(L"\nReport is initializing.\n"); break;
case REPORT_RUNNING: wprintf(L"\nRunning.\n"); break;
}
}
return S_OK;
}
void CLocationEvents::PrintCivicAddress(ICivicAddressReport* pReport)
{
CComBSTR addr1, addr2, postal, city, state, country;
if (SUCCEEDED(pReport->GetAddressLine1(&addr1)) && addr1.Length()) wprintf(L"\tAddress Line 1:\t%s\n", addr1);
if (SUCCEEDED(pReport->GetAddressLine2(&addr2)) && addr2.Length()) wprintf(L"\tAddress Line 2:\t%s\n", addr2);
if (SUCCEEDED(pReport->GetPostalCode(&postal)) && postal.Length()) wprintf(L"\tPostal Code:\t%s\n", postal);
if (SUCCEEDED(pReport->GetCity(&city)) && city.Length()) wprintf(L"\tCity:\t\t%s\n", city);
if (SUCCEEDED(pReport->GetStateProvince(&state)) && state.Length()) wprintf(L"\tState/Province:\t%s\n", state);
if (SUCCEEDED(pReport->GetCountryRegion(&country))) wprintf(L"\tCountry/Region:\t%s\n\n", country);
}
#include "LocationEvents.h"
int _tmain()
{
// ... 前述同步程式碼 ...
CComObject<CLocationEvents>* pEvents = NULL;
if (FAILED(CComObject<CLocationEvents>::CreateInstance(&pEvents)) || !pEvents) {
wprintf(L"Error creation Location events sink.\n");
return 1;
}
pEvents->AddRef();
if (FAILED(spLocation->RegisterForReport(pEvents, IID_ICivicAddressReport, 0))) {
pEvents->Release();
wprintf(L"Error registering for report.\n");
return 1;
}
wprintf(L"Press ENTER to exit.\n");
getchar();
if (pEvents) {
spLocation->UnregisterForReport(IID_ICivicAddressReport);
pEvents->Release();
}
return 0;
}

本實驗展示 Windows 7 Location API 同步(經緯度)與非同步(市政地址)存取模式,涵蓋 COM 物件建立、權限請求、報表狀態查詢、資料擷取與事件訂閱。產品級整合需額外處理錯誤、快取、UI 執行緒切換等,但核心概念已掌握。