Alarm Clock

Alarm Clock uses a Silverlight User Control to create an Analogue Clock which displays the Time and Alarm setting to create a simple Alarm Clock.

www.cespage.com/silverlight/sl4tut18.html

Step 1

Start Microsoft Visual Web Developer 2010 Express, then Select File then New Project... Select "Visual Basic" then "Silverlight Application" from Templates, select a Location if you wish, then enter a name for the Project and then click OK, see below:

New Project

Step 2

New Silverlight Application window should appear, uncheck the box "Host the Silverlight Application in a new Web site" and then select the required Silverlight Version, see below:

New Silverlight Application

Step 3

A Blank Page named MainPage.xaml should then appear, see below:

MainPage.xaml

Step 4

Select Project then "Add New Item...", and select the "Silverlight User Control" Template if not already Selected, then change the "Name" to Clock.xaml, see below:

Clock User Control

Step 5

Add the new User Control to the Project by Clicking on Add, then in the XAML Pane for the Clock.xaml User Control,
for the "<UserControl>" Tag change the DesignHeight and DesignWidth Attributes to "250", see below:

Clock UserControl Attributes

Step 6

Return to the Clock Designer View by selecting the "Clock.xaml" Tab.
Then from the All Silverlight Controls section in the Toolbox select the Canvas control:

Canvas Control

Step 7

Draw a Canvas on the Page then in the XAML Pane above the "</Grid>" then change the "Canvas1" line to the following:

<Canvas Height="250" Width="250" Name="Display"/>

See below:

Clock User Control with Display Canvas

Step 8

Right Click on the Page or the entry for "Clock.xaml" in Solution Explorer and choose the "View Code" option. In the Code View below the "Inherits UserControl" line type the following Declarations:

Private ReadOnly COLOR_TOMATO As Color = Color.FromArgb(255, 255, 99, 71)
Private ReadOnly COLOR_GAINSBORO As Color = Color.FromArgb(255, 220, 220, 220)
Private ReadOnly COLOR_WHITESMOKE As Color = Color.FromArgb(255, 245, 245, 245)
Private ReadOnly COLOR_ROYALBLUE As Color = Color.FromArgb(255, 65, 105, 225)

Private WithEvents _timer As New Windows.Threading.DispatcherTimer
Private _time As DateTime = Now
Private _alarm As DateTime
Private _markers As New Canvas
Private _face As New Canvas
Private _secondsHand As Rectangle
Private _minutesHand As Rectangle
Private _hoursHand As Rectangle
Private _alarmMinutesHand As Rectangle
Private _alarmHoursHand As Rectangle
Private _diameter As Double
Private _secondsWidth As Integer = 1
Private _secondsHeight As Integer
Private _minutesWidth As Integer = 5
Private _minutesHeight As Integer
Private _hoursWidth As Integer = 8
Private _hoursHeight As Integer
Private _alarmMinutesWidth As Integer = 5
Private _alarmMinutesHeight As Integer
Private _alarmHoursWidth As Integer = 8
Private _alarmHoursHeight As Integer
Private _isEnabled As Boolean = True
Private _isRealTime As Boolean = True
Private _showSeconds As Boolean = True
Private _showMinutes As Boolean = True
Private _showHours As Boolean = True
Private _showAlarm As Boolean = True
Private _hasAlarm As Boolean = False
Private _faceColour As Color = COLOR_ROYALBLUE
Private _rimColour As Color = Colors.Blue
Private _markerColour As Color = Colors.White
Private _secondColour As Color = COLOR_TOMATO
Private _minuteColour As Color = COLOR_GAINSBORO
Private _hourColour As Color = COLOR_WHITESMOKE
Private _alarmColour As Color = Colors.Orange

Public Event Triggered()

See Below:

Clock User Control Class Declarations

Step 9

While still in the Code View for the Clock User Control, above the "Public Sub New()" for "Partial Public Class Clock", type the following Functions:

Private Function Hand(ByRef Width As Double, ByRef Height As Double, _
    ByRef Background As Brush, ByRef Foreground As Brush, _
    ByRef RadiusX As Double, ByRef RadiusY As Double, _
    ByRef Thickness As Double)
  Dim _hand As New Rectangle
  _hand.Width = Width
  _hand.Height = Height
  _hand.Fill = Background
  _hand.StrokeThickness = Thickness
  _hand.RadiusX = RadiusX
  _hand.RadiusY = RadiusY
  _hand.Stroke = Foreground
  Return _hand
