I'm currently writing a GPS map viewer application for Windows Mobile on the .NET CF 2.0. It uses a worker thread to constantly read data from the GPS receiver and raise events whenever the desired data is received (position and velocity data). There are also GpsStarted and GpsStopped events raised whenever the GPS receiver starts or stops reading data. These events are subscribed to on a Windows Form where the map is displayed.
Whenever the GpsStarted event is raised on the form, I attempt to create new instances of my arrow sprite (an orange arrow that points which direction you're going on the map), and the rectangle used to position the arrow on the screen. Then, whenever a velocity or position update is received from the GPS, in the event handler I decide whether or not to display the arrow by setting a class scope boolean variable and setting the Direction attribute of the arrow sprite. I then call the form's Invalidate() method to force the form to redraw itself, showing the updated map view and position.
Now here's where my problem comes in. Once the form's OnPaint and OnPaintBackground methods execute, the arrow sprite is a null reference and the arrow's rectangle is an empty rectangle, just as they were defined before; I thought they were set in the GpsStarted event.
The GPS receiver logic is packaged into a separate class library that is referenced by the main UI application. My problem descibed above concerns events that are defined in the GPS dll and subscribed to on the UI.
Here are the sections of my code that i'm having trouble with. Any help would be greatly appreciated.
public
partial class frmViewer : Form{
private bool mShowPositionArrow = false; private Bitmap mPositionArrow = null;
private Rectangle mArrowRec = Rectangle.Empty;
private Arrow mArrow = null;
public void Gps_GpsStarted()
{
if (InvokeRequired)
{
try
{
GenericEventHandler d = new GenericEventHandler(Gps_GpsStarted);
Invoke(d);
}
catch (ObjectDisposedException) { }
}
else
{
// create object references and set rectangle value
mArrow = new Arrow();
mArrowRec = new Rectangle(
(ClientRectangle.Width / 2) - (Arrow.Size.Width / 2),
(ClientRectangle.Height / 2) - (Arrow.Size.Height / 2),
Arrow.Size.Width, Arrow.Size.Height);
}
}
public
void Gps_GpsStopped() {
if (InvokeRequired) {
try {
GenericEventHandler d = new GenericEventHandler(Gps_GpsStopped); Invoke(d);
}
catch (ObjectDisposedException) { } }
else {
mArrow =
null; mShowPositionArrow =
false; }
}
protected
override void OnPaint(PaintEventArgs e) {
base.OnPaint(e);
// mArrow = null and mShowPositionArrow = false here
if (Program.Map != null)
{
e.Graphics.DrawImage(mMapControls.ZoomInImage,
mMapControls.ZoomInRectangle, 0, 0,
mMapControls.ZoomInRectangle.Width,
mMapControls.ZoomInRectangle.Height, GraphicsUnit.Pixel, mImgAttr);
e.Graphics.DrawImage(mMapControls.ZoomOutImage,
mMapControls.ZoomOutRectangle, 0, 0,
mMapControls.ZoomOutRectangle.Width,
mMapControls.ZoomOutRectangle.Height, GraphicsUnit.Pixel, mImgAttr);
}
}
protected override void OnPaintBackground(PaintEventArgs e)
{
try
{
if (Program.Map != null) {
// mArrow = null and mShowPositionArrow = false here if (Program.Gps != null && Program.Gps.GpsState == DeviceState.Running && mArrow !=
null && mShowPositionArrow) {
// this code SHOULD execute
mPositionArrow = mArrow.DirectionArrow;
Program.Map.DrawScreen(ref e, ref mPositionArrow, ref mArrowRec); }
else {
// this code executes
Program.Map.DrawScreen(ref e); }
}
else {
e.Graphics.FillRectangle(mBackgroundBrush, ClientRectangle);
}
}
catch (Exception ex) {
Program.ShowError("Error", ex.Message); }
}
public
void Gps_PositionChanged(Position position) {
if (InvokeRequired) {
try {
PositionChangedHandler d = new PositionChangedHandler(Gps_PositionChanged); this.Invoke(d, new object[] { position }); }
catch (ObjectDisposedException) { } }
else {
try {
if (Program.Map != null && position.FixQuality != FixQuality.Invalid) {
// mArrow != null and mShowPositionArrow = true here
if (Program.Map.GoToPosition((double)position.Longitude.Coordinate, (double)position.Latitude.Coordinate)) {
// this code executes
mShowPositionArrow =
true; Invalidate();
}
else {
mShowPositionArrow =
false; }
}
}
catch (Exception ex) {
Program.ShowError("Error", ex.Message); }
}
}
public void Gps_VelocityChanged(Velocity velocity)
{
if (InvokeRequired) {
try {
VelocityChangedHandler d = new VelocityChangedHandler(Gps_VelocityChanged); this.Invoke(d, new object[] { velocity }); }
catch (ObjectDisposedException) { } }
else {
try {
// mArrow != null and mShowPositionArrow = true here
if (mShowPositionArrow && mArrow != null) {
// this code executes
mArrow.Direction = velocity.Direction;
Invalidate();
}
}
catch (Exception ex) {
Program.ShowError("Error", ex.Message); }
}
}