Introduction
Use your computer as a combination analog digital clock.
Some people leave their computers on all the time. Some think this will
extend the computers functional lifespan. If this is you, give this software a
try.
Background
This article is a clock screen saver and written in C#. It
is also very lightweight, the zipped exe is 11kb and zipped source is 33kb. This windows analog clock application takes command line arguments as screen
savers are required to do.
The required individual arguments are /s, /c, and /p for show,
configure, and preview.
The /s (show) argument displays the screen saver as shown above. In this mode
the application will exit on key press events or mouse movements. There is also
a non-standard behavior, on double click without moving the mouse, the
configuration form is displayed. See below.
The /c (configure) argument displays the screen saver settings as shown above.
On TextBox click event, the ColorDialog form is displayed. This allows the user
to choose their favorite color scheme. The update interval can also be adjusted.
The available intervals are 100, 200, 250, 350, 500, 1000, 5000, and 10000
milliseconds. 100 ms will give you a Rolex like second hand movement. Choose a
larger interval to use less CPU. Choose the second hand color the same as the
face color and you will hardly notice the second hand at all.
The /p (preview) argument displays a small version of the screen saver which is displayed
in the control panel (not shown).
This application also takes the /a (application) command line argument
to display the clock as a normal application, which is resizable, and movable
with the usual control buttons in the upper right corner, shown above. The local
Time Zone information is also displayed.
By imbedding command line arguments in a short cut the application can be run
in either screen saver or application mode.
Screen Saver Usage
To use as a screen saver change the AnaClock.exe suffix from .exe to .scr and
put it into the
\WINDOWS\system32 directory
or
\WINDOWS\sysWOW64 directory for Windows 7 64 bit OS
You may need to run as an administrator to do this.
Thereafter, the AnaClock screen saver will show up in the control panel
screen saver list.
Upon selection, the small view should appear, and the settings and full screen
preview buttons are enabled.
The Solution
The Visual Studio 2008 project contains two forms FormMain.cs, and
FormScreenSaverSettings.cs other classes are ColorUtils
, RegistryWrapper
, and
TextBoxColorSaver
. Most of the guts reside in the forms themselves.
TextBoxColorSaver
inherits from RegistryWrapper
and is used by both forms.
TextBoxColorSaver
has an instance of ColorUtils
.
Based upon the command line argument, Program.cs will create an instance of
either FormMain
or FormScreenSaverSettings
. The behavior of FormMain is
determined by which constructor is used, corresponding with the command line
arguments /s, /p, or /a.
Essence of screen saver vs application mode
Below is a code segment of Visual Studio generated InitializeComponent()
used in
all FormMain
constructors. Since this is a screen saver we want no borders, not
in taskbar, and stay on top.
private void InitializeComponent()
{
.
.
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.ShowInTaskbar = false;
this.TopMost = true;
.
.
}
Below is the complete constructor for the screen saver. We want to set the
bounds for the passed screen size and hide the curser.
public FormMain(Rectangle Bounds)
{
InitializeComponent();
this.Bounds = Bounds;
Cursor.Hide();
}
Below is the complete constructor for application mode. We set some flags so
the program won't exit on mouse movement or key down. Most importantly, we set
the FormBorderStyle
to Sizable.
public FormMain()
{
bRunAsApp = true;
IsPreviewMode = bRunAsApp;
InitializeComponent();
this.ShowInTaskbar = true;
this.Text = "MainForm as Application";
this.TopMost = false;
this.FormBorderStyle = FormBorderStyle.Sizable;
}
FormScreenSaverSettings
The six color related text boxes in FormScreenSaverSettings
efficiently all use the same OnColorTextBoxClick
method. In this event handler we cast parameter sender of type object to the
child class TextBox. For this form we know that each TextBox has a unique name.
We can use that fact to our advantage in terms of code reuse.
private void OnColorTextBoxClick(object sender, EventArgs e)
{
TextBox tb = sender as TextBox;
mTextBoxColorSaver.ChooseColor(ref tb, ref colorDialog);
}
Note, syntax:
TextBox tb = (TextBox)sender;
would also work.
Class TextBoxColorSaver
has method ChooseColor
which uses the windows
ColorDialog
to allow the user to choose a color. Upon confirmation, the chosen
color name is put into the registry, and the textbox BackColor
is set as well.
Also, the textbox text color is set to either black or white for contrast with
the BackColor
.
public void ChooseColor(ref TextBox tb, ref ColorDialog colorDialog)
{
DialogResult dr = colorDialog.ShowDialog();
if (dr == DialogResult.OK)
{
Color aColor = colorDialog.Color;
tb.Text = cu.GetColorName(aColor);
PutString(tb.Name, tb.Text);
tb.BackColor = aColor;
tb.ForeColor = cu.GetContrastTextColor(aColor);
}
else
{ tb.Text = cu.GetColorName(tb.BackColor);
PutString(tb.Name, tb.Text);
}
}
The above method uses an instance cu of class ColorUtils
for methods
GetColorName
and GetContrastTextColor
. The class is shown in its
entirety below.
using System;
using System.Drawing;
namespace Hugetiger
{
public class ColorUtils
{
public Color StringToColor(String psColorName, Color DefaultColor)
{
Color rv = DefaultColor;
if (psColorName != "null" && psColorName != String.Empty)
{
rv = Color.FromName(psColorName);
KnownColor kn = rv.ToKnownColor();
if (kn.ToString() == "0")
{ rv = Color.FromArgb(HexToInt(psColorName.Substring(0, 2)),
HexToInt(psColorName.Substring(2, 2)), HexToInt(psColorName.Substring(4, 2)));
}
}
return rv;
}
public Color StringToColor(String psCN)
{
return StringToColor(psCN, Color.White);
}
public Color GetContrastTextColor(Color aColor)
{
Color rv = Color.Gray;
float brightness = aColor.GetBrightness();
if (brightness < 0.50)
{
rv = Color.White;
}
else
{
rv = Color.Black;
}
return rv;
}
public String GetColorName(Color p)
{
String rv = String.Empty;
if (p.IsNamedColor)
{
rv = p.Name;
}
else
{
rv = IntToHex(p.R) + IntToHex(p.G) + IntToHex(p.B);
}
return rv;
}
public String IntToHex(int p)
{
String rv = p.ToString("X");
if (rv == "0")
{
rv = "00";
}
return rv;
}
public int HexToInt(String p)
{
int rv = int.Parse(p, System.Globalization.NumberStyles.HexNumber);
return rv;
}
}
}
Articles that provided inspiration and some source code
- A Resizable Analog Clock in C# using GDI+ & Windows Forms
- Making a C# Screen Saver
Points of Interest
Analog Digital Clock Screen Saver and App is written in a style that I like and feel is appropriate for small projects for a sole programmer. Other styles of organization may
be better for a team programming effort or for larger projects.
The techniques I used to implement Persistence from one run of the App to the next were interesting.
It
was fun writing this software, documenting it, and authoring this article.
Tested on Windows 7, Vista, MS Server 2003, and XP.
History
First version
May 7th 2012