Solved

Help building a digital display timer with .net

Posted on 2008-06-25
28
461 Views
Last Modified: 2013-11-26
Experts I am trying to build an application that resembles a digital clock.  My first step was to see if I could find a digital font.  This would have been the easiest solution, as I could update a labels text.  I had no luck finding a font so my next step was to have a series of images from 0 to 9 that would change depending on the time I was passing.  This became cumbersum and not very efficent.  Finally I found this control, which makes use of the drawing class.  This looks to be exactly what I need, but instead of having a clock or timer, I want it to draw the numbers that I pass it.  The entire project is in C# so I am having a harder time following the code.  Here is the project http://www.codeproject.com/KB/selection/DigitalClockControl.aspx.  I dont have a lot of experience with the drawing class so I am not really sure what is going on.  I have included a code snippet of the class that handles the drawing, the project also includes a bitmap file called Digital that has a black background with a red eight, so I am not sure where that is being used.  Can anyone help me to understand what is going on and whether or not I can get this class to draw numbers that I pass it?


using System;

using System.Drawing;

using System.Drawing.Drawing2D;
 

namespace SriClocks

{

	// A digit class which can draw a number on a graphics surface

	internal sealed class DigitalDisplay

	{

		// pens used to draw the digits

		private static Pen pen = new Pen(Color.FromArgb(255,0,0));

		private static Pen dimPen = null;
 

		private float linewidth = 20.0F;

		private Point[] Points; // end point coordinates of lines in the digital display
 

		// for each digit the display bits are set into an int

		// 'A' and 'P' are included for AM and PM display in the clock

		private int[] displayNum = new int[12]{63,12,118,94,77,91,123,14,127,95,

												  111, // to display 'A'

												  103}; // to display 'P'
 

		// Rectangles in which colons are displayed

		private Rectangle colonRect1, colonRect2;

	

		// This function is called by the paint method to display the numbers

		// A set of bits in the 'displayNum' variable define which of the

		// display legs to display

		// Based on this the ones with a '1' are in bright color and the rest

		// with '0's are in a dull color giving the effect of a digital clock

		internal void Draw(int num,  // number to display

			Graphics g) // graphics object for drawing

		{

			int check; // used to check if a leg of digit should be bright or dull
 

			// although pens are global linewidths are specific to each instance

			pen.Width = dimPen.Width = linewidth;
 

			for (int i=0; i<7; i++)

			{

				check = (int)System.Math.Pow(2, i);

				if ((check & displayNum[num])==0)

					g.DrawLine(dimPen, Points[i*2], Points[i*2+1]);

				else

					g.DrawLine(pen, Points[i*2], Points[i*2+1]);

			}

		}
 

		static private void setDimPen()

		{

			if (dimPen == null) dimPen = (Pen)pen.Clone();

			dimPen.Width = pen.Width;

			dimPen.Color = Color.FromArgb(

				pen.Color.R > 0 ? 60:0,

				pen.Color.G > 0 ? 60:0,

				pen.Color.B > 0 ? 60:0);

		}
 

		static internal void SetPenColor(DigitalColor dclr)

		{

			pen.Color = Color.FromArgb(

				(dclr == DigitalColor.RedColor) ? 255:0 ,

				(dclr == DigitalColor.GreenColor) ? 255:0,

				(dclr == DigitalColor.BlueColor) ? 255:0);

			setDimPen();

		}
 

		// function that draws a colon in the middle of the rectangular panel

		// possible modes are circular or rectangular points in the colon

		internal void DrawColon(Graphics g, ColonType type, bool dim)

		{

			pen.Width = dimPen.Width = linewidth;

			Pen p = (dim) ? dimPen : pen; // choose a pen for blinking

			switch(type)

			{

				case ColonType.Circular:

					g.DrawEllipse(p, colonRect1);

					g.DrawEllipse(p, colonRect2);

					break;

				case ColonType.Rectangular:

					g.DrawRectangle(p, colonRect1);

					g.DrawRectangle(p, colonRect2);

					break;

			}

		}
 

		// Draws the complete rectangle in dim shade to give the digital effect :-)

		internal void Draw(Graphics g)

		{

			// althought pens are static, linewidths are specific to each instance

			dimPen.Width = linewidth;

			for (int i=0; i<7; i++)

				g.DrawLine(dimPen, Points[i*2], Points[i*2+1]);

		}
 

		// Overloaded function to display characters 'A' and 'P' for AM and PM

		// Using the same algorithm used to display numbers above

		internal void Draw(char ch, // character to display

						Graphics g) // graphics object for drawing

		{

			// 10 and 11 are indices of A and P in the displayNum array

			switch(Char.ToUpper(ch))

			{

				case 'A':

					Draw(10, g);

					break;

				case 'P':

					Draw(11, g);

					break;

			}

		}
 

		// Constructor takes a rectangle and prepares the end points

		// of the lines to be drawn for the clock

		internal DigitalDisplay(Rectangle rect)

		{

			pen.StartCap = LineCap.Triangle;

			pen.EndCap = LineCap.Triangle;
 

			Points = new Point[14]; // there are 7 lines in a display

			for (int i=0; i<14; i++)

				Points[i] = new Point(0,0);

			CalculateAllParameters(rect);

		}
 

		internal void CalculateAllParameters(Rectangle rect)

		{

			linewidth = (int)(rect.Width/5);

			if (linewidth < 2) linewidth = 2;

			if (linewidth > 20) linewidth = 20;

			pen.Width = linewidth;

			setDimPen();
 

			CalculateLineEnds(rect);

			CalculateColonRectangles(rect);

		}
 

		// Function calculates end points of lines to display

		// The draw function will draw lines using this data

		private void CalculateLineEnds(Rectangle rect)

		{

			// 0,1,2,9,10,11,12 points share the same left edge X coordinate

			Points[0].X = Points[1].X = Points[2].X = Points[9].X = 

				Points[10].X = Points[11].X = Points[12].X = rect.Left;

 

			// points 3,4,5,6,7,8,13 the right edge X coordinate

			Points[3].X = Points[4].X = Points[5].X = Points[6].X =

					Points[7].X = Points[8].X = Points[13].X= rect.Right-(int)linewidth;
 

			// Points 1,2,3,4 are the top most points

			Points[1].Y = Points[2].Y = Points[3].Y = Points[4].Y = (int)(rect.Top);
 

			// Points 0,11,12,13,5,6 are the middle points

			Points[0].Y = Points[11].Y = Points[12].Y = Points[13].Y =

						Points[5].Y = Points[6].Y = 

							rect.Top + (int)((rect.Height-linewidth)/2.0);

			// points 7,8,9,10 are on the bottom edge

			Points[7].Y = Points[8].Y = Points[9].Y = Points[10].Y 

							= rect.Top + (int)(rect.Height-linewidth);
 

			// now adjust the coordinates that were computed, to get the digital look

			AdjustCoordinates();

		}

	

		// This function is necessary to give the lines a digital clock look

		// Push the coordinates a little away so that they look apart

		private void AdjustCoordinates()

		{

			Point swap; // required in case points have to be swapped

			for (int i=0; i<7; i++)

			{

				// Always draw from left to right and top to bottom

				// Adjust the end points accordingly

				if (Points[i*2].X > Points[(i*2)+1].X || Points[i*2].Y > Points[(i*2)+1].Y)

				{

					swap = Points[i*2]; Points[i*2]= Points[(i*2)+1]; Points[(i*2)+1]=swap;

				}
 

				// for horizontal lines adjust the X coord

				if (Points[i*2].X != Points[(i*2)+1].X)

				{

					Points[i*2].X += (int)(linewidth/1.6);

					Points[(i*2)+1].X -= (int)(linewidth/1.6);

				}

				// for vertical lines adjust the y coord

				if (Points[i*2].Y != Points[(i*2)+1].Y)

				{

					Points[i*2].Y += (int)(linewidth/1.6);

					Points[(i*2)+1].Y -= (int)(linewidth/1.6);

				}

			}

		}
 

		// function to calculate the rectangles required to drawn colon dot inside

		private void CalculateColonRectangles(Rectangle rect)

		{

			colonRect1 = colonRect2 = rect;

			colonRect1.X = colonRect2.X = rect.X + (int)((rect.Width - linewidth)/2.0);

			colonRect1.Y = rect.Y + rect.Height/3;

			colonRect2.Y = rect.Y + (rect.Height*2)/3;

			colonRect1.Width = colonRect1.Height = 

				colonRect2.Width = colonRect2.Height = (int) linewidth;

		}

	}

}

Open in new window

0
Comment
Question by:tentavarious
  • 16
  • 12
28 Comments
 
LVL 3

Expert Comment

by:GHCS_Mark
ID: 21866152
I am pretty sure there are other bits of code that are missing, since you don't have the definitions for the enums, however I have converted it over to VB so that maybe you can understand it better...

When you call the class, you pass in a Rectangle which is the area to be drawn upon.  The procedure then runs off and calculates all the various widths it needs in order to draw the characters at each of the 4 numeric points, plus the colon and AM/PM (A/P) points.

From what I can see in this class, you also need some code in the Paint event, which you don't have here so must be elsewhere in your example.
Imports System

Imports System.Drawing

Imports System.Drawing.Drawing2D
 

