Share |

Building GPS applications using Visual C++

Download Eye4Software GPS Toolkit free trial Download the Eye4Software GPS Toolkit fully functional 30 day trial version for free
Browse through the Eye4Software GPS Toolkit for Windows manual Browse through the Eye4Software GPS Toolkit manual

Introduction

The Eye4Software GPS toolkit allows software developers to add GPS functionality to their own programs without the need to have any knowledge on serial communications and GPS protocols like RS-232 and NMEA0183.

The product can be used in many programming environments, such as Visual Basic, Visual C++, Visual Studio.Net, Borland C++ Builder, Borland Delphi and VBA, but also web oriented applications such as ASP, ASP.NET and PHP, and all other programming environments that support ActiveX.

Prerequisites

First you must have Visual C++ and the Eye4Software GPS Component installed on your computer.
We will use Visual C++ 6.0 in this document, but all versions from 6.0 and up can be used.
You can download the Eye4Software GPS Component here.

Creating the project

Start the Visual C++ IDE, and select the "New" option from the "File" menu.
The "New Project" dialog now appears, you can use the dialog to enter the name of your product. Select "Win32 Console Application" if you wish to create a console application, or select the "MFC AppWizard" option to create a project with a GUI.


Copy the include files

In order to declare and create the objects from your Visual C++ application, you need to include the include files of the ActiveX control. You can create an include folder in your project folder where you store these files. These files can be found in the "Samples\Visual C++\Include" folder from the installation directory.

Declare and create the object(s)

Once you copied the include files, you have to declare these files in your source code like this:

#include "include\GpsCtrl.h"
#include "include\GpsConstantsX.h"
#include "include\GpsCtrl_i.c"

You can also include the ".c" file in your project instead of using the #include directive for this file.

The objects can be declared in your code like this:

IGps  *  m_pGps;

You can create the m_pGps instance of the object like this:

CoCreateInstance ( CLSID_Gps, NULL, CLSCTX_INPROC_SERVER, IID_IGps, (void**) &m_pGps );

The m_pGps pointer should not be zero, if this is the case, creation of the instance has failed. In this case please check the following:

  • Is the GpsCtrl.dll component copieed and registered on this computer;
  • Did you call CoInitialize () or AfxOleInit () in your project;
  • Did you install the correct DLL for the OS used (X86/x64/PocketPC).

The source code

Below you can find the sourcecode from the Visual C++ demo as shipped with the project.

#include "stdafx.h"

/////////////////////////////////////////////////////////////////////////////

#include "..\include\GpsConstantsX.h"
#include "..\include\GpsCtrl.h"

/////////////////////////////////////////////////////////////////////////////
#include "Demo.h"
#include "DemoDlg.h"

/////////////////////////////////////////////////////////////////////////////


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////

