⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gps.cs

📁 清华大学出版社出版的 移动应用开发宝典 张大威(2008)的附书源代码
💻 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 + -