Namespace SriClocks

    ' A digit class which can draw a number on a graphics surface

    Public Enum DigitalColor

        RedColor

        GreenColor

        BlueColor

    End Enum
 

    Public Enum colonType

        Circular

        Rectangular

    End Enum
 

    Class DigitalDisplay

        ' pens used to draw the digits

        Shared pen As Pen = New Pen(Color.FromArgb(255, 0, 0))

        Shared dimPen As Pen = Nothing
 

        Private linewidth As Double = 20.0

        Private Points As Point() ' end point coordinates of lines in the digital display
 

        ' for each digit the display bits are set into an int

        ' 'A' and 'P' are included for AM and PM display in the clock

        Private displayNum As Integer() = {63, 12, 118, 94, 77, 91, 123, 14, 127, 95, 111, 103}
 

        ' Rectangles in which colons are displayed

        Private colonRect1, colonRect2 As Rectangle
 

        ' This function is called by the paint method to display the numbers

        ' A set of bits in the 'displayNum' variable define which of the

        ' display legs to display

        ' Based on this the ones with a '1' are in bright color and the rest

        ' with '0's are in a dull color giving the effect of a digital clock

        Private Sub Draw(ByVal num As Integer, ByVal g As Graphics)

            Dim check As Integer ' used to check if a leg of digit should be bright or dull
 

            ' although pens are global linewidths are specific to each instance

            pen.Width = dimPen.Width = linewidth
 

            For i As Integer = 0 To 6

                check = CType(System.Math.Pow(2, i), Integer)

                If ((check & displayNum(num)) = 0) Then

                    g.DrawLine(dimPen, Points(i * 2), Points(i * 2 + 1))

                Else

                    g.DrawLine(pen, Points(i * 2), Points(i * 2 + 1))

                End If

            Next

        End Sub
 

        Private Shared Sub setDimPen()

            If (dimPen Is Nothing) Then dimPen = CType(pen.Clone(), Pen)

            dimPen.Width = pen.Width

            dimPen.Color = Color.FromArgb( _

             IIf(pen.Color.R > 0, 60, 0), _

             IIf(pen.Color.G > 0, 60, 0), _

             IIf(pen.Color.B > 0, 60, 0))

        End Sub
 

        Private Shared Sub SetPenColor(ByVal dclr As DigitalColor)

            pen.Color = Color.FromArgb( _

             IIf(dclr = DigitalColor.RedColor, 255, 0), _

             IIf(dclr = DigitalColor.GreenColor, 255, 0), _

             IIf(dclr = DigitalColor.BlueColor, 255, 0))

            setDimPen()

        End Sub
 

        ' function that draws a colon in the middle of the rectangular panel

        ' possible modes are circular or rectangular points in the colon

        Private Sub DrawColon(ByVal g As Graphics, ByVal type As ColonType, ByVal bDim As Boolean)

            pen.Width = dimPen.Width = linewidth

            Dim p As Pen = IIf(bDim, dimPen, pen) ' choose a pen for blinking

            Select Case type

                Case ColonType.Circular

                    g.DrawEllipse(p, colonRect1)

                    g.DrawEllipse(p, colonRect2)

                Case ColonType.Rectangular

                    g.DrawRectangle(p, colonRect1)

                    g.DrawRectangle(p, colonRect2)

            End Select

        End Sub
 

        ' Draws the complete rectangle in dim shade to give the digital effect :-)

        Private Sub Draw(ByVal g As Graphics)

            ' althought pens are static, linewidths are specific to each instance

            dimPen.Width = linewidth

            For i As Integer = 0 To 6

                g.DrawLine(dimPen, Points(i * 2), Points(i * 2 + 1))

            Next

        End Sub
 

        ' Overloaded function to display characters 'A' and 'P' for AM and PM

        ' Using the same algorithm used to display numbers above

        Private Sub Draw(ByVal ch As Char, ByVal g As Graphics)

            ' 10 and 11 are indices of A and P in the displayNum array

            Select Case Char.ToUpper(ch)

                Case "A"

                    Draw(10, g)

                Case "P"

                    Draw(11, g)

            End Select

        End Sub
 

        ' Constructor takes a rectangle and prepares the end points

        ' of the lines to be drawn for the clock

        Sub DigitalDisplay(ByVal rect As Rectangle)

            pen.StartCap = LineCap.Triangle

            pen.EndCap = LineCap.Triangle
 

            ReDim Points(14) ' there are 7 lines in a display

            For i As Integer = 0 To 13

                Points(i) = New Point(0, 0)

            Next

            CalculateAllParameters(rect)

        End Sub
 

        Sub CalculateAllParameters(ByVal rect As Rectangle)

            linewidth = CType((rect.Width / 5), Integer)

            If (linewidth < 2) Then linewidth = 2

            If (linewidth > 20) Then linewidth = 20
 

            pen.Width = linewidth

            setDimPen()
 

            CalculateLineEnds(rect)

            CalculateColonRectangles(rect)

        End Sub
 

        ' Function calculates end points of lines to display

        ' The draw function will draw lines using this data

        Private Sub CalculateLineEnds(ByVal rect As Rectangle)

            ' 0,1,2,9,10,11,12 points share the same left edge X coordinate

            Points(0).X = rect.Left

            Points(1).X = Points(0).X

            Points(2).X = Points(0).X

            Points(9).X = Points(0).X

            Points(10).X = Points(0).X

            Points(11).X = Points(0).X

            Points(12).X = Points(0).X
 

            ' points 3,4,5,6,7,8,13 the right edge X coordinate

            Points(3).X = rect.Right - CType(linewidth, Integer)

            Points(4).X = Points(3).X

            Points(5).X = Points(3).X

            Points(6).X = Points(3).X

            Points(7).X = Points(3).X

            Points(8).X = Points(3).X

            Points(13).X = Points(3).X
 

            ' Points 1,2,3,4 are the top most points

            Points(1).Y = CType(rect.Top, Integer)

            Points(2).Y = Points(1).Y

            Points(3).Y = Points(1).Y

            Points(4).Y = Points(1).Y
 

            ' Points 0,11,12,13,5,6 are the middle points

            Points(0).Y = rect.Top + CType(((rect.Height - linewidth) / 2.0), Integer)

            Points(11).Y = Points(0).Y

            Points(12).Y = Points(0).Y

            Points(13).Y = Points(0).Y

            Points(5).Y = Points(0).Y

            Points(6).Y = Points(0).Y
 

            ' points 7,8,9,10 are on the bottom edge

            Points(7).Y = rect.Top + CType((rect.Height - linewidth), Integer)

            Points(8).Y = Points(7).Y

            Points(9).Y = Points(7).Y

            Points(10).Y = Points(7).Y
 

            ' now adjust the coordinates that were computed, to get the digital look

            AdjustCoordinates()

        End Sub
 

        ' This function is necessary to give the lines a digital clock look

        ' Push the coordinates a little away so that they look apart

        Private Sub AdjustCoordinates()

            Dim swap As Point  ' required in case points have to be swapped

            For i As Integer = 0 To 6

                ' Always draw from left to right and top to bottom

                ' Adjust the end points accordingly

                If (Points(i * 2).X > Points((i * 2) + 1).X Or Points(i * 2).Y > Points((i * 2) + 1).Y) Then

                    swap = Points(i * 2)

                    Points(i * 2) = Points((i * 2) + 1)

                    Points((i * 2) + 1) = swap

                End If
 

                ' for horizontal lines adjust the X coord

                If (Points(i * 2).X <> Points((i * 2) + 1).X) Then

                    Points(i * 2).X += CType((linewidth / 1.6), Integer)

                    Points((i * 2) + 1).X -= CType((linewidth / 1.6), Integer)

                End If

                ' for vertical lines adjust the y coord

                If (Points(i * 2).Y <> Points((i * 2) + 1).Y) Then

                    Points(i * 2).Y += CType((linewidth / 1.6), Integer)

                    Points((i * 2) + 1).Y -= CType((linewidth / 1.6), Integer)

                End If

            Next

        End Sub
 

        ' function to calculate the rectangles required to drawn colon dot inside

        Private Sub CalculateColonRectangles(ByVal rect As Rectangle)

            colonRect2 = rect

            colonRect1 = rect

            colonRect1.X = colonRect2.X = rect.X + CType(((rect.Width - linewidth) / 2.0), Integer)

            colonRect1.Y = rect.Y + rect.Height / 3

            colonRect2.Y = rect.Y + (rect.Height * 2) / 3

            colonRect1.Width = CType(linewidth, Integer)

            colonRect1.Height = CType(linewidth, Integer)

            colonRect2.Width = CType(linewidth, Integer)

            colonRect2.Height = CType(linewidth, Integer)

        End Sub

    End Class

End Namespace

Open in new window

0
 

Author Comment

by:tentavarious
ID: 21868447
I have included the usercontrols code that uses the above class as well as the bitmap.  I still dont know why the bitmap is needed because, I thought the class draws the numbers from scratch.  Anyway my goal is to pass the rectangle and the numbers that need to be drawn to this class.  So basically if I pass 08:00, that is what will be drawn.
using System;

using System.Collections;

using System.ComponentModel;

using System.Drawing;

using System.Data;

using System.Windows.Forms;
 

namespace SriClocks

{

	public enum ColonType { Circular, Rectangular };

	public enum ClockType {DigitalClock, StopWatch, CountDown, Freeze };

	public enum DigitalColor {RedColor, BlueColor, GreenColor };

	// Clock format. For 12 hour format display 'A' (AM) or 'P' (PM)

	public enum ClockFormat { TwentyFourHourFormat, TwelveHourFormat };
 

	// DigitalClockCtrl is a control which displays a clock

	// Possible displays include a normal digital clock,

	//   a stop watch and a count down clock

	[ToolboxBitmap("Digital.bmp")]

	public class DigitalClockCtrl : System.Windows.Forms.UserControl

	{

		private System.ComponentModel.IContainer components;
 

		private Color digitsColor = Color.Red; // color of the digits displayed

		private Color countdownColor = Color.White; // background color after count down expires

		private ClockFormat clockDisplayFormat = ClockFormat.TwelveHourFormat;
 

		private DigitalDisplay[] DigitDisplay = null; // panels on which digits are displayed

		private DigitalDisplay[] ColonDisplay = null; // panels for displaying colons

		private DigitalDisplay AmPmDisplay = null; // panel for AM/PM display

		private DigitalDisplay MicroSecDisplay = null; // panel for displaying 1/10 of a second
 

		// ShowTimer to refresh the time display

		private System.Windows.Forms.Timer ShowTimer;

		// ColonTimer to blink the colons between the digits

		private System.Windows.Forms.Timer ColonTimer;

		// type of clock to display (a normal clock, stop watch or count down)

		private ClockType clockType = ClockType.DigitalClock;
 

		// date time used to display stopwatch, count begins from this variable

		private DateTime stopwatchBegin = DateTime.Now;

		// count down in milli seconds, default of 10 seconds

		int countDownMilliSeconds = 10000;

		// whenever count down starts this time is set to Now + countDownMilliSeconds

		private DateTime countDownTo;
 

		// currently displayed numbers on the clock, useful to freeze

		int hour, min, sec, ms;

		char am_pm;
 

		// delegates called when the count down is finished

		public delegate void CountDown();

		public event CountDown CountDownDone = null;
 

		// delegates called when an alarm is set

		public delegate void Alarm();

		public event Alarm RaiseAlarm = null;

		private ArrayList AlarmTimes = new ArrayList();
 

		// graphics surface for the control on which the clock is displayed

		private static Graphics graphics;
 

		public DigitalClockCtrl()

		{

			// This call is required by the Windows.Forms Form Designer.

			InitializeComponent();

		}
 

		// set count down time in milli seconds

		public int CountDownTime

		{

			get { return countDownMilliSeconds; }

			set 

			{ 

				if (value < 1000)

					MessageBox.Show("Count down time cannot be less than 1000", "Error");

				else

					countDownMilliSeconds = value; 

			}

		}
 

		// set the alarm time

		public DateTime AlarmTime

		{

			set 

			{

				if (value < DateTime.Now)

					MessageBox.Show("Alarm time cannot be earlier.", "Error");

				else

					AlarmTimes.Add(value);

			}

		}
 

		// set the display format, 12 Hr or 24 Hr

		public ClockFormat ClockDisplayFormat

		{

			set { this.clockDisplayFormat = value; }

		}
 

		// setting clock type

		// DigitalClock and StopWatch will automatically start the clock

		// For CountDown the number of seconds should be set before calling this property

		public ClockType SetClockType

		{

			get { return clockType; }

			set 

			{ 

				clockType = value;

				switch(clockType)

				{

					case ClockType.StopWatch:

						stopwatchBegin = DateTime.Now; // start stopwatch clock

						break;

					case ClockType.CountDown:

						countDownTo = DateTime.Now.AddMilliseconds(countDownMilliSeconds);

						break;

				}

			}

		}
 

		// set the color in which the digits are displayed

		public DigitalColor SetDigitalColor

		{

			set 

			{

				this.Invalidate();

				DigitalDisplay.SetPenColor(value);

			}

		}
 

		/// <summary>

		/// Clean up any resources being used.

		/// </summary>

		protected override void Dispose( bool disposing )

		{

			if( disposing )

			{

				ShowTimer.Stop();

				ColonTimer.Stop();

				if( components != null )

					components.Dispose();

			}

			base.Dispose( disposing );

			ShowTimer.Dispose();

			ColonTimer.Dispose();

		}
 

		#region Component Designer generated code

		/// <summary>

		/// Required method for Designer support - do not modify 

		/// the contents of this method with the code editor.

		/// </summary>

		private void InitializeComponent()

		{

			this.components = new System.ComponentModel.Container();

			this.ShowTimer = new System.Windows.Forms.Timer(this.components);

			this.ColonTimer = new System.Windows.Forms.Timer(this.components);

			// 

			// ShowTimer

			// 

			this.ShowTimer.Tick += new System.EventHandler(this.OnClockTimer);

			// 

			// ColonTimer

			// 

			this.ColonTimer.Tick += new System.EventHandler(this.OnColonTimer);

			// 

			// DigitalClockCtrl

			// 

			this.BackColor = System.Drawing.Color.Black;

			this.Name = "DigitalClockCtrl";

			this.Size = new System.Drawing.Size(354, 70);

			this.Load += new System.EventHandler(this.OnLoad);

			this.Paint += new System.Windows.Forms.PaintEventHandler(this.OnPaint);
 

		}

		#endregion
 

		// OnPaint - called when regions of clock are invalidated

		private void OnPaint(object sender, System.Windows.Forms.PaintEventArgs e)

		{

			lock(this)

			{

				DisplayTime(e.Graphics);

			}

		}
 

		// This function is aware which panel should display what number

		// and also the colons and PM and AM displays

		private bool blink = false; // toggle for blinking effect of colons

		private void DisplayTime(Graphics g)

		{

			DateTime dt = DateTime.Now;

			if (clockType != ClockType.Freeze)

			{

				hour=dt.Hour; 

				min=dt.Minute; 

				sec=dt.Second; 

				ms=dt.Millisecond;

				am_pm = ' ';

			}

			TimeSpan ts = TimeSpan.Zero;
 

			// check if alarms are set, raise them

			for (int i=0; i<AlarmTimes.Count; i++)

			{

				if (dt > (DateTime)AlarmTimes[i] && RaiseAlarm != null)

				{

					AlarmTimes.RemoveAt(i);

					RaiseAlarm();

				}

			}

			switch(clockType)

			{

				case ClockType.DigitalClock:

					if (clockDisplayFormat == ClockFormat.TwelveHourFormat)

						hour = dt.Hour % 12;

					if (hour == 0) hour = 12;

					switch(clockDisplayFormat)

					{

						case ClockFormat.TwentyFourHourFormat:

							break;

						case ClockFormat.TwelveHourFormat:

							am_pm = (dt.Hour/12 > 0) ? 'P' : 'A';

							break;

					}

					break;

				case ClockType.CountDown:

					ts = countDownTo.Subtract(dt);

					if (ts < TimeSpan.Zero)

					{

						clockType = ClockType.DigitalClock;

						ts = TimeSpan.Zero;

						if (CountDownDone != null)

							CountDownDone();

					}

					break;

				case ClockType.StopWatch:

					ts = dt.Subtract(this.stopwatchBegin);

					break;

				case ClockType.Freeze:

					break;

			}

			if (clockType != ClockType.DigitalClock && 

				clockType != ClockType.Freeze) // ts used for stopwatch or countdown

			{

				hour = ts.Hours;

				min = ts.Minutes;

				sec = ts.Seconds;

				ms = ts.Milliseconds;

			}

			DigitDisplay[0].Draw(hour/10, g);

			DigitDisplay[1].Draw(hour%10, g);

			DigitDisplay[2].Draw(min/10, g);

			DigitDisplay[3].Draw(min%10, g);

			DigitDisplay[4].Draw(sec/10, g);

			DigitDisplay[5].Draw(sec%10, g);

			MicroSecDisplay.Draw(ms/100, g);

			if (am_pm == ' ')

				AmPmDisplay.Draw(g);

			else

				AmPmDisplay.Draw(am_pm, g);

		}
 

		// Timer used to refresh clock display

		private void OnClockTimer(object sender, System.EventArgs e)

		{

			DisplayTime(graphics);

		}
 

		// Keeping the colon timer, gives a special effect of colon blinking

		// independent of the seconds or 1/10 seconds display

		private void OnColonTimer(object sender, System.EventArgs e)

		{

			//display the 2 colons between the hours-minutes and minutes-seconds

			ColonDisplay[0].DrawColon(graphics, ColonType.Rectangular, blink);

			ColonDisplay[1].DrawColon(graphics, ColonType.Rectangular, blink);

			if (clockType == ClockType.Freeze)

				blink = false;

			else

				blink = !blink;

		}
 

		private void OnLoad(object sender, System.EventArgs e)

		{

			graphics = Graphics.FromHwnd(this.Handle);

			PreparePanels();

			ShowTimer.Interval = 100;

			ShowTimer.Start();  // digits are refreshed on timer count

			ColonTimer.Interval = 1000;

			ColonTimer.Start(); // this will blink the colon
 

			// adding the resize handler here so that it will be called

			// only after graphics variable is created

			this.Resize += new System.EventHandler(this.OnResize); 

		}
 

		// function to prepare the digital clock panels by dividing the rectangle

		// It is assumed that the height of each digit is double that of it's width

		// Spacing betweent the digits is 10% of the width

		// The colon characters occupy 50% of width of the digits

		private void PreparePanels()

		{

			// from the above assumptions for height and width

			// the height should be 2.4 units and width 8.8 units :-)

			// check height and width whichever is dominant and adjust the other

			// and set up margins

			Rectangle rect = new Rectangle(0, 0, this.Width, this.Height);
 

			// widths, spacings and margins

			// height of colon display is same as a digit

			int DigitWidth, DigitHeight, ColonWidth, Spacing;

			float HMargin=0, // left and right margin

					VMargin=0; // top and bottom margin
 

			// Calculate a digit width (which is our unit) from the above metrics

			// and settle for the least value

			int WidthUnit = (int)(rect.Width/8.8F);

			int HeightUnit = (int)(rect.Height/2.4F);

			DigitWidth = (WidthUnit < HeightUnit) ? WidthUnit : HeightUnit;
 

			DigitHeight = 2 * DigitWidth;  // height is twice of width

			ColonWidth = DigitWidth/2;  // colon width is half of a digit

			Spacing = DigitWidth/10;

			if (Spacing < 1) Spacing = 1; // atleast a spacing of 1 is required

			HMargin = (rect.Width - (8.8F * DigitWidth))/2;

			VMargin = (rect.Height - DigitHeight)/2;
 

			// This is the basic rectangle, offset it as required

			Rectangle basicRect = new Rectangle(0, 0, (int)DigitWidth, (int)DigitHeight);

			int XOffset, YOffset;

			Rectangle calcRect;  // calculated rectangle for a panel

			// Y offset is same for all elements, expcept 1/10 second and AM/PM display

			YOffset = (int)(VMargin);
 

			// create digit panels.  6 digits

			if (DigitDisplay == null)

				DigitDisplay = new DigitalDisplay[6];

			for (int i=0; i<6; i++)

			{

				calcRect = basicRect;

				XOffset = (int)(HMargin + (Spacing * (i+2+(i/2))) + (i * DigitWidth) + ((i/2) * ColonWidth));

				calcRect.Offset(XOffset, YOffset);

				if (DigitDisplay[i] == null)

					DigitDisplay[i] = new DigitalDisplay(calcRect);

				else

					DigitDisplay[i].CalculateAllParameters(calcRect);

			}
 

			if (ColonDisplay == null)

				ColonDisplay = new DigitalDisplay[2];

			// for first colon

			calcRect = basicRect;

			calcRect.Width = (int)ColonWidth;

			XOffset = (int)(HMargin + 3*Spacing + 2*DigitWidth);

			calcRect.Offset(XOffset, YOffset);

			if (ColonDisplay[0] == null)

				ColonDisplay[0] = new DigitalDisplay(calcRect);

			else

				ColonDisplay[0].CalculateAllParameters(calcRect);

			

			// for second colon

			calcRect = basicRect;

			calcRect.Width = (int)ColonWidth;

			XOffset = (int)((6*Spacing) + (4*DigitWidth) + ColonWidth + HMargin);

			calcRect.Offset(XOffset, YOffset);

			if (ColonDisplay[1] == null)

				ColonDisplay[1] = new DigitalDisplay(calcRect);

			else

				ColonDisplay[1].CalculateAllParameters(calcRect);
 

			// for displaying 'A'(AM) or 'P' (PM)

			calcRect = basicRect;

			calcRect.Width = (int)ColonWidth;

			calcRect.Height = calcRect.Height/2;

			XOffset = (int)((10*Spacing)+(6*DigitWidth)+(2*ColonWidth)+HMargin);

			calcRect.Offset(XOffset, (int)(YOffset + DigitHeight/2.0 + 1));

			if (AmPmDisplay == null)

				AmPmDisplay = new DigitalDisplay(calcRect);

			else

				AmPmDisplay.CalculateAllParameters(calcRect);
 

			// for displaying 1/10 of a second

			// reuse AM/PM display panel rectangle

			// only change Y coordinate, shift upwards

			calcRect.Y = YOffset-1; // just to keep it apart from AM/PM display

			if (MicroSecDisplay == null)

				MicroSecDisplay = new DigitalDisplay(calcRect);

			else

				MicroSecDisplay.CalculateAllParameters(calcRect);

		}
 

		// On resize of control recalculate the rectangles for display

		// Also recreate the graphics so that the clipping region is updated

		private void OnResize(object sender, System.EventArgs e)

		{

			lock(this)

			{

				PreparePanels();

				graphics.Dispose();

				graphics = Graphics.FromHwnd(this.Handle);

				graphics.Clear(BackColor);

			}

		}

	}

}

Open in new window

Digital.bmp
0
 
LVL 3

Expert Comment

by:GHCS_Mark
ID: 21870057
OK.  First off, the bitmap is needed to be used for display only on the form via the [ToolboxBitmap("Digital.bmp")] line.

Now, to display a specific time, rather than current time, you would take the DisplayTime function and modify it as such:


		private void DisplayTime(Graphics g)

		{

			DateTime dt = DateTime.Now;

			if (clockType != ClockType.Freeze)

			{

				hour=dt.Hour; 

				min=dt.Minute; 

				sec=dt.Second; 

				ms=dt.Millisecond;

				am_pm = ' ';

			}

			TimeSpan ts = TimeSpan.Zero;

 

			// check if alarms are set, raise them

			for (int i=0; i<AlarmTimes.Count; i++)

			{

				if (dt > (DateTime)AlarmTimes[i] && RaiseAlarm != null)

				{

					AlarmTimes.RemoveAt(i);

					RaiseAlarm();

				}

			}
 

			switch(clockType)

			{

				case ClockType.DigitalClock:

					if (clockDisplayFormat == ClockFormat.TwelveHourFormat)

						hour = dt.Hour % 12;

					if (hour == 0) hour = 12;

					switch(clockDisplayFormat)

					{

						case ClockFormat.TwentyFourHourFormat:

							break;

						case ClockFormat.TwelveHourFormat:

							am_pm = (dt.Hour/12 > 0) ? 'P' : 'A';

							break;

					}

					break;

				case ClockType.CountDown:

					ts = countDownTo.Subtract(dt);

					if (ts < TimeSpan.Zero)

					{

						clockType = ClockType.DigitalClock;

						ts = TimeSpan.Zero;

						if (CountDownDone != null)

							CountDownDone();

					}

					break;

				case ClockType.StopWatch:

					ts = dt.Subtract(this.stopwatchBegin);

					break;

				case ClockType.Freeze:

					break;

			}

			if (clockType != ClockType.DigitalClock && 

				clockType != ClockType.Freeze) // ts used for stopwatch or countdown

			{

				hour = ts.Hours;

				min = ts.Minutes;

				sec = ts.Seconds;

				ms = ts.Milliseconds;

			}
 

			DrawTime(g);

		}

		

		private void DrawTime(Grahics g)

		{

			DigitDisplay[0].Draw(hour/10, g);

			DigitDisplay[1].Draw(hour%10, g);

			DigitDisplay[2].Draw(min/10, g);

			DigitDisplay[3].Draw(min%10, g);

			DigitDisplay[4].Draw(sec/10, g);

			DigitDisplay[5].Draw(sec%10, g);

			MicroSecDisplay.Draw(ms/100, g);

			if (am_pm == ' ')

				AmPmDisplay.Draw(g);

			else

				AmPmDisplay.Draw(am_pm, g);

		}

		

		public void DisplayTime(Graphics g, int p_hour, int p_min, int p_sec, int p_ms, char p_am_pm)

		{

			hour = p_hour;

			min = p_min;

			sec = p_sec;

			ms = p_ms;

			am_pm = p_am_pm;

			

			DrawTime(g);

		}

Open in new window

0
 
LVL 3

Expert Comment

by:GHCS_Mark
ID: 21870075
Oh, and you might need to add a different clock type if you are after specifying a specific time, because the OnPaint routine would switch back to using Clock, Stopwatch or Countdown.
0
 
LVL 3

Expert Comment

by:GHCS_Mark
ID: 21870127
Here's the updated version that includes a ClockType.Static and utilises that:


		public enum ClockType {DigitalClock, StopWatch, CountDown, Freeze, Static };

		

		private void DisplayTime(Graphics g)

		{

			DateTime dt = DateTime.Now;

			if (clockType != ClockType.Freeze && clockType != ClockType.Static)

			{

				hour=dt.Hour; 

				min=dt.Minute; 

				sec=dt.Second; 

				ms=dt.Millisecond;

				am_pm = ' ';

			}

			TimeSpan ts = TimeSpan.Zero;

 

			CheckAlarms(dt);

			

			switch(clockType)

			{

				case ClockType.DigitalClock:

					if (clockDisplayFormat == ClockFormat.TwelveHourFormat)

						hour = dt.Hour % 12;

					if (hour == 0) hour = 12;

					switch(clockDisplayFormat)

					{

						case ClockFormat.TwentyFourHourFormat:

							break;

						case ClockFormat.TwelveHourFormat:

							am_pm = (dt.Hour/12 > 0) ? 'P' : 'A';

							break;

					}

					break;

				case ClockType.CountDown:

					ts = countDownTo.Subtract(dt);

					if (ts < TimeSpan.Zero)

					{

						clockType = ClockType.DigitalClock;

						ts = TimeSpan.Zero;

						if (CountDownDone != null)

							CountDownDone();

					}

					break;

				case ClockType.StopWatch:

					ts = dt.Subtract(this.stopwatchBegin);

					break;

				case ClockType.Freeze:

					break;

				case ClockType.Static:

					break;

			}

			if (clockType != ClockType.DigitalClock && 

				clockType != ClockType.Static &&

				clockType != ClockType.Freeze) // ts used for stopwatch or countdown

			{

				hour = ts.Hours;

				min = ts.Minutes;

				sec = ts.Seconds;

				ms = ts.Milliseconds;

			}
 

			DrawTime(g);

		}

		

		private void DrawTime(Grahics g)

		{

			DigitDisplay[0].Draw(hour/10, g);

			DigitDisplay[1].Draw(hour%10, g);

			DigitDisplay[2].Draw(min/10, g);

			DigitDisplay[3].Draw(min%10, g);

			DigitDisplay[4].Draw(sec/10, g);

			DigitDisplay[5].Draw(sec%10, g);

			MicroSecDisplay.Draw(ms/100, g);

			if (am_pm == ' ')

				AmPmDisplay.Draw(g);

			else

				AmPmDisplay.Draw(am_pm, g);

		}

		

		private void CheckAlarms(DateTime dt)

		{

			// check if alarms are set, raise them

			for (int i=0; i<AlarmTimes.Count; i++)

			{

				if (dt > (DateTime)AlarmTimes[i] && RaiseAlarm != null)

				{

					AlarmTimes.RemoveAt(i);

					RaiseAlarm();

				}

			}

		}
 

		// This function displays time in a static fashion

		public void DisplayTime(Graphics g, int p_hour, int p_min, int p_sec, int p_ms, char p_am_pm)

		{

			clockType = ClockType.Static;

			

			hour = p_hour;

			min = p_min;

			sec = p_sec;

			ms = p_ms;

			am_pm = p_am_pm;
 

			// Comment out the following if you don't want to raise Alarm events on the current time

			CheckAlarms(DateTime.Now);

			DrawTime(g);

		}

Open in new window

0
 
LVL 3

Expert Comment

by:GHCS_Mark
ID: 21870145
Oh, and if you are having trouble with getting the correct Graphics object to pass in, you could cheat and replace the DrawTime with a this.Invalidate(); which should force OnPaint to be called anyway.  I just think it would be neater to call it with the correct object rather than firing off yet more events.
0
 

Author Comment

by:tentavarious
ID: 21874259
Is it possible to convert this to vb.net?  Also how can I make this simple, I don't need to use any of the clock functions or date time functions I just want to draw the numbers I pass it.  I like the how the numbers look and how they resemble a digital clock, so for example: if I just pass 9999, thats what I  want drawn.  My problem, is I don't have experience with the drawing class, but I want to take that digitaldisplay class apart to make use of the drawing functions.  One more thing what does this line of code do:[ToolboxBitmap("Digital.bmp")].
0
 
