Translation: 30 days Windows Mobile, day three - GPS Compass (.NET vs WinAPI / C)
- Transfer
The third part of the translation cycle. Today we have GPS Compass in turn . Previous article, Bluetooth manager - http://habrahabr.ru/blogs/mobiledev/61703/ .
The original is here .
I'm not a designer, but as mentioned earlier, the application should look attractive. Therefore, for the GPS compass, I found a very good free image on Wikimedia . When the basis for design was chosen, it remains to determine the mechanism for obtaining GPS data. The following options were available:
I settled on the third option, because it is quite new and as the documentation says, “it is useful, because provides an intermediate level of abstraction between GPS device manufacturers and developers. ” Nobody makes equipment in the same way - there are always features and pitfalls.
To test the application, I needed a GPS device, and I even had one (AT&T Tilt), but, unfortunately, in the room the signal level tended to zero. Fortunately, Microsoft found the FakeGPS utility that was just right for my purpose. This utility uses a text file with GPS data to emulate the functioning of a real GPS receiver.
In the documentation, I quickly discovered what I needed - a description of the GPS_POSITION structure. For my simple application, I needed only one flHeading field , in degrees. North is zero.
At this stage, complete with the Windows Mobile 6 SDK in the examples, I found the GPS Application - C: \ Program Files \ Windows Mobile 6 SDK \ Samples \ PocketPC \ CS \ GPS
Of course, you could write everything from scratch, but I will repeat again - always try to maximize the use of existing developments.
The application had a good status screen, the call of which I made in the menu. However, the main component of the application, of course, is displayed in the screenshot above. In principle, based on this example, you can build any application using GPS.
Download the source code .
Note translator:Chris does not like to give code examples in his articles, preferring to immediately give a link to a file with the source code of the project. However, I allow myself to make particularly interesting inserts, if relevant. In the case of GPS Compass, citing pieces of code is useless, because it will turn out either too little or too much. I’ll say one thing - if Chris hadn’t had an SDK application on hand, he would have suffered a lot since the example contains all the wrappers around native structures, enumerations and methods, this example is also good for studying the features of marshalling large and complex structures.
In Windows Mobile 5 and above, there is a unified API called GPS Intermediate Driver , which will allow many applications to simultaneously use one GPS device. This is a high-level interface, eliminating the need to parse NEMA sentences , etc.
To connect to a GPS device, we need to connect gpsapi.h and call GPSOpenDevice
This API considers links , this means that every call to GPSOpenDevice must have a closing GPSCloseDevice. GPS equipment will only turn off when the last client completes the connection.
Further, for information, we will use the GPSGetPosition or GPSGetDeviceState methods to obtain the position or status of the device, respectively. For example, to get the current location, you can use the following code:
Please note that the GPS_POSITION structure contains the dwValidFlags field. This is a bitmask that tells which fields contain the correct information. For example, if the GPS_VALID_LATITUDE flag is not set in the field, this means that you cannot rely on the dblLatitude field.
In our GPS compass we use one interesting feature. By passing two event handlers as parameters to the GPSOpenDevice method, we eliminate the need to periodically poll the device using GPSGetPosition. Instead, we just wait until this or that event fires, with a guarantee of receiving data that differs from the previously obtained values.
This is the first application that required a menu. The menu is created in the resource editor and loaded using SHCreateMenuBar . A call to this method is usually placed in the WM_INITDIALOG handler :
Next, there is a whole set of APIs for interacting with menu items. For example, you can activate or deactivate a specific item using EnableMenuItem :
Note that the same method is called to set different states of menu items. The correct place for such calls is in the WM_INITMENUPOPUP handler . This message is sent to the menu owner just before the menu is displayed.
Download the source code .
What I like about translating two articles at once is that Chris describes how to quickly add the required functionality to C #, and Christopher always digs deeper and describes the subtleties of libraries that you often just can't see from .net if you don’t get into it. Accordingly, even if there is no need or desire to program on a pure WinAPI, it is very useful to know how everything is arranged inside.
Chris Kraft C #
The original is here .
I'm not a designer, but as mentioned earlier, the application should look attractive. Therefore, for the GPS compass, I found a very good free image on Wikimedia . When the basis for design was chosen, it remains to determine the mechanism for obtaining GPS data. The following options were available:
- receive data through serial port
- using the OpenNetCF GPS library
- using GPS Intermediate Driver
I settled on the third option, because it is quite new and as the documentation says, “it is useful, because provides an intermediate level of abstraction between GPS device manufacturers and developers. ” Nobody makes equipment in the same way - there are always features and pitfalls.
To test the application, I needed a GPS device, and I even had one (AT&T Tilt), but, unfortunately, in the room the signal level tended to zero. Fortunately, Microsoft found the FakeGPS utility that was just right for my purpose. This utility uses a text file with GPS data to emulate the functioning of a real GPS receiver.
In the documentation, I quickly discovered what I needed - a description of the GPS_POSITION structure. For my simple application, I needed only one flHeading field , in degrees. North is zero.
At this stage, complete with the Windows Mobile 6 SDK in the examples, I found the GPS Application - C: \ Program Files \ Windows Mobile 6 SDK \ Samples \ PocketPC \ CS \ GPS
Of course, you could write everything from scratch, but I will repeat again - always try to maximize the use of existing developments.
The application had a good status screen, the call of which I made in the menu. However, the main component of the application, of course, is displayed in the screenshot above. In principle, based on this example, you can build any application using GPS.
Download the source code .
Note translator:Chris does not like to give code examples in his articles, preferring to immediately give a link to a file with the source code of the project. However, I allow myself to make particularly interesting inserts, if relevant. In the case of GPS Compass, citing pieces of code is useless, because it will turn out either too little or too much. I’ll say one thing - if Chris hadn’t had an SDK application on hand, he would have suffered a lot since the example contains all the wrappers around native structures, enumerations and methods, this example is also good for studying the features of marshalling large and complex structures.
Christopher Fairbairn WinAPI - C
In Windows Mobile 5 and above, there is a unified API called GPS Intermediate Driver , which will allow many applications to simultaneously use one GPS device. This is a high-level interface, eliminating the need to parse NEMA sentences , etc.
To connect to a GPS device, we need to connect gpsapi.h and call GPSOpenDevice
// Откроем соединение с GPS Intermediate Driver
HANDLE hGPS = GPSOpenDevice(NULL, NULL, NULL, 0);
* This source code was highlighted with Source Code Highlighter.
This API considers links , this means that every call to GPSOpenDevice must have a closing GPSCloseDevice. GPS equipment will only turn off when the last client completes the connection.
Further, for information, we will use the GPSGetPosition or GPSGetDeviceState methods to obtain the position or status of the device, respectively. For example, to get the current location, you can use the following code:
GPS_POSITION pos;
// Инициализируем структуру
memset(&pos, 0, sizeof(pos));
pos.dwVersion = GPS_VERSION_CURRENT;
pos.dwSize = sizeof(pos);
// Просим GPS intermediate driver
// заполнить структуру.
GPSGetPosition(hGPS, &pos, 500000, 0);
* This source code was highlighted with Source Code Highlighter.
Please note that the GPS_POSITION structure contains the dwValidFlags field. This is a bitmask that tells which fields contain the correct information. For example, if the GPS_VALID_LATITUDE flag is not set in the field, this means that you cannot rely on the dblLatitude field.
In our GPS compass we use one interesting feature. By passing two event handlers as parameters to the GPSOpenDevice method, we eliminate the need to periodically poll the device using GPSGetPosition. Instead, we just wait until this or that event fires, with a guarantee of receiving data that differs from the previously obtained values.
Create a menu.
This is the first application that required a menu. The menu is created in the resource editor and loaded using SHCreateMenuBar . A call to this method is usually placed in the WM_INITDIALOG handler :
case WM_INITDIALOG:
// Configure the menu
SHMENUBARINFO mbi;
memset(&mbi, 0, sizeof(mbi));
mbi.cbSize = sizeof(mbi);
mbi.hWndParent = hWnd; // the dialog's handle
mbi.nToolBarId = IDR_MENU; // the menu resource id
mbi.hInstRes = GetModuleHandle(NULL);
mbi.dwFlags = SHCMBF_HMENU;
// Create the menu
SHCreateMenuBar(&mbi);
break;
* This source code was highlighted with Source Code Highlighter.
Next, there is a whole set of APIs for interacting with menu items. For example, you can activate or deactivate a specific item using EnableMenuItem :
// Disable a menu item with id 'IDC_SOME_ITEM'
EnableMenuItem(hMenu, IDC_SOME_ITEM,
MF_BYCOMMAND | MF_GRAYED);
// Enable a menu item with id 'IDC_SOME_ITEM'
EnableMenuItem(hMenu, IDC_SOME_ITEM,
MF_BYCOMMAND | MF_ENABLED);
* This source code was highlighted with Source Code Highlighter.
Note that the same method is called to set different states of menu items. The correct place for such calls is in the WM_INITMENUPOPUP handler . This message is sent to the menu owner just before the menu is displayed.
Download the source code .
Conclusion from the translator
What I like about translating two articles at once is that Chris describes how to quickly add the required functionality to C #, and Christopher always digs deeper and describes the subtleties of libraries that you often just can't see from .net if you don’t get into it. Accordingly, even if there is no need or desire to program on a pure WinAPI, it is very useful to know how everything is arranged inside.