End Function

Private Function TransformGroup(ByRef Angle As Double, _
    ByRef X As Double, ByRef Y As Double) As TransformGroup
  Dim _transformGroup As New TransformGroup
  Dim _firstTranslate As New TranslateTransform
  _firstTranslate.X = X
  _firstTranslate.Y = Y
  _transformGroup.Children.Add(_firstTranslate)
  Dim _rotateTransform As New RotateTransform
  _rotateTransform.Angle = Angle
  _transformGroup.Children.Add(_rotateTransform)
  Dim _secondTranslate As New TranslateTransform
  _secondTranslate.X = _diameter / 2
  _secondTranslate.Y = _diameter / 2
  _transformGroup.Children.Add(_secondTranslate)
  Return _transformGroup
End Function

See Below:

Clock User Control Functions

Step 10

While still in the Code View for the Clock User Control, above the "Public Sub New()" for "Partial Public Class Clock" and below the Functions, type the following Subs:

Private Sub SecondHand(ByVal Seconds As Integer)
  If _secondsHand IsNot Nothing AndAlso _face.Children.Contains(_secondsHand) Then
    _face.Children.Remove(_secondsHand)
  End If
  If _showSeconds Then
    _secondsHand = Hand(_secondsWidth, _secondsHeight,
      New SolidColorBrush(_secondColour), Nothing, 0, 0, 0)
    _secondsHand.RenderTransform = TransformGroup(Seconds * 6,
      -_secondsWidth / 2, -_secondsHeight + 4.25)
    If Not _face.Children.Contains(_secondsHand) Then
      _face.Children.Add(_secondsHand)
    End If
  End If
End Sub

Private Sub MinuteHand(ByVal Minutes As Integer, ByVal Seconds As Integer)
  If _minutesHand IsNot Nothing AndAlso _face.Children.Contains(_minutesHand) Then
    _face.Children.Remove(_minutesHand)
  End If
  If _showMinutes Then
    _minutesHand = Hand(_minutesWidth, _minutesHeight,
      New SolidColorBrush(_minuteColour), Nothing, 2, 2, 0.6)
    _minutesHand.RenderTransform = TransformGroup(6 * Minutes + Seconds / 10,
      -_minutesWidth / 2, -_minutesHeight + 4.25)
  End If
  If _face.Children.Contains(_minutesHand) = False Then
    _face.Children.Add(_minutesHand)
  End If
End Sub

Private Sub HourHand(ByVal Hours As Integer, ByVal Minutes As Integer, ByVal Seconds As Integer)
  If _hoursHand IsNot Nothing AndAlso _face.Children.Contains(_hoursHand) Then
    _face.Children.Remove(_hoursHand)
  End If
  If _showHours Then
    _hoursHand = Hand(_hoursWidth, _hoursHeight,
      New SolidColorBrush(_hourColour), Nothing, 3, 3, 0.6)
    _hoursHand.RenderTransform = TransformGroup(30 * Hours + Minutes / 2 + Seconds / 120,
      -_hoursWidth / 2, -_hoursHeight + 4.25)
  End If
  If _face.Children.Contains(_hoursHand) = False Then
    _face.Children.Add(_hoursHand)
  End If
End Sub

Private Sub AlarmMinuteHand(ByVal Minutes As Integer, ByVal Seconds As Integer)
  If _alarmMinutesHand IsNot Nothing AndAlso _face.Children.Contains(_alarmMinutesHand) Then
    _face.Children.Remove(_alarmMinutesHand)
  End If
  If _hasAlarm Then
    If _showAlarm Then
      _alarmMinutesHand = Hand(_alarmMinutesWidth, _alarmMinutesHeight,
        New SolidColorBrush(_alarmColour), Nothing, 2, 2, 0.6)
      _alarmMinutesHand.RenderTransform = TransformGroup(6 * Minutes + Seconds / 10,
        -_alarmMinutesWidth / 2, -_alarmMinutesHeight + 4.25)
    End If
    If _face.Children.Contains(_alarmMinutesHand) = False Then
      _face.Children.Add(_alarmMinutesHand)
    End If
  End If