LVL 3

Expert Comment

by:GHCS_Mark
ID: 21874515
This should provide for the simple version of the UserControl from there you can modify it to work how you want it to....
Imports System

Imports System.Drawing

Imports System.Drawing.Drawing2D
 

Namespace SriClocks

    ' A digit class which can draw a number on a graphics surface

    Public Enum DigitalColor

        RedColor

        GreenColor

        BlueColor

    End Enum
 

    Public Enum colonType

        Circular

        Rectangular

    End Enum
 

    Class DigitalDisplay

        ' pens used to draw the digits

        Shared pen As Pen = New Pen(Color.FromArgb(255, 0, 0))

        Shared dimPen As Pen = Nothing
 

        Private linewidth As Double = 20.0

        Private Points As Point() ' end point coordinates of lines in the digital display
 

        ' for each digit the display bits are set into an int

        ' 'A' and 'P' are included for AM and PM display in the clock

        Private displayNum As Integer() = {63, 12, 118, 94, 77, 91, 123, 14, 127, 95, 111, 103}
 

        ' Rectangles in which colons are displayed

        Private colonRect1, colonRect2 As Rectangle
 

        ' This function is called by the paint method to display the numbers

        ' A set of bits in the 'displayNum' variable define which of the

        ' display legs to display

        ' Based on this the ones with a '1' are in bright color and the rest

        ' with '0's are in a dull color giving the effect of a digital clock

        Protected Friend Sub Draw(ByVal num As Integer, ByVal g As Graphics)

            Dim check As Integer ' used to check if a leg of digit should be bright or dull
 

            ' although pens are global linewidths are specific to each instance

            pen.Width = dimPen.Width = linewidth
 

            For i As Integer = 0 To 6

                check = CType(System.Math.Pow(2, i), Integer)

                If ((check & displayNum(num)) = 0) Then

                    g.DrawLine(dimPen, Points(i * 2), Points(i * 2 + 1))

                Else

                    g.DrawLine(pen, Points(i * 2), Points(i * 2 + 1))

                End If

            Next

        End Sub
 

        Private Shared Sub setDimPen()

            If (dimPen Is Nothing) Then dimPen = CType(pen.Clone(), Pen)

            dimPen.Width = pen.Width

            dimPen.Color = Color.FromArgb( _

             IIf(pen.Color.R > 0, 60, 0), _

             IIf(pen.Color.G > 0, 60, 0), _

             IIf(pen.Color.B > 0, 60, 0))

        End Sub
 

        Private Shared Sub SetPenColor(ByVal dclr As DigitalColor)

            pen.Color = Color.FromArgb( _

             IIf(dclr = DigitalColor.RedColor, 255, 0), _

             IIf(dclr = DigitalColor.GreenColor, 255, 0), _

             IIf(dclr = DigitalColor.BlueColor, 255, 0))

            setDimPen()

        End Sub
 

        ' function that draws a colon in the middle of the rectangular panel

        ' possible modes are circular or rectangular points in the colon

        Private Sub DrawColon(ByVal g As Graphics, ByVal type As ColonType, ByVal bDim As Boolean)

            pen.Width = dimPen.Width = linewidth

            Dim p As Pen = IIf(bDim, dimPen, pen) ' choose a pen for blinking

            Select Case type

                Case ColonType.Circular

                    g.DrawEllipse(p, colonRect1)

                    g.DrawEllipse(p, colonRect2)

                Case ColonType.Rectangular

                    g.DrawRectangle(p, colonRect1)

                    g.DrawRectangle(p, colonRect2)

            End Select

        End Sub
 

        ' Draws the complete rectangle in dim shade to give the digital effect :-)

        Protected Friend Sub Draw(ByVal g As Graphics)

            ' althought pens are static, linewidths are specific to each instance

            dimPen.Width = linewidth

            For i As Integer = 0 To 6

                g.DrawLine(dimPen, Points(i * 2), Points(i * 2 + 1))

            Next

        End Sub
 

        ' Overloaded function to display characters 'A' and 'P' for AM and PM

        ' Using the same algorithm used to display numbers above

        Protected Friend Sub Draw(ByVal ch As Char, ByVal g As Graphics)

            ' 10 and 11 are indices of A and P in the displayNum array

            Select Case Char.ToUpper(ch)

                Case "A"

                    Draw(10, g)

                Case "P"

                    Draw(11, g)

            End Select

        End Sub
 

        ' Constructor takes a rectangle and prepares the end points

        ' of the lines to be drawn for the clock

        Sub DigitalDisplay(ByVal rect As Rectangle)

            pen.StartCap = LineCap.Triangle

            pen.EndCap = LineCap.Triangle
 

            ReDim Points(14) ' there are 7 lines in a display

            For i As Integer = 0 To 13

                Points(i) = New Point(0, 0)

            Next

            CalculateAllParameters(rect)

        End Sub
 

        Sub CalculateAllParameters(ByVal rect As Rectangle)

            linewidth = CType((rect.Width / 5), Integer)

            If (linewidth < 2) Then linewidth = 2

            If (linewidth > 20) Then linewidth = 20
 

            pen.Width = linewidth

            setDimPen()
 

            CalculateLineEnds(rect)

            CalculateColonRectangles(rect)

        End Sub
 

        ' Function calculates end points of lines to display

        ' The draw function will draw lines using this data

        Private Sub CalculateLineEnds(ByVal rect As Rectangle)

            ' 0,1,2,9,10,11,12 points share the same left edge X coordinate

            Points(0).X = rect.Left

            Points(1).X = Points(0).X

            Points(2).X = Points(0).X

            Points(9).X = Points(0).X

            Points(10).X = Points(0).X

            Points(11).X = Points(0).X

            Points(12).X = Points(0).X
 

            ' points 3,4,5,6,7,8,13 the right edge X coordinate

            Points(3).X = rect.Right - CType(linewidth, Integer)

            Points(4).X = Points(3).X

            Points(5).X = Points(3).X

            Points(6).X = Points(3).X

            Points(7).X = Points(3).X

            Points(8).X = Points(3).X

            Points(13).X = Points(3).X
 

            ' Points 1,2,3,4 are the top most points

            Points(1).Y = CType(rect.Top, Integer)

            Points(2).Y = Points(1).Y

            Points(3).Y = Points(1).Y

            Points(4).Y = Points(1).Y
 

            ' Points 0,11,12,13,5,6 are the middle points

            Points(0).Y = rect.Top + CType(((rect.Height - linewidth) / 2.0), Integer)

            Points(11).Y = Points(0).Y

            Points(12).Y = Points(0).Y

            Points(13).Y = Points(0).Y

            Points(5).Y = Points(0).Y

            Points(6).Y = Points(0).Y
 

            ' points 7,8,9,10 are on the bottom edge

            Points(7).Y = rect.Top + CType((rect.Height - linewidth), Integer)

            Points(8).Y = Points(7).Y

            Points(9).Y = Points(7).Y

            Points(10).Y = Points(7).Y
 

            ' now adjust the coordinates that were computed, to get the digital look

            AdjustCoordinates()

        End Sub
 

        ' This function is necessary to give the lines a digital clock look

        ' Push the coordinates a little away so that they look apart

        Private Sub AdjustCoordinates()

            Dim swap As Point  ' required in case points have to be swapped

            For i As Integer = 0 To 6

                ' Always draw from left to right and top to bottom

                ' Adjust the end points accordingly

                If (Points(i * 2).X > Points((i * 2) + 1).X Or Points(i * 2).Y > Points((i * 2) + 1).Y) Then

                    swap = Points(i * 2)

                    Points(i * 2) = Points((i * 2) + 1)

                    Points((i * 2) + 1) = swap

                End If
 

                ' for horizontal lines adjust the X coord

                If (Points(i * 2).X <> Points((i * 2) + 1).X) Then

                    Points(i * 2).X += CType((linewidth / 1.6), Integer)

                    Points((i * 2) + 1).X -= CType((linewidth / 1.6), Integer)

                End If

                ' for vertical lines adjust the y coord

                If (Points(i * 2).Y <> Points((i * 2) + 1).Y) Then

                    Points(i * 2).Y += CType((linewidth / 1.6), Integer)

                    Points((i * 2) + 1).Y -= CType((linewidth / 1.6), Integer)

                End If

            Next

        End Sub
 

        ' function to calculate the rectangles required to drawn colon dot inside

        Private Sub CalculateColonRectangles(ByVal rect As Rectangle)

            colonRect2 = rect

            colonRect1 = rect

            colonRect1.X = colonRect2.X = rect.X + CType(((rect.Width - linewidth) / 2.0), Integer)

            colonRect1.Y = rect.Y + rect.Height / 3

            colonRect2.Y = rect.Y + (rect.Height * 2) / 3

            colonRect1.Width = CType(linewidth, Integer)

            colonRect1.Height = CType(linewidth, Integer)

            colonRect2.Width = CType(linewidth, Integer)

            colonRect2.Height = CType(linewidth, Integer)

        End Sub

    End Class
 

    <ToolboxBitmap("Digital.bmp")> _

    Class DigitalClock

        Inherits System.Windows.Forms.UserControl
 

        Private DigitDisplay As DigitalDisplay() = Nothing ' panels on which digits are displayed

        Private ColonDisplay As DigitalDisplay() = Nothing ' panels for displaying colons

        Private AmPmDisplay As DigitalDisplay = Nothing  ' panel for AM/PM display

        Private MicroSecDisplay As DigitalDisplay = Nothing ' panel for displaying 1/10 of a second
 

        ' This function displays time in a static fashion

        Public Sub DisplayTime(ByVal g As Graphics, ByVal hour As Integer, ByVal min As Integer, ByVal sec As Integer, ByVal ms As Integer, ByVal am_pm As Char)

            DigitDisplay(0).Draw(hour / 10, g)

            DigitDisplay(1).Draw(hour Mod 10, g)

            DigitDisplay(2).Draw(min / 10, g)

            DigitDisplay(3).Draw(min Mod 10, g)

            DigitDisplay(4).Draw(sec / 10, g)

            DigitDisplay(5).Draw(sec Mod 10, g)

            MicroSecDisplay.Draw(ms / 100, g)

            If (am_pm = " ") Then

                AmPmDisplay.Draw(g)

            Else

                AmPmDisplay.Draw(am_pm, g)

            End If

        End Sub

    End Class

End Namespace

Open in new window

0
 

Author Comment

by:tentavarious
ID: 21874801
This is a dumb question, but what do I pass for the graphics argument?  The form i want it displayed on?
0
 
LVL 3

Expert Comment

by:GHCS_Mark
ID: 21874857
I have updated the solution once more, to now have a GetGraphics() property (readonly) and correctly initialise the class to work out its dimensions, etc.  Plus, you now have DisplayTime(string) which will accept a numeric string of upto six numbers and display this on screen.  You might notice some real estate not being used by the class coz I have left in the rest of the panels within the PreparePanels() section.
Imports System

Imports System.Drawing

Imports System.Drawing.Drawing2D
 

Namespace SriClocks

    ' A digit class which can draw a number on a graphics surface

    Public Enum DigitalColor

        RedColor

        GreenColor

        BlueColor

    End Enum
 

    Public Enum colonType

        Circular

        Rectangular

    End Enum
 

    Class DigitalDisplay

        ' pens used to draw the digits

        Shared pen As Pen = New Pen(Color.FromArgb(255, 0, 0))

        Shared dimPen As Pen = Nothing
 

        Private linewidth As Double = 20.0

        Private Points As Point() ' end point coordinates of lines in the digital display
 

        ' for each digit the display bits are set into an int

        ' 'A' and 'P' are included for AM and PM display in the clock

        Private displayNum As Integer() = {63, 12, 118, 94, 77, 91, 123, 14, 127, 95, 111, 103}
 

        ' Rectangles in which colons are displayed

        Private colonRect1, colonRect2 As Rectangle
 

        ' This function is called by the paint method to display the numbers

        ' A set of bits in the 'displayNum' variable define which of the

        ' display legs to display

        ' Based on this the ones with a '1' are in bright color and the rest

        ' with '0's are in a dull color giving the effect of a digital clock

        Protected Friend Sub Draw(ByVal num As Integer, ByVal g As Graphics)

            Dim check As Integer ' used to check if a leg of digit should be bright or dull
 

            ' although pens are global linewidths are specific to each instance

            pen.Width = dimPen.Width = linewidth
 

            For i As Integer = 0 To 6

                check = CType(System.Math.Pow(2, i), Integer)

                If ((check & displayNum(num)) = 0) Then

                    g.DrawLine(dimPen, Points(i * 2), Points(i * 2 + 1))

                Else

                    g.DrawLine(pen, Points(i * 2), Points(i * 2 + 1))

                End If

            Next

        End Sub
 

        Private Shared Sub setDimPen()

            If (dimPen Is Nothing) Then dimPen = CType(pen.Clone(), Pen)

            dimPen.Width = pen.Width

            dimPen.Color = Color.FromArgb( _

             IIf(pen.Color.R > 0, 60, 0), _

             IIf(pen.Color.G > 0, 60, 0), _

             IIf(pen.Color.B > 0, 60, 0))

        End Sub
 

        Private Shared Sub SetPenColor(ByVal dclr As DigitalColor)

            pen.Color = Color.FromArgb( _

             IIf(dclr = DigitalColor.RedColor, 255, 0), _

             IIf(dclr = DigitalColor.GreenColor, 255, 0), _

             IIf(dclr = DigitalColor.BlueColor, 255, 0))

            setDimPen()

        End Sub
 

        ' function that draws a colon in the middle of the rectangular panel

        ' possible modes are circular or rectangular points in the colon

        Private Sub DrawColon(ByVal g As Graphics, ByVal type As ColonType, ByVal bDim As Boolean)

            pen.Width = dimPen.Width = linewidth

            Dim p As Pen = IIf(bDim, dimPen, pen) ' choose a pen for blinking

            Select Case type

                Case ColonType.Circular

                    g.DrawEllipse(p, colonRect1)

                    g.DrawEllipse(p, colonRect2)

                Case ColonType.Rectangular

                    g.DrawRectangle(p, colonRect1)

                    g.DrawRectangle(p, colonRect2)

            End Select

        End Sub
 

        ' Draws the complete rectangle in dim shade to give the digital effect :-)

        Protected Friend Sub Draw(ByVal g As Graphics)

            ' althought pens are static, linewidths are specific to each instance

            dimPen.Width = linewidth

            For i As Integer = 0 To 6

                g.DrawLine(dimPen, Points(i * 2), Points(i * 2 + 1))

            Next

        End Sub
 

        ' Overloaded function to display characters 'A' and 'P' for AM and PM

        ' Using the same algorithm used to display numbers above

        Protected Friend Sub Draw(ByVal ch As Char, ByVal g As Graphics)

            ' 10 and 11 are indices of A and P in the displayNum array

            Select Case Char.ToUpper(ch)

                Case "A"

                    Draw(10, g)

                Case "P"

                    Draw(11, g)

            End Select

        End Sub
 

        ' Constructor takes a rectangle and prepares the end points

        ' of the lines to be drawn for the clock

        Public Sub New(ByVal rect As Rectangle)

            pen.StartCap = LineCap.Triangle

            pen.EndCap = LineCap.Triangle
 

            ReDim Points(14) ' there are 7 lines in a display

            For i As Integer = 0 To 13

                Points(i) = New Point(0, 0)

            Next

            CalculateAllParameters(rect)

        End Sub
 

        Sub CalculateAllParameters(ByVal rect As Rectangle)

            linewidth = CType((rect.Width / 5), Integer)

            If (linewidth < 2) Then linewidth = 2

            If (linewidth > 20) Then linewidth = 20
 

            pen.Width = linewidth

            setDimPen()
 

            CalculateLineEnds(rect)

            CalculateColonRectangles(rect)

        End Sub
 

        ' Function calculates end points of lines to display

        ' The draw function will draw lines using this data

        Private Sub CalculateLineEnds(ByVal rect As Rectangle)

            ' 0,1,2,9,10,11,12 points share the same left edge X coordinate

            Points(0).X = rect.Left

            Points(1).X = Points(0).X

            Points(2).X = Points(0).X

            Points(9).X = Points(0).X

            Points(10).X = Points(0).X

            Points(11).X = Points(0).X

            Points(12).X = Points(0).X
 

            ' points 3,4,5,6,7,8,13 the right edge X coordinate

            Points(3).X = rect.Right - CType(linewidth, Integer)

            Points(4).X = Points(3).X

            Points(5).X = Points(3).X

            Points(6).X = Points(3).X

            Points(7).X = Points(3).X

            Points(8).X = Points(3).X

            Points(13).X = Points(3).X
 

            ' Points 1,2,3,4 are the top most points

            Points(1).Y = CType(rect.Top, Integer)

            Points(2).Y = Points(1).Y

            Points(3).Y = Points(1).Y

            Points(4).Y = Points(1).Y
 

            ' Points 0,11,12,13,5,6 are the middle points

            Points(0).Y = rect.Top + CType(((rect.Height - linewidth) / 2.0), Integer)

            Points(11).Y = Points(0).Y

            Points(12).Y = Points(0).Y

            Points(13).Y = Points(0).Y

            Points(5).Y = Points(0).Y

            Points(6).Y = Points(0).Y
 

            ' points 7,8,9,10 are on the bottom edge

            Points(7).Y = rect.Top + CType((rect.Height - linewidth), Integer)

            Points(8).Y = Points(7).Y

            Points(9).Y = Points(7).Y

            Points(10).Y = Points(7).Y
 

            ' now adjust the coordinates that were computed, to get the digital look

            AdjustCoordinates()

        End Sub
 

        ' This function is necessary to give the lines a digital clock look

        ' Push the coordinates a little away so that they look apart

        Private Sub AdjustCoordinates()

            Dim swap As Point  ' required in case points have to be swapped

            For i As Integer = 0 To 6

                ' Always draw from left to right and top to bottom

                ' Adjust the end points accordingly

                If (Points(i * 2).X > Points((i * 2) + 1).X Or Points(i * 2).Y > Points((i * 2) + 1).Y) Then

                    swap = Points(i * 2)

                    Points(i * 2) = Points((i * 2) + 1)

                    Points((i * 2) + 1) = swap

                End If
 

                ' for horizontal lines adjust the X coord

                If (Points(i * 2).X <> Points((i * 2) + 1).X) Then

                    Points(i * 2).X += CType((linewidth / 1.6), Integer)

                    Points((i * 2) + 1).X -= CType((linewidth / 1.6), Integer)

                End If

                ' for vertical lines adjust the y coord

                If (Points(i * 2).Y <> Points((i * 2) + 1).Y) Then

                    Points(i * 2).Y += CType((linewidth / 1.6), Integer)

                    Points((i * 2) + 1).Y -= CType((linewidth / 1.6), Integer)

                End If

            Next

        End Sub
 

        ' function to calculate the rectangles required to drawn colon dot inside

        Private Sub CalculateColonRectangles(ByVal rect As Rectangle)

            colonRect2 = rect

            colonRect1 = rect

            colonRect1.X = colonRect2.X = rect.X + CType(((rect.Width - linewidth) / 2.0), Integer)

            colonRect1.Y = rect.Y + rect.Height / 3

            colonRect2.Y = rect.Y + (rect.Height * 2) / 3

            colonRect1.Width = CType(linewidth, Integer)

            colonRect1.Height = CType(linewidth, Integer)

            colonRect2.Width = CType(linewidth, Integer)

            colonRect2.Height = CType(linewidth, Integer)

        End Sub

    End Class
 

    <ToolboxBitmap("Digital.bmp")> _

    Class DigitalClock

        Inherits System.Windows.Forms.UserControl
 

        Private DigitDisplay As DigitalDisplay() = Nothing ' panels on which digits are displayed

        Private ColonDisplay As DigitalDisplay() = Nothing ' panels for displaying colons

        Private AmPmDisplay As DigitalDisplay = Nothing  ' panel for AM/PM display

        Private MicroSecDisplay As DigitalDisplay = Nothing ' panel for displaying 1/10 of a second

        Private MyGraphics As Graphics
 

        ' This function displays time in a static fashion

        Public Sub DisplayTime(ByVal numString As String)

            Dim intNumber As Integer

            If Integer.TryParse(numString, intNumber) Then

                Dim strNumber As String = intNumber.ToString()

                Dim intDigit As Integer
 

                For intLoop As Integer = 0 To 5

                    If strNumber.Length < intLoop AndAlso _

                        Integer.TryParse(strNumber(intLoop), intDigit) Then

                        DigitDisplay(intLoop).Draw(intDigit, MyGraphics)

                    Else

                        DigitDisplay(intLoop).Draw(MyGraphics)

                    End If

                Next

            Else

                Throw New ArgumentException("String was not a number", "numString")

            End If

        End Sub
 

        Public Sub DisplayTime(ByVal hour As Integer, ByVal min As Integer, ByVal sec As Integer, ByVal ms As Integer, ByVal am_pm As Char)

            DisplayTime(Me.GetGraphics(), hour, min, sec, ms, am_pm)

        End Sub
 

        Public Sub DisplayTime(ByVal g As Graphics, ByVal hour As Integer, ByVal min As Integer, ByVal sec As Integer, ByVal ms As Integer, ByVal am_pm As Char)

            DigitDisplay(0).Draw(hour / 10, g)

            DigitDisplay(1).Draw(hour Mod 10, g)

            DigitDisplay(2).Draw(min / 10, g)

            DigitDisplay(3).Draw(min Mod 10, g)

            DigitDisplay(4).Draw(sec / 10, g)

            DigitDisplay(5).Draw(sec Mod 10, g)

            MicroSecDisplay.Draw(ms / 100, g)

            If (am_pm = " ") Then

                AmPmDisplay.Draw(g)

            Else

                AmPmDisplay.Draw(am_pm, g)

            End If

        End Sub
 

        Public ReadOnly Property GetGraphics() As Graphics

            Get

                Return MyGraphics

            End Get

        End Property
 

        ' function to prepare the digital clock panels by dividing the rectangle

        ' It is assumed that the height of each digit is double that of it's width

        ' Spacing betweent the digits is 10% of the width

        ' The colon characters occupy 50% of width of the digits

        Private Sub PreparePanels()

            ' from the above assumptions for height and width

            ' the height should be 2.4 units and width 8.8 units :-)

            ' check height and width whichever is dominant and adjust the other

            ' and set up margins

            Dim rect As Rectangle = New Rectangle(0, 0, Me.Width, Me.Height)
 

            ' widths, spacings and margins

            ' height of colon display is same as a digit

            Dim DigitWidth, DigitHeight, ColonWidth, Spacing As Integer

            Dim HMargin As Double = 0 ' left and right margin

            Dim VMargin As Double = 0 ' top and bottom margin
 

            ' Calculate a digit width (which is our unit) from the above metrics

            ' and settle for the least value

            Dim WidthUnit As Integer = CType(rect.Width / 8.8F, Integer)

            Dim HeightUnit As Integer = CType((rect.Height / 2.4F), Integer)

            DigitWidth = IIf(WidthUnit < HeightUnit, WidthUnit, HeightUnit)
 

            DigitHeight = 2 * DigitWidth ' height is twice of width

            ColonWidth = DigitWidth / 2 'colon width is half of a digit

            Spacing = DigitWidth / 10

            If (Spacing < 1) Then Spacing = 1 ' atleast a spacing of 1 is required

            HMargin = (rect.Width - (8.8F * DigitWidth)) / 2

            VMargin = (rect.Height - DigitHeight) / 2
 

            ' This is the basic rectangle, offset it as required

            Dim basicRect As Rectangle = New Rectangle(0, 0, CType(DigitWidth, Integer), CType(DigitHeight, Integer))

            Dim XOffset, YOffset As Integer

            Dim calcRect As Rectangle   ' calculated rectangle for a panel

            ' Y offset is same for all elements, expcept 1/10 second and AM/PM display

            YOffset = CType(VMargin, Integer)
 

            ' create digit panels.  6 digits

            If (DigitDisplay Is Nothing) Then

                ReDim DigitDisplay(6)

            End If
 

            For i As Integer = 0 To 5

                calcRect = basicRect

                XOffset = CType((HMargin + (Spacing * (i + 2 + (i / 2))) + (i * DigitWidth) + ((i / 2) * ColonWidth)), Integer)

                calcRect.Offset(XOffset, YOffset)

                If (DigitDisplay(i) Is Nothing) Then

                    DigitDisplay(i) = New DigitalDisplay(calcRect)

                Else

                    DigitDisplay(i).CalculateAllParameters(calcRect)

                End If

            Next
 

            If (ColonDisplay Is Nothing) Then

                ReDim ColonDisplay(2)

            End If
 

            ' for first colon

            calcRect = basicRect

            calcRect.Width = CType(ColonWidth, Integer)

            XOffset = CType((HMargin + 3 * Spacing + 2 * DigitWidth), Integer)

            calcRect.Offset(XOffset, YOffset)

            If (ColonDisplay(0) Is Nothing) Then

                ColonDisplay(0) = New DigitalDisplay(calcRect)

            Else

                ColonDisplay(0).CalculateAllParameters(calcRect)

            End If
 

            ' for second colon

            calcRect = basicRect

            calcRect.Width = CType(ColonWidth, Integer)

            XOffset = CType(((6 * Spacing) + (4 * DigitWidth) + ColonWidth + HMargin), Integer)

            calcRect.Offset(XOffset, YOffset)

            If (ColonDisplay(1) Is Nothing) Then

                ColonDisplay(1) = New DigitalDisplay(calcRect)

            Else

                ColonDisplay(1).CalculateAllParameters(calcRect)

            End If
 

            ' for displaying 'A'(AM) or 'P' (PM)

            calcRect = basicRect

            calcRect.Width = CType(ColonWidth, Integer)

            calcRect.Height = calcRect.Height / 2

            XOffset = CType(((10 * Spacing) + (6 * DigitWidth) + (2 * ColonWidth) + HMargin), Integer)

            calcRect.Offset(XOffset, CType((YOffset + DigitHeight / 2.0 + 1), Integer))

            If (AmPmDisplay Is Nothing) Then

                AmPmDisplay = New DigitalDisplay(calcRect)

            Else

                AmPmDisplay.CalculateAllParameters(calcRect)

            End If
 

            ' for displaying 1/10 of a second

            ' reuse AM/PM display panel rectangle

            ' only change Y coordinate, shift upwards

            calcRect.Y = YOffset - 1 ' just to keep it apart from AM/PM display

            If (MicroSecDisplay Is Nothing) Then

                MicroSecDisplay = New DigitalDisplay(calcRect)

            Else

                MicroSecDisplay.CalculateAllParameters(calcRect)

            End If

        End Sub
 

        ' On resize of control recalculate the rectangles for display

        ' Also recreate the graphics so that the clipping region is updated

        Private Sub DigitalClock_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize

            SyncLock (Me)

                PreparePanels()

                MyGraphics.Dispose()

                MyGraphics = Graphics.FromHwnd(Me.Handle)

                MyGraphics.Clear(BackColor)

            End SyncLock

        End Sub
 

        Private Sub DigitalClock_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

            MyGraphics = Graphics.FromHwnd(Me.Handle)

            PreparePanels()

        End Sub

    End Class

End Namespace

Open in new window

0
 

Author Comment

by:tentavarious
ID: 21875141
Ok, I am having some problems getting this to work.  I keep getting an error saying Object reference not set to an instance of an object.
This error happens when I tried to display some numbers in the DisplayTime function.  I removed the am/pm argument since I won't be using this as an actual clock.  I think the problem is when I initialize the Sriclocks.DigitalDisplay class
Imports System

Imports System.Drawing

Imports System.Drawing.Drawing2D

<ToolboxBitmap("Digital.bmp")> _

Public Class Form2

    Inherits System.Windows.Forms.Form

    Private DigitDisplay As SriClocks.DigitalDisplay() = Nothing ' panels on which digits are displayed

    Private ColonDisplay As SriClocks.DigitalDisplay() = Nothing ' panels for displaying colons

    Private AmPmDisplay As SriClocks.DigitalDisplay = Nothing  ' panel for AM/PM display

    Private MicroSecDisplay As SriClocks.DigitalDisplay = Nothing ' panel for displaying 1/10 of a second

    Private MyGraphics As Graphics
 

    ' This function displays time in a static fashion

    

    Public Sub DisplayTime(ByVal hour As Integer, ByVal min As Integer, ByVal sec As Integer, ByVal ms As Integer)

        DisplayTime(Me.GetGraphics(), hour, min, sec, ms)

    End Sub
 

    Public Sub DisplayTime(ByVal g As Graphics, ByVal hour As Integer, ByVal min As Integer, ByVal sec As Integer, ByVal ms As Integer)

        DigitDisplay(0).Draw(hour / 10, g)

        DigitDisplay(1).Draw(hour Mod 10, g)

        DigitDisplay(2).Draw(min / 10, g)

        DigitDisplay(3).Draw(min Mod 10, g)

        DigitDisplay(4).Draw(sec / 10, g)

        DigitDisplay(5).Draw(sec Mod 10, g)

        MicroSecDisplay.Draw(ms / 100, g)

    End Sub
 

    Public ReadOnly Property GetGraphics() As Graphics

        Get

            Return MyGraphics

        End Get

    End Property
 

    ' function to prepare the digital clock panels by dividing the rectangle

    ' It is assumed that the height of each digit is double that of it's width

    ' Spacing betweent the digits is 10% of the width

    ' The colon characters occupy 50% of width of the digits

    Private Sub PreparePanels()

        ' from the above assumptions for height and width

        ' the height should be 2.4 units and width 8.8 units :-)

        ' check height and width whichever is dominant and adjust the other

        ' and set up margins

        Dim rect As Rectangle = New Rectangle(0, 0, Me.Width, Me.Height)
 

        ' widths, spacings and margins

        ' height of colon display is same as a digit

        Dim DigitWidth, DigitHeight, ColonWidth, Spacing As Integer

        Dim HMargin As Double = 0 ' left and right margin

        Dim VMargin As Double = 0 ' top and bottom margin
 

        ' Calculate a digit width (which is our unit) from the above metrics

        ' and settle for the least value

        Dim WidthUnit As Integer = CType(rect.Width / 8.8F, Integer)

        Dim HeightUnit As Integer = CType((rect.Height / 2.4F), Integer)

        DigitWidth = IIf(WidthUnit < HeightUnit, WidthUnit, HeightUnit)
 

        DigitHeight = 2 * DigitWidth ' height is twice of width

        ColonWidth = DigitWidth / 2 'colon width is half of a digit

        Spacing = DigitWidth / 10

        If (Spacing < 1) Then Spacing = 1 ' atleast a spacing of 1 is required

        HMargin = (rect.Width - (8.8F * DigitWidth)) / 2

        VMargin = (rect.Height - DigitHeight) / 2
 

        ' This is the basic rectangle, offset it as required

        Dim basicRect As Rectangle = New Rectangle(0, 0, CType(DigitWidth, Integer), CType(DigitHeight, Integer))

        Dim XOffset, YOffset As Integer

        Dim calcRect As Rectangle   ' calculated rectangle for a panel

        ' Y offset is same for all elements, expcept 1/10 second and AM/PM display

        YOffset = CType(VMargin, Integer)
 

        ' create digit panels.  6 digits

        If (DigitDisplay Is Nothing) Then

            ReDim DigitDisplay(6)

        End If
 

        For i As Integer = 0 To 5

            calcRect = basicRect

            XOffset = CType((HMargin + (Spacing * (i + 2 + (i / 2))) + (i * DigitWidth) + ((i / 2) * ColonWidth)), Integer)

            calcRect.Offset(XOffset, YOffset)

            If (DigitDisplay(i) Is Nothing) Then

                DigitDisplay(i) = New SriClocks.DigitalDisplay(calcRect)

            Else

                DigitDisplay(i).CalculateAllParameters(calcRect)

            End If

        Next
 

        If (ColonDisplay Is Nothing) Then

            ReDim ColonDisplay(2)

        End If
 

        ' for first colon

        calcRect = basicRect

        calcRect.Width = CType(ColonWidth, Integer)

        XOffset = CType((HMargin + 3 * Spacing + 2 * DigitWidth), Integer)

        calcRect.Offset(XOffset, YOffset)

        If (ColonDisplay(0) Is Nothing) Then

            ColonDisplay(0) = New SriClocks.DigitalDisplay(calcRect)

        Else

            ColonDisplay(0).CalculateAllParameters(calcRect)

        End If
 

        ' for second colon

        calcRect = basicRect

        calcRect.Width = CType(ColonWidth, Integer)

        XOffset = CType(((6 * Spacing) + (4 * DigitWidth) + ColonWidth + HMargin), Integer)

        calcRect.Offset(XOffset, YOffset)

        If (ColonDisplay(1) Is Nothing) Then

            ColonDisplay(1) = New SriClocks.DigitalDisplay(calcRect)

        Else

            ColonDisplay(1).CalculateAllParameters(calcRect)

        End If
 

        ' for displaying 'A'(AM) or 'P' (PM)

        calcRect = basicRect

        calcRect.Width = CType(ColonWidth, Integer)

        calcRect.Height = calcRect.Height / 2

        XOffset = CType(((10 * Spacing) + (6 * DigitWidth) + (2 * ColonWidth) + HMargin), Integer)

        calcRect.Offset(XOffset, CType((YOffset + DigitHeight / 2.0 + 1), Integer))

        If (AmPmDisplay Is Nothing) Then

            AmPmDisplay = New SriClocks.DigitalDisplay(calcRect)

        Else

            AmPmDisplay.CalculateAllParameters(calcRect)

        End If
 

        ' for displaying 1/10 of a second

        ' reuse AM/PM display panel rectangle

        ' only change Y coordinate, shift upwards

        calcRect.Y = YOffset - 1 ' just to keep it apart from AM/PM display

        If (MicroSecDisplay Is Nothing) Then

            MicroSecDisplay = New SriClocks.DigitalDisplay(calcRect)

        Else

            MicroSecDisplay.CalculateAllParameters(calcRect)

        End If

    End Sub
 

    ' On resize of control recalculate the rectangles for display

    ' Also recreate the graphics so that the clipping region is updated

    Private Sub DigitalClock_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Resize

        SyncLock (Me)

            PreparePanels()

            MyGraphics.Dispose()

            MyGraphics = Graphics.FromHwnd(Me.Handle)

            MyGraphics.Clear(BackColor)

        End SyncLock

    End Sub
 

    Private Sub DigitalClock_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load

        MyGraphics = Graphics.FromHwnd(Me.Handle)

        PreparePanels()

        DisplayTime(9, 3, 0, 12)

    End Sub

Open in new window

0
 

Author Comment

by:tentavarious
ID: 21875461
Ok, I got it working by calling the DisplayTime procedure from your PreparePanels procedure, but when I run it, nothing happens I just get a blank form.  Right now I am using the form as the drawing area and I set the background to black, but after running through the code the form's back ground color gets set to control and it gets resized.  What am I forgetting to do?  I just wanna draw these values on my form 9,3,0,12?

DisplayTime(9, 3, 0, 12)
0
 
LVL 3

Expert Comment

by:GHCS_Mark
ID: 21875926
Zip up and attach the example code you have and I will see if I can update it to work.  It would be better than playing around with half guesses.
0
 

Author Comment

by:tentavarious
ID: 21876006
Its not allowing me to attach the file because of the .vb extenstion.  I will just attach a code snippet of the form I am using in which I am trying to draw.
Imports System

Imports System.Drawing

Imports System.Drawing.Drawing2D

<ToolboxBitmap("Digital.bmp")> _

Public Class Form2

    Inherits System.Windows.Forms.Form

    Public DigitDisplay As SriClocks.DigitalDisplay() = Nothing ' panels on which digits are displayed

    Public ColonDisplay As SriClocks.DigitalDisplay() = Nothing ' panels for displaying colons

    Public AmPmDisplay As SriClocks.DigitalDisplay = Nothing  ' panel for AM/PM display

    Public MicroSecDisplay As SriClocks.DigitalDisplay = Nothing ' panel for displaying 1/10 of a second

    Private MyGraphics As Graphics
 

    ' This function displays time in a static fashion

    

    Public Sub DisplayTime(ByVal hour As Integer, ByVal min As Integer, ByVal sec As Integer, ByVal ms As Integer)

        DisplayTime(Me.GetGraphics(), hour, min, sec, ms)

    End Sub
 

    Public Sub DisplayTime(ByVal g As Graphics, ByVal hour As Integer, ByVal min As Integer, ByVal sec As Integer, ByVal ms As Integer) 

        DigitDisplay(0).SetPenColor(SriClocks.DigitalColor.GreenColor)

        DigitDisplay(1).SetPenColor(SriClocks.DigitalColor.GreenColor)

        DigitDisplay(2).SetPenColor(SriClocks.DigitalColor.GreenColor)

        DigitDisplay(3).SetPenColor(SriClocks.DigitalColor.GreenColor)

        DigitDisplay(4).SetPenColor(SriClocks.DigitalColor.GreenColor)

        DigitDisplay(5).SetPenColor(SriClocks.DigitalColor.GreenColor)
 

        DigitDisplay(0).Draw(hour / 10, g)

        DigitDisplay(1).Draw(hour Mod 10, g)

        DigitDisplay(2).Draw(min / 10, g)

        DigitDisplay(3).Draw(min Mod 10, g)

        DigitDisplay(4).Draw(sec / 10, g)

        DigitDisplay(5).Draw(sec Mod 10, g)

        MicroSecDisplay.Draw(ms / 100, g)

    End Sub
 

    Public ReadOnly Property GetGraphics() As Graphics

        Get

            Return MyGraphics

        End Get

    End Property
 

    ' function to prepare the digital clock panels by dividing the rectangle

    ' It is assumed that the height of each digit is double that of it's width

    ' Spacing betweent the digits is 10% of the width

    ' The colon characters occupy 50% of width of the digits

    Private Sub PreparePanels()

        ' from the above assumptions for height and width

        ' the height should be 2.4 units and width 8.8 units :-)

        ' check height and width whichever is dominant and adjust the other

        ' and set up margins

        Dim rect As Rectangle = New Rectangle(0, 0, Me.Width, Me.Height)
 

        ' widths, spacings and margins

        ' height of colon display is same as a digit

        Dim DigitWidth, DigitHeight, ColonWidth, Spacing As Integer

        Dim HMargin As Double = 0 ' left and right margin

        Dim VMargin As Double = 0 ' top and bottom margin
 

        ' Calculate a digit width (which is our unit) from the above metrics

        ' and settle for the least value

        Dim WidthUnit As Integer = CType(rect.Width / 8.8F, Integer)

        Dim HeightUnit As Integer = CType((rect.Height / 2.4F), Integer)

        DigitWidth = IIf(WidthUnit < HeightUnit, WidthUnit, HeightUnit)
 

        DigitHeight = 2 * DigitWidth ' height is twice of width

        ColonWidth = DigitWidth / 2 'colon width is half of a digit

        Spacing = DigitWidth / 10

        If (Spacing < 1) Then Spacing = 1 ' atleast a spacing of 1 is required

        HMargin = (rect.Width - (8.8F * DigitWidth)) / 2

        VMargin = (rect.Height - DigitHeight) / 2
 

        ' This is the basic rectangle, offset it as required

        Dim basicRect As Rectangle = New Rectangle(0, 0, CType(DigitWidth, Integer), CType(DigitHeight, Integer))

        Dim XOffset, YOffset As Integer

        Dim calcRect As Rectangle   ' calculated rectangle for a panel

        ' Y offset is same for all elements, expcept 1/10 second and AM/PM display

        YOffset = CType(VMargin, Integer)
 

        ' create digit panels.  6 digits

        If (DigitDisplay Is Nothing) Then

            ReDim DigitDisplay(6)

        End If
 

        For i As Integer = 0 To 5

            calcRect = basicRect

            XOffset = CType((HMargin + (Spacing * (i + 2 + (i / 2))) + (i * DigitWidth) + ((i / 2) * ColonWidth)), Integer)

            calcRect.Offset(XOffset, YOffset)

            If (DigitDisplay(i) Is Nothing) Then

                DigitDisplay(i) = New SriClocks.DigitalDisplay(calcRect)

            Else

                DigitDisplay(i).CalculateAllParameters(calcRect)

            End If

        Next
 

        If (ColonDisplay Is Nothing) Then

            ReDim ColonDisplay(2)

        End If
 

        ' for first colon

        calcRect = basicRect

        calcRect.Width = CType(ColonWidth, Integer)

        XOffset = CType((HMargin + 3 * Spacing + 2 * DigitWidth), Integer)

        calcRect.Offset(XOffset, YOffset)

        If (ColonDisplay(0) Is Nothing) Then

            ColonDisplay(0) = New SriClocks.DigitalDisplay(calcRect)

        Else

            ColonDisplay(0).CalculateAllParameters(calcRect)

        End If
 

        ' for second colon

        calcRect = basicRect

        calcRect.Width = CType(ColonWidth, Integer)

        XOffset = CType(((6 * Spacing) + (4 * DigitWidth) + ColonWidth + HMargin), Integer)

        calcRect.Offset(XOffset, YOffset)

        If (ColonDisplay(1) Is Nothing) Then

            ColonDisplay(1) = New SriClocks.DigitalDisplay(calcRect)

        Else

            ColonDisplay(1).CalculateAllParameters(calcRect)

        End If
 

        ' for displaying 'A'(AM) or 'P' (PM)

        calcRect = basicRect

        calcRect.Width = CType(ColonWidth, Integer)

        calcRect.Height = calcRect.Height / 2

        XOffset = CType(((10 * Spacing) + (6 * DigitWidth) + (2 * ColonWidth) + HMargin), Integer)

        calcRect.Offset(XOffset, CType((YOffset + DigitHeight / 2.0 + 1), Integer))

        If (AmPmDisplay Is Nothing) Then

            AmPmDisplay = New SriClocks.DigitalDisplay(calcRect)

        Else

            AmPmDisplay.CalculateAllParameters(calcRect)

        End If
 

        ' for displaying 1/10 of a second

        ' reuse AM/PM display panel rectangle

        ' only change Y coordinate, shift upwards

        calcRect.Y = YOffset - 1 ' just to keep it apart from AM/PM display

        If (MicroSecDisplay Is Nothing) Then

            MicroSecDisplay = New SriClocks.DigitalDisplay(calcRect)

        Else

            MicroSecDisplay.CalculateAllParameters(calcRect)

        End If

        DisplayTime(Now.Hour, Now.Minute, Now.Second, 2)

    End Sub
 

    ' On resize of control recalculate the rectangles for display

    ' Also recreate the graphics so that the clipping region is updated

    Private Sub DigitalClock_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Resize

        SyncLock (Me)

            PreparePanels()

            MyGraphics.Dispose()

            MyGraphics = Graphics.FromHwnd(Me.Handle)

            MyGraphics.Clear(BackColor)

        End SyncLock

    End Sub
 

    Private Sub InitializeComponent()

        '

        'Form2

        '

        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)

        Me.BackColor = System.Drawing.Color.Black

        Me.ClientSize = New System.Drawing.Size(376, 86)

        Me.ForeColor = System.Drawing.Color.Black

        Me.Name = "Form2"

        Me.Text = "Takt_Time"
 

    End Sub
 

    Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        MyGraphics = Graphics.FromHwnd(Me.Handle)

        PreparePanels()

    End Sub

End Class

Open in new window

0
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 3

Expert Comment

by:GHCS_Mark
ID: 21876213
Try zipping up the folder containing the project, not just the one VB file, so that all the classes are available.  It could be a minor issue elsewhere that is causing it but its far easier to work out if I can step through it.  The coding 'appears' fine when I am glancing at it.
0
 

Author Comment

by:tentavarious
ID: 21876285
I zipped the entire folder, but it still didnt like it.  Let me see if I can try again
0
 

Author Comment

by:tentavarious
ID: 21876296
Yep I get this message: The extension of one or more files in the archive is not in the list of allowed extensions: Takt_Time/AssemblyInfo.vb
0
 

Author Comment

by:tentavarious
ID: 21876433
This is not working, it doesnt like a lot of the file exstensions.  The uploader must loop through all files and check extensions in a zipped folder.  Can't you just make a new project and use the code from the DigitalDisplay class, to create a new class plus my form2 code to make a new form?  I have already included the bitmap file and that is pretty much everything I have.  The uploader doesn't like vb,exe,resx or sln file extensions.  
0
 

Author Comment

by:tentavarious
ID: 21883429
Any luck?  Basically what I want to do is get rid of the user control and just use it directly with Form2, I wouldn't think it would be that hard.
0
 

Author Comment

by:tentavarious
ID: 21883697
Ok, something is wrong with this part, when I added this line <ToolboxBitmap("Digital.bmp")> _ my forms properties dont work, they default back to its normal settings.  So what is going on when I add that line.

<ToolboxBitmap("Digital.bmp")> _
Class Form2
end Class
0
 

Author Comment

by:tentavarious
ID: 21884199
Ok, nevermind my last comments, I got the draw to work, but for some reason it only draws 8's and it doesnt look right.  I have attached my form code and the drawing class also a bitmap if what is going on
'Form Code

Imports System

Imports System.Drawing

Imports System.Drawing.Drawing2D

<ToolboxBitmap("Digital.bmp")> _

Public Class test

    Inherits System.Windows.Forms.Form
 

#Region " Windows Form Designer generated code "
 

    Public Sub New()

        MyBase.New()
 

        'This call is required by the Windows Form Designer.

        InitializeComponent()
 

        'Add any initialization after the InitializeComponent() call
 

    End Sub
 

    'Form overrides dispose to clean up the component list.

    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)

        If disposing Then

            If Not (components Is Nothing) Then

                components.Dispose()

            End If

        End If

        MyBase.Dispose(disposing)

    End Sub
 

    'Required by the Windows Form Designer

    Private components As System.ComponentModel.IContainer
 

    'NOTE: The following procedure is required by the Windows Form Designer

    'It can be modified using the Windows Form Designer.  

    'Do not modify it using the code editor.

    Friend WithEvents Button1 As System.Windows.Forms.Button

    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()

        Me.Button1 = New System.Windows.Forms.Button

        Me.SuspendLayout()

        '

        'Button1

        '

        Me.Button1.BackColor = System.Drawing.SystemColors.Control

        Me.Button1.Location = New System.Drawing.Point(288, 40)

        Me.Button1.Name = "Button1"

        Me.Button1.TabIndex = 1

        Me.Button1.Text = "Button1"

        '

        'test

        '

        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)

        Me.BackColor = System.Drawing.SystemColors.ControlText

        Me.ClientSize = New System.Drawing.Size(384, 94)

        Me.Controls.Add(Me.Button1)

        Me.Name = "test"

        Me.Text = "test"

        Me.ResumeLayout(False)
 

    End Sub
 

#End Region

    Public DigitDisplay As SriClocks.DigitalDisplay() = Nothing ' panels on which digits are displayed

    Public ColonDisplay As SriClocks.DigitalDisplay() = Nothing ' panels for displaying colons

    Public AmPmDisplay As SriClocks.DigitalDisplay = Nothing  ' panel for AM/PM display

    Public MicroSecDisplay As SriClocks.DigitalDisplay = Nothing ' panel for displaying 1/10 of a second

    Private MyGraphics As Graphics

    Public clockval As SriClocks.colonType = SriClocks.colonType.Circular

    Private Sub test_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        GetGraphics = Graphics.FromHwnd(Me.Handle)

        PreparePanels()

    End Sub

    Public Sub DisplayTime(ByVal hour As Integer, ByVal min As Integer, ByVal sec As Integer, ByVal ms As Integer)

        DisplayTime(Me.GetGraphics(), hour, min, sec, ms)

    End Sub

    Public Sub DisplayTime(ByVal g As Graphics, ByVal hour As Integer, ByVal min As Integer, ByVal sec As Integer, ByVal ms As Integer)

        DigitDisplay(0).SetPenColor(SriClocks.DigitalColor.GreenColor)

        DigitDisplay(1).SetPenColor(SriClocks.DigitalColor.GreenColor)

        DigitDisplay(2).SetPenColor(SriClocks.DigitalColor.GreenColor)

        DigitDisplay(3).SetPenColor(SriClocks.DigitalColor.GreenColor)

        DigitDisplay(4).SetPenColor(SriClocks.DigitalColor.GreenColor)

        DigitDisplay(5).SetPenColor(SriClocks.DigitalColor.GreenColor)
 

        DigitDisplay(0).Draw(hour / 10, g)

        DigitDisplay(1).Draw(hour Mod 10, g)

        DigitDisplay(2).Draw(min / 10, g)

        DigitDisplay(3).Draw(min Mod 10, g)

        DigitDisplay(4).Draw(sec / 10, g)

        DigitDisplay(5).Draw(sec Mod 10, g)

        MicroSecDisplay.Draw(ms / 100, g)

    End Sub

    Public Property GetGraphics() As Graphics

        Get

            Return MyGraphics

        End Get

        Set(ByVal Value As Graphics)

            MyGraphics = Value

        End Set

    End Property

    Private Sub PreparePanels()

        ' from the above assumptions for height and width

        ' the height should be 2.4 units and width 8.8 units :-)

        ' check height and width whichever is dominant and adjust the other

        ' and set up margins

        Dim rect As Rectangle = New Rectangle(0, 0, Me.Width, Me.Height)
 

        ' widths, spacings and margins

        ' height of colon display is same as a digit

        Dim DigitWidth, DigitHeight, ColonWidth, Spacing As Integer

        Dim HMargin As Double = 0 ' left and right margin

        Dim VMargin As Double = 0 ' top and bottom margin
 

        ' Calculate a digit width (which is our unit) from the above metrics

        ' and settle for the least value

        Dim WidthUnit As Integer = CType(rect.Width / 8.8F, Integer)

        Dim HeightUnit As Integer = CType((rect.Height / 2.4F), Integer)

        DigitWidth = IIf(WidthUnit < HeightUnit, WidthUnit, HeightUnit)
 

        DigitHeight = 2 * DigitWidth ' height is twice of width

        ColonWidth = DigitWidth / 2 'colon width is half of a digit

        Spacing = DigitWidth / 10

        If (Spacing < 1) Then Spacing = 1 ' atleast a spacing of 1 is required

        HMargin = (rect.Width - (8.8F * DigitWidth)) / 2

        VMargin = (rect.Height - DigitHeight) / 2
 

        ' This is the basic rectangle, offset it as required

        Dim basicRect As Rectangle = New Rectangle(0, 0, CType(DigitWidth, Integer), CType(DigitHeight, Integer))

        Dim XOffset, YOffset As Integer

        Dim calcRect As Rectangle   ' calculated rectangle for a panel

        ' Y offset is same for all elements, expcept 1/10 second and AM/PM display

        YOffset = CType(VMargin, Integer)
 

        ' create digit panels.  6 digits

        If (DigitDisplay Is Nothing) Then

            ReDim DigitDisplay(6)

        End If
 

        For i As Integer = 0 To 5

            calcRect = basicRect

            XOffset = CType((HMargin + (Spacing * (i + 2 + (i / 2))) + (i * DigitWidth) + ((i / 2) * ColonWidth)), Integer)

            calcRect.Offset(XOffset, YOffset)

            If (DigitDisplay(i) Is Nothing) Then

                DigitDisplay(i) = New SriClocks.DigitalDisplay(calcRect)

            Else

                DigitDisplay(i).CalculateAllParameters(calcRect)

            End If

        Next
 

        If (ColonDisplay Is Nothing) Then

            ReDim ColonDisplay(2)

        End If
 

        ' for first colon

        calcRect = basicRect

        calcRect.Width = CType(ColonWidth, Integer)

        XOffset = CType((HMargin + 3 * Spacing + 2 * DigitWidth), Integer)

        calcRect.Offset(XOffset, YOffset)

        If (ColonDisplay(0) Is Nothing) Then

            ColonDisplay(0) = New SriClocks.DigitalDisplay(calcRect)

        Else

            ColonDisplay(0).CalculateAllParameters(calcRect)

        End If
 

        ' for second colon

        calcRect = basicRect

        calcRect.Width = CType(ColonWidth, Integer)

        XOffset = CType(((6 * Spacing) + (4 * DigitWidth) + ColonWidth + HMargin), Integer)

        calcRect.Offset(XOffset, YOffset)

        If (ColonDisplay(1) Is Nothing) Then

            ColonDisplay(1) = New SriClocks.DigitalDisplay(calcRect)

        Else

            ColonDisplay(1).CalculateAllParameters(calcRect)

        End If
 

        ' for displaying 'A'(AM) or 'P' (PM)

        calcRect = basicRect

        calcRect.Width = CType(ColonWidth, Integer)

        calcRect.Height = calcRect.Height / 2

        XOffset = CType(((10 * Spacing) + (6 * DigitWidth) + (2 * ColonWidth) + HMargin), Integer)

        calcRect.Offset(XOffset, CType((YOffset + DigitHeight / 2.0 + 1), Integer))

        If (AmPmDisplay Is Nothing) Then

            AmPmDisplay = New SriClocks.DigitalDisplay(calcRect)

        Else

            AmPmDisplay.CalculateAllParameters(calcRect)

        End If
 

        ' for displaying 1/10 of a second

        ' reuse AM/PM display panel rectangle

        ' only change Y coordinate, shift upwards

        calcRect.Y = YOffset - 1 ' just to keep it apart from AM/PM display

        If (MicroSecDisplay Is Nothing) Then

            MicroSecDisplay = New SriClocks.DigitalDisplay(calcRect)

        Else

            MicroSecDisplay.CalculateAllParameters(calcRect)

        End If

        DisplayTime(Now.Hour, Now.Minute, Now.Second, 1)

    End Sub
 

    Private Sub test_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Resize

        SyncLock (Me)

            GetGraphics = Graphics.FromHwnd(Me.Handle)

            PreparePanels()

            GetGraphics.Dispose()

            MyGraphics = Graphics.FromHwnd(Me.Handle)

            MyGraphics.Clear(Color.Black)

        End SyncLock

    End Sub
 

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        GetGraphics = Graphics.FromHwnd(Me.Handle)

        PreparePanels()

    End Sub

