📄 gps.cs
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
using System;
using System.Runtime.InteropServices;
using System.Collections;
using System.Text;
namespace Microsoft.WindowsMobile.Samples.Location
{
public delegate void LocationChangedEventHandler(object sender, LocationChangedEventArgs args);
public delegate void DeviceStateChangedEventHandler(object sender, DeviceStateChangedEventArgs args);
/// <summary>
/// Summary description for GPS.
/// </summary>
public class Gps
{
// handle to the gps device
IntPtr gpsHandle = IntPtr.Zero;
// handle to the native event that is signalled when the GPS
// devices gets a new location
Chapter14.Threading.EventWaitHandle newLocationHandle;
// handle to the native event that is signalled when the GPS
// device state changes
Chapter14.Threading.EventWaitHandle deviceStateChangedHandle;
// handle to the native event that we use to stop our event
// thread
Chapter14.Threading.EventWaitHandle stopHandle;
//IntPtr stopHandle = IntPtr.Zero;
// holds our event thread instance
System.Threading.Thread gpsEventThread = null;
event LocationChangedEventHandler locationChanged;
/// <summary>
/// Event that is raised when the GPS locaction data changes
/// </summary>
public event LocationChangedEventHandler LocationChanged
{
add
{
locationChanged += value;
// create our event thread only if the user decides to listen
CreateGpsEventThread();
}
remove
{
locationChanged -= value;
}
}
event DeviceStateChangedEventHandler deviceStateChanged;
/// <summary>
/// Event that is raised when the GPS device state changes
/// </summary>
public event DeviceStateChangedEventHandler DeviceStateChanged
{
add
{
deviceStateChanged += value;
// create our event thread only if the user decides to listen
CreateGpsEventThread();
}
remove
{
deviceStateChanged -= value;
}
}
/// <summary>
/// True: The GPS device has been opened. False: It has not been opened
/// </summary>
public bool Opened
{
get { return gpsHandle != IntPtr.Zero; }
}
public Gps()
{
}
~Gps()
{
// make sure that the GPS was closed.
Close();
}
/// <summary>
/// Opens the GPS device and prepares to receive data from it.
/// </summary>
public void Open()
{
if (!Opened)
{
// create handles for GPS events
newLocationHandle = new Chapter14.Threading.EventWaitHandle(false, Chapter14.Threading.EventResetMode.AutoReset, null); // CreateEvent(IntPtr.Zero, 0, 0, null);
deviceStateChangedHandle = new Chapter14.Threading.EventWaitHandle(false, Chapter14.Threading.EventResetMode.AutoReset, null);
stopHandle = new Chapter14.Threading.EventWaitHandle(false, Chapter14.Threading.EventResetMode.AutoReset, null);
gpsHandle = GPSOpenDevice(newLocationHandle.Handle, deviceStateChangedHandle.Handle, null, 0);
// if events were hooked up before the device was opened, we'll need
// to create the gps event thread.
if (locationChanged != null || deviceStateChanged != null)
{
CreateGpsEventThread();
}
}
}
/// <summary>
/// Closes the gps device.
/// </summary>
public void Close()
{
if (gpsHandle != IntPtr.Zero)
{
GPSCloseDevice(gpsHandle);
gpsHandle = IntPtr.Zero;
}
// Set our native stop event so we can exit our event thread.
stopHandle.Set();
// block until our event thread is finished before
// we close our native event handles
lock (this)
{
newLocationHandle.Close();
deviceStateChangedHandle.Close();
stopHandle.Close();
}
}
/// <summary>
/// Get the position reported by the GPS receiver
/// </summary>
/// <returns>GpsPosition class with all the position details</returns>
public GpsPosition GetPosition()
{
return GetPosition(TimeSpan.Zero);
}
/// <summary>
/// Get the position reported by the GPS receiver that is no older than
/// the maxAge passed in
/// </summary>
/// <param name="maxAge">Max age of the gps position data that you want back.
/// If there is no data within the required age, null is returned.
/// if maxAge == TimeSpan.Zero, then the age of the data is ignored</param>
/// <returns>GpsPosition class with all the position details</returns>
public GpsPosition GetPosition(TimeSpan maxAge)
{
if (Opened)
{
GPS_POSITION position = new GPS_POSITION();
position.dwVersion = 1;
position.dwSize = Marshal.SizeOf(typeof(GPS_POSITION));
// call native method passing in our native struct
int result = GPSGetPosition(gpsHandle, ref position, 500000, 0);
if (result == 0)
{
// native call succeeded, create managed wrapper class
GpsPosition gp = new GpsPosition(position);
if (maxAge != TimeSpan.Zero)
{
// check to see if the data is recent enough.
if (!gp.TimeValid || DateTime.Now - maxAge > gp.Time)
{
return null;
}
}
return gp;
}
}
return null;
}
/// <summary>
/// Queries the device state.
/// </summary>
/// <returns>Device state information</returns>
public GpsDeviceState GetDeviceState()
{
GPS_DEVICE device = new GPS_DEVICE();
device.dwVersion = 1;
device.dwSize = Marshal.SizeOf(typeof(GPS_DEVICE));
int result = GPSGetDeviceState(ref device);
if (result == 0)
{
// instantiate the GpsDeviceState class passing in the native pointer
return new GpsDeviceState(device);
}
return null;
}
/// <summary>
/// Creates our event thread that will receive native events
/// </summary>
private void CreateGpsEventThread()
{
// we only want to create the thread if we don't have one created already
// and we have opened the gps device
if (gpsEventThread == null && gpsHandle != IntPtr.Zero)
{
// Create and start thread to listen for GPS events
gpsEventThread = new System.Threading.Thread(new System.Threading.ThreadStart(WaitForGpsEvents));
gpsEventThread.Start();
}
}
/// <summary>
/// Method used to listen for native events from the GPS.
/// </summary>
private void WaitForGpsEvents()
{
lock (this)
{
bool listening = true;
System.Threading.WaitHandle[] handles = new System.Threading.WaitHandle[] { stopHandle, deviceStateChangedHandle, newLocationHandle};
while (listening)
{
int obj = Chapter14.Threading.EventWaitHandle.WaitAny(handles); //WaitForMultipleObjects(3, handles, 0, -1);
if (obj != -1)
{
switch (obj)
{
case 0:
// we've been signalled to stop
listening = false;
break;
case 1:
// device state has changed
if (deviceStateChanged != null)
{
deviceStateChanged(this, new DeviceStateChangedEventArgs(GetDeviceState()));
}
break;
case 2:
// location has changed
if (locationChanged != null)
{
locationChanged(this, new LocationChangedEventArgs(GetPosition()));
}
break;
}
}
}
// clear our gpsEventThread so that we can recreate this thread again
// if the events are hooked up again.
gpsEventThread = null;
}
}
#region PInvokes to gpsapi.dll
[DllImport("gpsapi.dll")]
static extern IntPtr GPSOpenDevice(IntPtr hNewLocationData, IntPtr hDeviceStateChange, string szDeviceName, int dwFlags);
[DllImport("gpsapi.dll")]
static extern int GPSCloseDevice(IntPtr hGPSDevice);
[DllImport("gpsapi.dll")]
static extern int GPSGetPosition(IntPtr hGPSDevice, ref GPS_POSITION pGPSPosition, int dwMaximumAge, int dwFlags);
[DllImport("gpsapi.dll")]
static extern int GPSGetDeviceState(ref GPS_DEVICE pGPSDevice);
#endregion
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -