Tuesday, February 25, 2014

Jul 1, 2009

Windows Mobile 6 with C# (compass control)

Actually the textual representation did not look to great. So I decided to look for a free .NET mobile compass control - which I did not find.

Let's hack some dirty user control drawing code:

/// 
/// Paints the control.
/// 
/// 
protected override void OnPaintBackground(PaintEventArgs e)
{
    base.OnPaintBackground(e);

    int penWidth = 5;
    using (Graphics g = this.CreateGraphics())
    using (Pen penBlackThin = new Pen(Color.Black, penWidth - 3))
    using (Pen penBlack = new Pen(Color.Black, penWidth))
    using (Pen penDarkGray = new Pen(Color.DarkGray, penWidth))
    using (Pen penRed = new Pen(Color.Red, penWidth + 3))
    using (Pen penWhite = new Pen(Color.WhiteSmoke, penWidth + 3))
    using (Brush brushDarkGray = new SolidBrush(Color.DarkGray))
    using (Brush brushWhite = new SolidBrush(Color.White))
    using (Brush brushLightGray = new SolidBrush(Color.LightGray))
    using (Brush brushRed = new SolidBrush(Color.Red))
    {
        double radius = (this.ClientRectangle.Width - 50) / 2;
        double radiusInner = (this.ClientRectangle.Width - 70) / 2;
        int xcenter = this.ClientRectangle.Width / 2;
        int ycenter = this.ClientRectangle.Height / 2;
        float halfFont = this.Font.Size / 2;

        // g.Clear(this.BackColor);

        // draw circles
        g.FillEllipse(brushLightGray, penWidth, penWidth, this.ClientRectangle.Width - 2 * penWidth, this.ClientRectangle.Height - 2 * penWidth);
        g.DrawEllipse(penDarkGray, penWidth, penWidth, this.ClientRectangle.Width - 2 * penWidth, this.ClientRectangle.Height - 2 * penWidth);
        g.DrawEllipse(penBlack, 2 * penWidth, 2 * penWidth, this.ClientRectangle.Width - 4 * penWidth, this.ClientRectangle.Height - 4 * penWidth);

        // draw separator lines
        for (int l = 0; l < 16; l++)
        {
            double angle = l * 22.5 + this.Heading;
            double xout = Math.Sin(this.ToRadian(angle)) * radiusInner;
            double yout = Math.Cos(this.ToRadian(angle)) * radiusInner;
            double xin = Math.Sin(this.ToRadian(angle)) * (radiusInner - 2 *this.Font.Size);
            double yin = Math.Cos(this.ToRadian(angle)) * (radiusInner - 2 *this.Font.Size);
            g.DrawLine(penBlackThin, (int)xout + xcenter, (int)yout + ycenter, (int)xin + xcenter, (int)yin + ycenter);
        }

        // draw N, W, E, S
        double x = Math.Sin(this.ToRadian(this.Heading)) * radius;
        double y = Math.Cos(this.ToRadian(this.Heading)) * radius;
        g.DrawString("N"this.Font, brushRed, (float)(xcenter - x) - halfFont, (float)(ycenter - y) - halfFont);
        g.DrawString("S"this.Font, brushRed, (float)(xcenter + x) - halfFont, (float)(ycenter + y) - halfFont);
        g.DrawString("W"this.Font, brushRed, (float)(xcenter - y) - halfFont, (float)(ycenter + x) - halfFont);
        g.DrawString("E"this.Font, brushRed, (float)(xcenter + y) - halfFont, (float)(ycenter - x) - halfFont);

        // draw needle
        g.DrawLine(penWhite, xcenter, ycenter, xcenter, this.ClientRectangle.Height - 50);
        g.DrawLine(penRed, xcenter, 50, xcenter, ycenter);

        // draw digital heading
        g.FillRectangle(brushWhite, (int)(xcenter - 11 * halfFont), (int)(ycenter - 5 * halfFont), (int)(22 * halfFont), (int)(11 * halfFont));
        g.DrawString(string.Format("{0,3:000}°"this.Heading), this.Font, brushRed, xcenter - 4 * halfFont, ycenter - 5 * halfFont);

        // draw height above sea level
        g.DrawString(string.Format("{0,4:0000.0}m"this.Height), this.Font, brushRed, xcenter - 10 * halfFont, ycenter);
    }
}


which looks about this on the device:


Needs some adjustments, especially to look great on other screen resolutions too. Maybe later ...