End Class
 
 

''The Class that handles all of the drawing

Imports System

Imports System.Drawing

Imports System.Drawing.Drawing2D
 

Namespace SriClocks

    ' A digit class which can draw a number on a graphics surface

    Public Enum DigitalColor

        RedColor

        GreenColor

        BlueColor

    End Enum
 

    Public Enum colonType

        Circular

        Rectangular

    End Enum
 

    Public Class DigitalDisplay

        ' pens used to draw the digits

        Shared pen As pen = New pen(Color.FromArgb(255, 0, 0))

        Shared dimPen As pen = Nothing
 

        Private linewidth As Double = 20.0F
 

        Private Points As Point() ' end point coordinates of lines in the digital display
 

        ' for each digit the display bits are set into an int

        ' 'A' and 'P' are included for AM and PM display in the clock

        Private displayNum As Integer() = {63, 12, 118, 94, 77, 91, 123, 14, 127, 95, 111, 103}
 

        ' Rectangles in which colons are displayed

        Private colonRect1, colonRect2 As Rectangle
 

        ' This function is called by the paint method to display the numbers

        ' A set of bits in the 'displayNum' variable define which of the

        ' display legs to display

        ' Based on this the ones with a '1' are in bright color and the rest

        ' with '0's are in a dull color giving the effect of a digital clock

        Protected Friend Sub Draw(ByVal num As Integer, ByVal g As Graphics)

            Dim check As Integer ' used to check if a leg of digit should be bright or dull
 

            ' although pens are global linewidths are specific to each instance

            pen.Width = dimPen.Width = linewidth
 

            For i As Integer = 0 To 6

                check = CType(System.Math.Pow(2, i), Integer)

                If ((check & displayNum(num)) = 0) Then

                    g.DrawLine(dimPen, Points(i * 2), Points(i * 2 + 1))

                Else

                    g.DrawLine(pen, Points(i * 2), Points(i * 2 + 1))

                End If

            Next
 

        End Sub
 

        Private Shared Sub setDimPen()

            If (dimPen Is Nothing) Then dimPen = CType(pen.Clone(), Pen)

            dimPen.Width = pen.Width

            dimPen.Color = Color.FromArgb( _

             IIf(pen.Color.R > 0, 60, 0), _

             IIf(pen.Color.G > 0, 60, 0), _

             IIf(pen.Color.B > 0, 60, 0))

        End Sub
 

        Public Shared Sub SetPenColor(ByVal dclr As DigitalColor)

            pen.Color = Color.FromArgb( _

             IIf(dclr = DigitalColor.RedColor, 255, 0), _

             IIf(dclr = DigitalColor.GreenColor, 255, 0), _

             IIf(dclr = DigitalColor.BlueColor, 255, 0))

            setDimPen()

        End Sub
 

        ' function that draws a colon in the middle of the rectangular panel

        ' possible modes are circular or rectangular points in the colon

        Private Sub DrawColon(ByVal g As Graphics, ByVal type As colonType, ByVal bDim As Boolean)

            pen.Width = dimPen.Width = linewidth

            Dim p As Pen = IIf(bDim, dimPen, pen) ' choose a pen for blinking

            Select Case type

                Case colonType.Circular

                    g.DrawEllipse(p, colonRect1)

                    g.DrawEllipse(p, colonRect2)

                Case colonType.Rectangular

                    g.DrawRectangle(p, colonRect1)

                    g.DrawRectangle(p, colonRect2)

            End Select

        End Sub
 

        ' Draws the complete rectangle in dim shade to give the digital effect :-)

        Protected Friend Sub Draw(ByVal g As Graphics)

            ' althought pens are static, linewidths are specific to each instance

            dimPen.Width = linewidth

            For i As Integer = 0 To 6

                g.DrawLine(dimPen, Points(i * 2), Points(i * 2 + 1))

            Next

        End Sub
 

        ' Overloaded function to display characters 'A' and 'P' for AM and PM

        ' Using the same algorithm used to display numbers above

        Protected Friend Sub Draw(ByVal ch As Char, ByVal g As Graphics)

            ' 10 and 11 are indices of A and P in the displayNum array

            Select Case Char.ToUpper(ch)

                Case "A"

                    Draw(10, g)

                Case "P"

                    Draw(11, g)

            End Select

        End Sub
 

        ' Constructor takes a rectangle and prepares the end points

        ' of the lines to be drawn for the clock

        Public Sub New(ByVal rect As Rectangle)

            pen.StartCap = LineCap.Triangle

            pen.EndCap = LineCap.Triangle
 

            ReDim Points(14) ' there are 7 lines in a display

            For i As Integer = 0 To 13

                Points(i) = New Point(0, 0)

            Next

            CalculateAllParameters(rect)

        End Sub
 

        Sub CalculateAllParameters(ByVal rect As Rectangle)

            linewidth = CType((rect.Width / 5), Integer)

            If (linewidth < 2) Then linewidth = 2

            If (linewidth > 20) Then linewidth = 20
 

            pen.Width = linewidth

            setDimPen()
 

            CalculateLineEnds(rect)

            CalculateColonRectangles(rect)

        End Sub
 

        ' Function calculates end points of lines to display

        ' The draw function will draw lines using this data

        Private Sub CalculateLineEnds(ByVal rect As Rectangle)

            ' 0,1,2,9,10,11,12 points share the same left edge X coordinate

            Points(0).X = rect.Left

            Points(1).X = Points(0).X

            Points(2).X = Points(0).X

            Points(9).X = Points(0).X

            Points(10).X = Points(0).X

            Points(11).X = Points(0).X

            Points(12).X = Points(0).X
 

            ' points 3,4,5,6,7,8,13 the right edge X coordinate

            Points(3).X = rect.Right - CType(linewidth, Integer)

            Points(4).X = Points(3).X

            Points(5).X = Points(3).X

            Points(6).X = Points(3).X

            Points(7).X = Points(3).X

            Points(8).X = Points(3).X

            Points(13).X = Points(3).X
 

            ' Points 1,2,3,4 are the top most points

            Points(1).Y = CType(rect.Top, Integer)

            Points(2).Y = Points(1).Y

            Points(3).Y = Points(1).Y

            Points(4).Y = Points(1).Y
 

            ' Points 0,11,12,13,5,6 are the middle points

            Points(0).Y = rect.Top + CType(((rect.Height - linewidth) / 2.0), Integer)

            Points(11).Y = Points(0).Y

            Points(12).Y = Points(0).Y

            Points(13).Y = Points(0).Y

            Points(5).Y = Points(0).Y

            Points(6).Y = Points(0).Y
 

            ' points 7,8,9,10 are on the bottom edge

            Points(7).Y = rect.Top + CType((rect.Height - linewidth), Integer)

            Points(8).Y = Points(7).Y

            Points(9).Y = Points(7).Y

            Points(10).Y = Points(7).Y
 

            ' now adjust the coordinates that were computed, to get the digital look

            AdjustCoordinates()

        End Sub
 

        ' This function is necessary to give the lines a digital clock look

        ' Push the coordinates a little away so that they look apart

        Private Sub AdjustCoordinates()

            Dim swap As Point  ' required in case points have to be swapped

            For i As Integer = 0 To 6

                ' Always draw from left to right and top to bottom

                ' Adjust the end points accordingly

                If (Points(i * 2).X > Points((i * 2) + 1).X Or Points(i * 2).Y > Points((i * 2) + 1).Y) Then

                    swap = Points(i * 2)

                    Points(i * 2) = Points((i * 2) + 1)

                    Points((i * 2) + 1) = swap

                End If
 

                ' for horizontal lines adjust the X coord

                If (Points(i * 2).X <> Points((i * 2) + 1).X) Then

                    Points(i * 2).X += CType((linewidth / 1.6), Integer)

                    Points((i * 2) + 1).X -= CType((linewidth / 1.6), Integer)

                End If

                ' for vertical lines adjust the y coord

                If (Points(i * 2).Y <> Points((i * 2) + 1).Y) Then

                    Points(i * 2).Y += CType((linewidth / 1.6), Integer)

                    Points((i * 2) + 1).Y -= CType((linewidth / 1.6), Integer)

                End If

            Next

        End Sub
 

        ' function to calculate the rectangles required to drawn colon dot inside

        Private Sub CalculateColonRectangles(ByVal rect As Rectangle)

            colonRect2 = rect

            colonRect1 = rect

            colonRect1.X = colonRect2.X = rect.X + CType(((rect.Width - linewidth) / 2.0), Integer)

            colonRect1.Y = rect.Y + rect.Height / 3

            colonRect2.Y = rect.Y + (rect.Height * 2) / 3

            colonRect1.Width = CType(linewidth, Integer)

            colonRect1.Height = CType(linewidth, Integer)

            colonRect2.Width = CType(linewidth, Integer)

            colonRect2.Height = CType(linewidth, Integer)

        End Sub

    End Class
 

End Namespace

Open in new window

test-Draw.gif
0
 

Author Comment

by:tentavarious
ID: 21885531
ok, I am getting most of this figured out, the characters have the right size and thickness but I am still showing all 8's
test-Draw.gif
0
 
LVL 3

Expert Comment

by:GHCS_Mark
ID: 21894613
Apologies, I've been in the middle of a crucial Firewall switch and it's taken a lot of time and effort to get it right :-)

I'll take a look at this tomorrow, hopefully. Good to see you've managed to make progress!
0
 

Author Comment

by:tentavarious
ID: 21910799
Ok, I got the user control to work with my app, but now I need help with the stop watch feature.  The demo app can be downloaded from this site:http://www.codeproject.com/KB/selection/DigitalClockControl.aspx.   The problem I am having with the stop watch feature is that I want to start it a specified timed, right now if I click the stop watch it automatically resets to all 0's.  I need to have it start, then if I switch to something else and switch back it will start back where it left off.
0
 
LVL 3

Expert Comment

by:GHCS_Mark
ID: 21915977
Which code are you using now, the demo or a modified version of it. or the control we had above?
0
 

Author Comment

by:tentavarious
ID: 21916124
I am using, the demo's usercontrol and trying to modified.
0
 
LVL 3

Accepted Solution

by:
GHCS_Mark earned 500 total points
ID: 21917150
OK, in the demo project is has SetClockType() in DigitalClockCtrl.cs and when it sets the type to StopWatch it has a line that reads:

stopwatchBegin = DateTime.Now

What you will need to do, is when you want to freeze the clock, find the difference as a TimeSpan between stopwatchBegin and DateTime.Now.  Then, when you come to "unfreeze" the time, you simply subtract the TimeSpan from the current DateTime.Now value as you are setting it.

You will need to differentiate between starting the start watch and stop it. So therefore, maybe have function as so (untested so may need fixing up):

void StartStopWatch()
{
    stopwatchBegin = DateTime.Now;
    clockType = ClockType.StopWatch;
}

void ContinueStopWatch(ts Timespan)
{
    stopwatchBegin = (DateTime.Now - ts)
}
0
 

Author Closing Comment

by:tentavarious
ID: 31470561
Thank you, I modified the code a little to get the same results.  Works great now thanks again.
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Recently while returning home from work my wife (another .NET developer) was murmuring something. On further poking she said that she has been assigned a task where she has to serialize and deserialize objects and she is afraid of serialization. Wha…
It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now