CDemoDlg::CDemoDlg(CWnd* pParent) : CDialog(CDemoDlg::IDD, pParent)
{
   //{{AFX_DATA_INIT(CDemoDlg)
   m_bCheckCRC       = FALSE;
   m_bCheckLogData   = FALSE;
   m_strAltitude     = _T("");
   m_strCourse       = _T("");
   m_strGpsFix       = _T("");
   m_strLatitude     = _T("");
   m_strLongitude    = _T("");
   m_strLogfile      = _T("");
   m_strResult       = _T("");
   m_strGpsSats      = _T("");
   m_strSpeed        = _T("");
   m_strTime         = _T("");
   //}}AFX_DATA_INIT

   HRESULT hr = CoCreateInstance ( CLSID_Gps, NULL, CLSCTX_INPROC_SERVER, IID_IGps, (void**) &m_pGps );

   m_bStarted  = FALSE;

   if( ! SUCCEEDED ( hr ) )
   {
      m_pGps = NULL; 
      return;
   }

   m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

/////////////////////////////////////////////////////////////////////////////

CDemoDlg::~CDemoDlg ()
{
   if ( m_pGps )
   {
      m_pGps->Close ();
      m_pGps->Release ();
   }
}

/////////////////////////////////////////////////////////////////////////////

void CDemoDlg::DoDataExchange(CDataExchange* pDX)
{
   CDialog::DoDataExchange(pDX);
   //{{AFX_DATA_MAP(CDemoDlg)
   DDX_Control(pDX, IDC_LIST_SATS, m_listSats);
   DDX_Control(pDX, IDC_COMBO_PORT, m_comboPort);
   DDX_Control(pDX, IDC_COMBO_BAUDRATE, m_comboBaudrate);
   DDX_Check(pDX, IDC_CHECK_CRC, m_bCheckCRC);
   DDX_Check(pDX, IDC_CHECK_LOGDATA, m_bCheckLogData);
   DDX_Text(pDX, IDC_EDIT_ALTITUDE, m_strAltitude);
   DDX_Text(pDX, IDC_EDIT_COURSE, m_strCourse);
   DDX_Text(pDX, IDC_EDIT_FIX, m_strGpsFix);
   DDX_Text(pDX, IDC_EDIT_LATITUDE, m_strLatitude);
   DDX_Text(pDX, IDC_EDIT_LONGITUDE, m_strLongitude);
   DDX_Text(pDX, IDC_EDIT_LOGFILE, m_strLogfile);
   DDX_Text(pDX, IDC_EDIT_RESULT, m_strResult);
   DDX_Text(pDX, IDC_EDIT_SATS, m_strGpsSats);
   DDX_Text(pDX, IDC_EDIT_SPEED, m_strSpeed);
   DDX_Text(pDX, IDC_EDIT_TIME, m_strTime);
   //}}AFX_DATA_MAP
}

/////////////////////////////////////////////////////////////////////////////

BEGIN_MESSAGE_MAP(CDemoDlg, CDialog)
   //{{AFX_MSG_MAP(CDemoDlg)
   ON_WM_PAINT()
   ON_WM_QUERYDRAGICON()
   ON_BN_CLICKED(IDC_BUTTON_START, OnButtonStart)
   ON_BN_CLICKED(IDC_BUTTON_STOP, OnButtonStop)
   ON_BN_CLICKED(IDC_BUTTON_BROWSE, OnButtonBrowse)
   ON_BN_CLICKED(IDC_BUTTON_VIEW, OnButtonView)
   ON_WM_TIMER()
   //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////

LONG CDemoDlg::GetLastResult ()
{
   LONG  lResult     = 0L;
   BSTR  bstrResult  = NULL;

   if ( m_pGps )
   {
      m_pGps->get_LastError            ( &lResult    );
      m_pGps->get_LastErrorDescription ( &bstrResult );
      
      if ( bstrResult )
      {
         m_strResult.Format ( _T("%ld (%ls)"), lResult, bstrResult );
      
         SysFreeString ( bstrResult );
      }
   }

   UpdateData ( FALSE );

   return lResult;
}

/////////////////////////////////////////////////////////////////////////////

void CDemoDlg::SetLogFile ()
{
   TCHAR tszTempPath [ MAX_PATH + 1 ];

   // Get Temp Folder
   GetTempPath ( MAX_PATH, tszTempPath );

   // Add trailing backslash
   if( tszTempPath [ 0 ] == '\0' || tszTempPath [ _tcslen ( tszTempPath ) - 1 ] != '\\' )
   {
      _tcscat( tszTempPath, _T("\\") );
   }

   // Set logfile
   m_strLogfile  = tszTempPath;
   m_strLogfile += _T("GpsLog.txt");

   UpdateData ( FALSE );
}


/////////////////////////////////////////////////////////////////////////////

BOOL CDemoDlg::OnInitDialog()
{
   LONG  lPort = 0L;

   CString  strPort  = _T("");

   CDialog::OnInitDialog();

   SetIcon(m_hIcon, TRUE);
   SetIcon(m_hIcon, FALSE);

   for ( lPort = 1 ; lPort <= 16 ; lPort++ )
   {
      strPort.Format ( _T("COM%ld"), lPort );
      m_comboPort.AddString ( strPort );
   }
   
   m_comboPort.SetCurSel ( 0 );

   m_comboBaudrate.AddString ( _T("1200"  ) );
   m_comboBaudrate.AddString ( _T("2400"  ) );
   m_comboBaudrate.AddString ( _T("4800"  ) );
   m_comboBaudrate.AddString ( _T("9600"  ) );
   m_comboBaudrate.AddString ( _T("19200" ) );
   m_comboBaudrate.AddString ( _T("38400" ) );
   m_comboBaudrate.AddString ( _T("57600" ) );
   m_comboBaudrate.AddString ( _T("115200") );

   m_comboBaudrate.SetCurSel ( 2 );

   SetupListCtrl ();

   EnableControls ();

   SetTimer ( 1, 1000L, NULL );

   SetLogFile ();

   return TRUE;  
}

/////////////////////////////////////////////////////////////////////////////

void CDemoDlg::OnPaint() 
{
   if (IsIconic())
   {
      CPaintDC dc(this);

      SendMessage ( WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

      int cxIcon = GetSystemMetrics(SM_CXICON);
      int cyIcon = GetSystemMetrics(SM_CYICON);
      CRect rect;
      GetClientRect(&rect);
      int x = (rect.Width() - cxIcon + 1) / 2;
      int y = (rect.Height() - cyIcon + 1) / 2;

      dc.DrawIcon(x, y, m_hIcon);
   }
   else
   {
      CDialog::OnPaint();
   }
}

/////////////////////////////////////////////////////////////////////////////

HCURSOR CDemoDlg::OnQueryDragIcon()
{
   return (HCURSOR) m_hIcon;
}

/////////////////////////////////////////////////////////////////////////////

void CDemoDlg::SetupListCtrl ()
{
   m_listSats.SetExtendedStyle ( LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT );

   LVCOLUMN lvCol;

   ZeroMemory (&lvCol,sizeof(LVCOLUMN));

   lvCol.mask     = LVCF_TEXT|LVCF_WIDTH;
   lvCol.cx       = 90;
   lvCol.pszText  = _T("PRN#");

   m_listSats.InsertColumn ( 0,&lvCol);

   lvCol.mask     = LVCF_TEXT|LVCF_WIDTH;
   lvCol.cx       = 90;
   lvCol.pszText  = _T("Elevation");
   
   m_listSats.InsertColumn ( 1,&lvCol);

   lvCol.mask     = LVCF_TEXT|LVCF_WIDTH;
   lvCol.cx       = 90;
   lvCol.pszText  = _T("Azimuth");

   m_listSats.InsertColumn ( 2,&lvCol);

   lvCol.mask     = LVCF_TEXT|LVCF_WIDTH;
   lvCol.cx       = 90;
   lvCol.pszText  = _T("SNR (db)");

   m_listSats.InsertColumn ( 3,&lvCol);
}

/////////////////////////////////////////////////////////////////////////////

void CDemoDlg::OnButtonStart() 
{
   BSTR  bstrTemp = NULL;

   CString  strTemp     = _T("");

   if ( m_pGps == NULL )
   {
      AfxMessageBox ( _T("GpsCtrl.dll failed to load.\nCheck if the file is 
      present on this computer\nand reregister it using REGSVR32" ) );
   }

   UpdateData ( TRUE );

   // Set Serial Port
   m_pGps->put_DeviceSerialPort ( m_comboPort.GetCurSel () + 1L );
   
   // Set Serial Baudrate
   m_comboBaudrate.GetLBText ( m_comboBaudrate.GetCurSel (), strTemp );
   m_pGps->put_DeviceBaudrate ( _tcstol ( strTemp, NULL, 10 ) );

   // Set Logfile
   bstrTemp = m_strLogfile.AllocSysString ();
   m_pGps->put_LogFile ( bstrTemp );
   SysFreeString ( bstrTemp );

   // Set CRC Checking
   m_pGps->put_EnableChecksum ( m_bCheckCRC );

   // Set NMEA logging
   m_pGps->put_LogGpsData    ( m_bCheckLogData );

   // Set Units
   m_pGps->put_UnitsSpeed     ( GPS_SPEED_KNOTS   );
   m_pGps->put_UnitsAltitude  ( GPS_ALTITUDE_FEET );

   // Set Lat-Lon format
   m_pGps->put_LatLonStringFormat ( GPS_LATLONFORMAT_DM );

   // Start !
   m_pGps->Open ();

   // Get Result and set controls
   if ( GetLastResult () == 0L )
   {
      m_bStarted = TRUE;
      EnableControls ();
   }
}

/////////////////////////////////////////////////////////////////////////////

void CDemoDlg::OnButtonStop() 
{
   if ( m_pGps == NULL )
   {
      AfxMessageBox ( _T("GpsCtrl.dll failed to load.\nCheck if the file is 
      present on this computer\nand reregister it using REGSVR32" ) );
   }

   m_bStarted = FALSE;

   m_pGps->Close ();

   EnableControls ();
}

/////////////////////////////////////////////////////////////////////////////

void CDemoDlg::EnableControls ()
{
   GetDlgItem ( IDC_BUTTON_START    )->EnableWindow ( !m_bStarted );
   GetDlgItem ( IDC_BUTTON_STOP     )->EnableWindow (  m_bStarted );

   GetDlgItem ( IDC_CHECK_CRC       )->EnableWindow ( !m_bStarted );
   GetDlgItem ( IDC_CHECK_LOGDATA   )->EnableWindow ( !m_bStarted );

   GetDlgItem ( IDC_COMBO_PORT      )->EnableWindow ( !m_bStarted );
   GetDlgItem ( IDC_COMBO_BAUDRATE  )->EnableWindow ( !m_bStarted );
}

/////////////////////////////////////////////////////////////////////////////

void CDemoDlg::OnButtonBrowse() 
{
   CFileDialog cfd ( FALSE, NULL, 0, NULL, _T("All Files (*.*)|*.*||\0\0") );
   
   UpdateData ( TRUE );
   
   cfd.m_ofn.lpstrInitialDir = m_strLogfile;
   
   if ( cfd.DoModal () == IDOK )
   {
      m_strLogfile = cfd.GetPathName ();
   }

   UpdateData ( FALSE );
}

/////////////////////////////////////////////////////////////////////////////

void CDemoDlg::OnButtonView() 
{
   UpdateData();
   
   if ( m_strLogfile.GetLength () )
   {
      if ( ShellExecute ( NULL, _T("open"), m_strLogfile, NULL, NULL, SW_SHOWDEFAULT ) == INVALID_HANDLE_VALUE ) 
      {
         AfxMessageBox ( _T("Failed to display logfile"), MB_OK );
      }
   }
}

/////////////////////////////////////////////////////////////////////////////

void CDemoDlg::OnTimer(UINT nIDEvent) 
{
   BSTR  bstrValue   = NULL;
   LONG  lValue      = 0L;
   LONG  lResult     = 0L;
   DOUBLE   dblValue = 0L;
   INT      nIndex      = 0L;
   BOOL  bUsed    = FALSE;
   
   CString  strTemp     = _T("");

   VARIANT  vtValue;

   VariantInit ( &vtValue );

   IGpsSatelliteInfo *  pSat  = NULL;
   
   if ( nIDEvent == 1 )
   {
      if ( m_bStarted )
      {
         UpdateData ( TRUE );

         LockWindowUpdate ();

         m_pGps->get_gpsLatitudeString ( &bstrValue );
         m_strLatitude = bstrValue;
         SysFreeString ( bstrValue );

         m_pGps->get_gpsLongitudeString ( &bstrValue );
         m_strLongitude = bstrValue;
         SysFreeString ( bstrValue );

         m_pGps->get_gpsSpeed ( &dblValue );
         m_strSpeed.Format ( _T("%3.1f knots"), dblValue );

         m_pGps->get_gpsCourse ( &dblValue );
         m_strCourse.Format ( _T("%3.0f degrees"), dblValue );

         m_pGps->get_gpsAltitude ( &dblValue );
         m_strAltitude.Format ( _T("%3.0f feet"), dblValue );

         m_pGps->get_gpsTimeString ( &bstrValue );
         m_strTime = bstrValue;
         SysFreeString ( bstrValue );

         m_pGps->get_gpsQuality ( &lValue );
         m_strGpsFix.Format ( _T("%ld"), lValue );

         m_pGps->get_gpsSatellites ( &lValue );
         m_strGpsSats.Format ( _T("%ld"), lValue );

         // Display information about satellites used for fix
         m_listSats.DeleteAllItems ();

         m_pGps->GetFirstSatellite ( &vtValue );
         m_pGps->get_LastError ( &lResult );

         while ( lResult == 0L )
         {
            pSat = ( vtValue.vt == VT_DISPATCH ) ? ( IGpsSatelliteInfo * ) vtValue.pdispVal : NULL;

            if ( pSat )
            {
               pSat->get_UsedForFix ( &bUsed );

               if ( bUsed )
               {
                  // Insert item with satellite PRN number
                  pSat->get_ID ( &lValue );
                  strTemp.Format ( _T("%ld"), lValue );

                  m_listSats.InsertItem ( nIndex, strTemp, 0 );

                  // Set Elevation
                  pSat->get_Elevation ( &lValue );
                  strTemp.Format ( _T("%ld"), lValue );
                  m_listSats.SetItemText ( nIndex, 1, strTemp );

                  // Set Azimuth
                  pSat->get_Azimuth ( &lValue );
                  strTemp.Format ( _T("%ld"), lValue );
                  m_listSats.SetItemText ( nIndex, 2, strTemp );

                  // Set SignalNoise ratio
                  pSat->get_SignalNoiseRatio ( &lValue );
                  strTemp.Format ( _T("%ld"), lValue );
                  m_listSats.SetItemText ( nIndex, 3, strTemp );

                  nIndex++;
               }

               VariantClear ( &vtValue );
            }

            // Get Next Satellite
            m_pGps->GetNextSatellite ( &vtValue );
            m_pGps->get_LastError ( &lResult );
         }

         UnlockWindowUpdate ();

         UpdateData ( FALSE );
      }
   }

   CDialog::OnTimer(nIDEvent);
}

/////////////////////////////////////////////////////////////////////////////