End Sub

Private Sub AlarmHourHand(ByVal Hours As Integer, ByVal Minutes As Integer, ByVal Seconds As Integer)
  If _alarmHoursHand IsNot Nothing AndAlso _face.Children.Contains(_alarmHoursHand) Then
    _face.Children.Remove(_alarmHoursHand)
  End If
  If _hasAlarm Then
    If _showAlarm Then
      _alarmHoursHand = Hand(_alarmHoursWidth, _alarmHoursHeight,
        New SolidColorBrush(_alarmColour), Nothing, 3, 3, 0.6)
      _alarmHoursHand.RenderTransform = TransformGroup(30 * Hours + Minutes / 2 + Seconds / 120,
        -_alarmHoursWidth / 2, -_alarmHoursHeight + 4.25)
    End If
    If _face.Children.Contains(_alarmHoursHand) = False Then
      _face.Children.Add(_alarmHoursHand)
    End If
  End If
End Sub

Private Sub Layout(ByRef Canvas As Canvas)
  Dim _rim As New Ellipse
  Dim _inner As New Ellipse
  Canvas.Children.Clear()
  _diameter = Canvas.Width
  _rim.Height = _diameter
  _rim.Width = _diameter
  _rim.Fill = New SolidColorBrush(_rimColour)
  Canvas.Children.Add(_rim)
  _inner.Width = _diameter - 30
  _inner.Height = _diameter - 30
  _inner.Fill = New SolidColorBrush(_faceColour)
  Canvas.SetTop(_inner, 15)
  Canvas.SetLeft(_inner, 15)
  Canvas.Children.Add(_inner)
  _markers.Children.Clear()
  _markers.Width = _diameter
  _markers.Height = _diameter
  For i As Integer = 0 To 59
    Dim _marker As New Rectangle
    If i Mod 5 = 0 Then
      _marker.Width = 3
      _marker.Height = 8
      _marker.Fill = New SolidColorBrush(_markerColour)
      _marker.RenderTransform = TransformGroup(i * 6, -(_marker.Width / 2),
        -(_marker.Height * 2 + 4.5 - _rim.StrokeThickness / 2 - _diameter / 2 - 8))
    Else
      _marker.Width = 1
      _marker.Height = 4
      _marker.Fill = New SolidColorBrush(_markerColour)
      _marker.RenderTransform = TransformGroup(i * 6, -(_marker.Width / 2),
        -(_marker.Height * 2 + 12.75 - _rim.StrokeThickness / 2 - _diameter / 2 - 8))
    End If
    _markers.Children.Add(_marker)
  Next
  Canvas.Children.Add(_markers)
  _face.Width = _diameter
  _face.Height = _diameter
  Canvas.Children.Add(_face)
  _secondsHeight = _diameter / 2 - 20
  _minutesHeight = _diameter / 2 - 40
  _hoursHeight = _diameter / 2 - 60
  _alarmMinutesHeight = _diameter / 2 - 25
  _alarmHoursHeight = _diameter / 2 - 50
End Sub

Private Sub Timer_Tick(ByVal sender As Object, _
    ByVal e As EventArgs) _
    Handles _timer.Tick
  If _isRealTime Then _time = Now()
  If _hasAlarm Then
    If Format(_time, "hh:mm:ss") = _
        Format(_alarm, "hh:mm") & ":00" Then
      RaiseEvent Triggered()
    End If
  End If
  AlarmMinuteHand(_alarm.Minute, _alarm.Second)
  AlarmHourHand(_alarm.Hour, _alarm.Minute, _alarm.Second)
  SecondHand(_time.Second)
  MinuteHand(_time.Minute, _time.Second)
  HourHand(_time.Hour, _time.Minute, _time.Second)
End Sub

See Below:

Clock User Control Subs

Step 11

Still In the Code View for the Clock User Control in the "Public Sub New()" Constructor below the "InitializeComponent()" line type the following:

Layout(Display)
_timer.Start()

See Below:

Clock User Control Constructor

Step 12

While still in the Code View for the Clock User Control, above the "End Class" for "Partial Public Class Clock", type the following Properties:

Public Property FaceColour() As Color
  Get		 
    Return _faceColour
  End Get
  Set(ByVal Value As Color)
    If Value = Nothing Then
      _faceColour = COLOR_ROYALBLUE
    Else
      _faceColour = Value
    End If
    Layout(Display)
  End Set
End Property

Public Property RimColour() As Color
  Get		 
    Return _rimColour
  End Get
  Set(ByVal Value As Color)
    If Value = Nothing Then
      _rimColour = Colors.Blue
    Else
      _rimColour = Value
    End If
    Layout(Display)
  End Set
End Property

Public Property MarkerColour() As Color
  Get		 
    Return _markerColour
  End Get
  Set(ByVal Value As Color)
    If Value = Nothing Then
      _markerColour = Colors.White
    Else
      _markerColour = Value
    End If
    Layout(Display)
  End Set
End Property

Public Property SecondHandColor() As Color
  Get		 
    Return _secondColour
  End Get
  Set(ByVal Value As Color)
    If Value = Nothing Then
      _secondColour = COLOR_TOMATO
    Else
      _secondColour = Value
    End If
  End Set
End Property

Public Property MinuteHandColor() As Color
  Get		 
    Return _minuteColour
  End Get
  Set(ByVal Value As Color)
    If Value = Nothing Then
      _minuteColour = COLOR_GAINSBORO
    Else
      _minuteColour = Value
    End If
  End Set
End Property

Public Property HourHandColor() As Color
  Get		 
    Return _hourColour
  End Get
  Set(ByVal Value As Color)
    If Value = Nothing Then
      _hourColour = COLOR_WHITESMOKE
    Else
      _hourColour = Value
    End If
  End Set
End Property

Public Property AlarmHandsColor() As Color
  Get		 
    Return _alarmColour
  End Get
  Set(ByVal Value As Color)
    If Value = Nothing Then
      _alarmColour = Colors.Orange
    Else
      _alarmColour = Value
    End If
  End Set
End Property

Public Property Enabled As Boolean
  Get
    Return _isEnabled
  End Get
  Set(ByVal value As Boolean)
    _isEnabled = value
    If _isEnabled Then
      _timer.Start()
    Else
      _timer.Stop()
    End If
  End Set
End Property

Public Property RealTime As Boolean
  Get
    Return _isRealTime
  End Get
  Set(ByVal value As Boolean)
    _isRealTime = value
  End Set
End Property

Public Property ShowSeconds As Boolean
  Get
    Return _showSeconds
  End Get
  Set(ByVal value As Boolean)
    _showSeconds = value
  End Set
End Property

Public Property ShowMinutes As Boolean
  Get
    Return _showMinutes
  End Get
  Set(ByVal value As Boolean)
    _showMinutes = value
  End Set
End Property

Public Property ShowHours As Boolean
  Get
    Return _showHours
  End Get
  Set(ByVal value As Boolean)
    _showHours = value
  End Set
End Property

Public Property ShowAlarm As Boolean
  Get
    Return _showAlarm
  End Get
  Set(ByVal value As Boolean)
    _showAlarm = value
  End Set
End Property

Public Property Time() As DateTime
  Get
    Return _time
  End Get
  Set(ByVal Value As DateTime)
    _time = Value
  End Set
End Property

Public Property Alarm() As DateTime
  Get
    Return _alarm
  End Get
  Set(ByVal Value As DateTime)
    _alarm = Value
    _hasAlarm = Not _alarm = Nothing
  End Set
End Property

See Below:

Clock User Control Properties

Step 13

Return to the MainPage Designer View by selecting the "MainPage.xaml" Tab.
Then from the All Silverlight Controls section in the Toolbox select the Canvas control:

Canvas Control

Step 14

Draw a Two Canvases on the Page then in the XAML Pane above the "</Grid>" then change the "<Canvas>" lines to the following:

<Canvas Height="35" Width="400" VerticalAlignment="Top" HorizontalAlignment="Left" Name="Toolbar"></Canvas>
<Canvas Height="265" Width="400" Margin="0,35,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" Name="Content"></Canvas>

See below:

MainPage with Toolbar Canvas and Content Canvas

Step 15

Then from the Common Silverlight Controls section in the Toolbox select the ComboBox control:

ComboBox Control

Step 16

Draw Two ComboBoxes on the "Toolbar" Canvas by dragging the ComboBoxes from the Toolbox onto the Canvas then in the XAML Pane inbetween the "<Canvas>" and "</Canvas>" tags change the "<ComboBox>" lines to the following:

<ComboBox Canvas.Left="6" Canvas.Top="6" Height="23" Width="75" Name="AlarmHours"/>
<ComboBox Canvas.Left="87" Canvas.Top="6" Height="23" Width="75" Name="AlarmMinutes"/>

See below:

MainPage with Canvas and ComboBoxes

Step 17

Then from the Common Silverlight Controls section in the Toolbox select the CheckBox control:

CheckBox Control

Step 18

Draw a CheckBox on the Upper Canvas (Toolbar) next to the Buttons, and change the <CheckBox> line to the following:

<CheckBox Canvas.Left="168" Canvas.Top="10" Height="17" Width="75" Content="Set Alarm" Name="SetAlarm"/>

See below:

MainPage with Toolbar ComboBoxes and Alarm Set CheckBox

Step 19

Select Debug then the "Build AlarmClock" option from the menu, see below:

Build AlarmClock

Step 20

Then from the AlarmClock Controls section in the Toolbox select the Clock (AlarmClock) control:

Clock Control (AlarmClock)

Step 21

Draw a Clock on the larger or "Content" Canvas and in the XAML Pane change the "<my:Clock>" line to the following:

<my:Clock Canvas.Left="75" Canvas.Top="10" x:Name="AlarmClock"/>

See below:

MainPage with Clock UserControl

Step 22

Right Click on the Page or the entry for "MainPage.xaml" in Solution Explorer and choose the "View Code" option.
In the Code View for the "Public Sub New()" Constructor below the "InitializeComponent()" line type the following:

For H As Integer = 0 To 23
  AlarmHours.Items.Add(Format(H, "00"))
Next
AlarmHours.SelectedItem = CStr(Format(Now.Hour, "00"))
For M As Integer = 0 To 59
  AlarmMinutes.Items.Add(Format(M, "00"))
Next
AlarmMinutes.SelectedItem = CStr(Format(Now.Minute, "00"))

See Below:

MainPage.xaml Constructor

Step 23

While still in the Code View, below the "End Sub" for "Public Sub New()" Constructor type the following Event Handler Sub:

Private Sub AlarmClock_Triggered() Handles AlarmClock.Triggered
  MessageBox.Show("Alarm!", "Alarm Clock", MessageBoxButton.OK)
End Sub 

See Below:

MainPage.xaml Clock Alarm Triggered Event Handler

Step 24

Return to the Designer View by selecting the "MainPage.xaml" Tab, or Right Click on the Page or the Entry for "MainPage.xaml" in Solution Explorer and choose the "View Designer" option.
Click on the "Alarm Set" Checkbox, then goto the Properties box and Click on the "Events" Tab, see below:

AlarmSet CheckBox Property Events

Double Click on the "Click" Event and type in the SetAlarm_Click Sub:

If SetAlarm.IsChecked Then
  AlarmClock.Alarm = New DateTime(Now.Year, Now.Month, Now.Day, _
    CInt(AlarmHours.SelectedItem), _
    CInt(AlarmMinutes.SelectedItem), 0)
Else
  AlarmClock.Alarm = Nothing
End If

See Below:

SetAlarm CheckBox Click Event

Step 25

Save the Project as you have now finished the Silverlight application. Select Debug then Start Debugging or click on Start Debugging:

Start Debugging

After you do, the following will appear in a new Web Browser window:

Application Running

Step 26

Set the Alarm using the ComboBoxes to select the Hour and Minutes, then Check the "Alarm Set" checkbox, a MessageBox will appear when the Alarm is Triggered, see below:

Alarm Clock

Step 27

Close the Application and Browser window by clicking on the Close Button Close on the top right of the Application Window and Web Browser to Stop the application.

This is a Simple Alarm Clock application, you can change the Colours used on the Clock, by selecting the Clock and then goto the Properties box and change them such as the Hour Hand, Face Colour and more. You could also customise the clock such as make it use a GradientBrush or other effects - make it your own!