65.9K
CodeProject 正在变化。 阅读更多。
Home

模拟数字时钟屏幕保护程序和应用程序

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (1投票)

2012 年 5 月 8 日

CPOL

4分钟阅读

viewsIcon

26232

downloadIcon

732

组合式模拟数字时钟屏保和应用,设置包括颜色和更新间隔。

引言

将您的电脑用作组合式模拟数字时钟。

有些人会一直开着电脑。有些人认为这可以延长电脑的功能寿命。如果您是这些人,不妨试试这款软件。

背景

本文介绍的是一款 C# 编写的模拟数字时钟屏保。它也非常轻量级,压缩后的 exe 文件为 11kb,压缩后的源代码为 33kb。这个 Windows 模拟时钟应用支持命令行参数,这是屏保程序所必需的。

所需的单独参数是 /s、 /c 和 /p,分别用于显示、配置和预览。

/s (显示) 参数会显示如上图所示的屏保。在此模式下,应用程序将在按键事件或鼠标移动时退出。还有一个非标准行为,在不移动鼠标的情况下双击,会显示配置窗体。请参见下文。

/c (配置) 参数会显示如上图所示的屏保设置。在 TextBox 点击事件中,会显示 ColorDialog 窗体。这允许用户选择他们喜欢的配色方案。还可以调整更新间隔。可用的间隔是 100、200、250、350、500、1000、5000 和 10000 毫秒。100 毫秒可以实现类似劳力士的秒针移动效果。选择较大的间隔可以减少 CPU 使用。将秒针的颜色设置为与表盘颜色相同,您几乎注意不到秒针的存在。

/p (预览) 参数会显示一个小的屏保版本,该版本在控制面板中显示(未显示)。

此应用程序还支持 /a (应用) 命令行参数,以正常的应用程序模式显示时钟,该模式可调整大小,并带有右上角的标准控制按钮(如上图所示)。还会显示本地时区信息。

通过在快捷方式中嵌入命令行参数,该应用程序可以以屏保模式或应用程序模式运行。

屏保使用方法

要用作屏保,请将 AnaClock.exe 的后缀从 .exe 改为 .scr,然后将其放入

\WINDOWS\system32 目录

\WINDOWS\sysWOW64 目录(适用于 Windows 7 64 位操作系统)

您可能需要以管理员身份运行才能执行此操作。

之后,AnaClock 屏保将出现在控制面板的屏保列表中。

选择后,应出现小预览,并且“设置”和“全屏预览”按钮将启用。

解决方案

Visual Studio 2008 项目包含两个窗体 *FormMain.cs* 和 *FormScreenSaverSettings.cs*,其他类有 `ColorUtils`、`RegistryWrapper` 和 `TextBoxColorSaver`。大部分核心功能都 resides 在窗体本身。`TextBoxColorSaver` 继承自 `RegistryWrapper`,并被两个窗体使用。`TextBoxColorSaver` 包含 `ColorUtils` 的实例。

根据命令行参数,Program.cs 将创建 `FormMain` 或 `FormScreenSaverSettings` 的实例。FormMain 的行为由使用的构造函数决定,对应于命令行参数 /s、/p 或 /a。

屏保模式与应用程序模式的核心区别

以下是 Visual Studio 生成的 `InitializeComponent()` 的代码片段,该代码在所有 `FormMain` 构造函数中使用。由于这是一个屏保,我们不希望有边框,不出现在任务栏,并且需要保持在最顶层。

private void InitializeComponent()
{
 .
 .
 this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
 this.ShowInTaskbar = false;
 this.TopMost = true;
 .
 .
}

以下是屏保的完整构造函数。我们希望设置基于屏幕尺寸的边界并隐藏光标。

public FormMain(Rectangle Bounds)
{
 InitializeComponent();
 this.Bounds = Bounds;
 //hide the cursor
 Cursor.Hide();
}

以下是应用程序模式的完整构造函数。我们设置了一些标志,以便程序不会因鼠标移动或按键而退出。最重要的是,我们将 `FormBorderStyle` 设置为 `Sizable`(可调整大小)。

/// default constructor used in application mode (/a)
public FormMain()
{
 bRunAsApp = true;
 IsPreviewMode = bRunAsApp;
 InitializeComponent();
 this.ShowInTaskbar = true;
 this.Text = "MainForm as Application";
 this.TopMost = false;
 this.FormBorderStyle = FormBorderStyle.Sizable;
}

FormScreenSaverSettings

在 `FormScreenSaverSettings` 中的六个颜色相关的文本框都高效地使用了相同的 `OnColorTextBoxClick` 方法。在此事件处理程序中,我们将参数 sender(类型为 object)强制转换为子类 TextBox。对于这个窗体,我们知道每个 TextBox 都有一个唯一的名称。我们可以利用这一点来实现代码重用。

private void OnColorTextBoxClick(object sender, EventArgs e)
{
 TextBox tb = sender as TextBox;
 mTextBoxColorSaver.ChooseColor(ref tb, ref colorDialog);
}

注意,语法

TextBox tb = (TextBox)sender;

也会奏效。

类 `TextBoxColorSaver` 具有 `ChooseColor` 方法,该方法使用 Windows `ColorDialog` 允许用户选择颜色。确认后,将颜色的名称保存在注册表中,并设置文本框的 `BackColor`。此外,文本框的前景文字颜色设置为黑色或白色,以与 `BackColor` 形成对比。

/// pop up color picker and store results in Registry 
/// and load into text box.
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
 { // On Cancel Load default 
  tb.Text = cu.GetColorName(tb.BackColor);
  PutString(tb.Name, tb.Text);
 }
}

上述方法使用 `ColorUtils` 类的实例 `cu` 来调用 `GetColorName` 和 `GetContrastTextColor` 方法。该类完整展示如下。

using System;
using System.Drawing;

namespace Hugetiger
{
 /// Color utilities
 public class ColorUtils
 {
  /// Convert a String ColorName to an actual Color.
  /// Prefer known colors, use DefaultColor if needed.
  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")
    {  // in Hex
     rv = Color.FromArgb(HexToInt(psColorName.Substring(0, 2)), 
     HexToInt(psColorName.Substring(2, 2)), HexToInt(psColorName.Substring(4, 2)));
    }
   }
   return rv;
  }
  
  /// Convert a String ColorName to an actual Color, use default Color White
  public Color StringToColor(String psCN)
  {
   return StringToColor(psCN, Color.White);
  }

  /// Use White text for dark backgrounds
  /// and visa versa
  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;
  }

  /// Returns either named color or web type 6 hex numbers
  /// Black 000000 White FFFFFF  Red FF0000 Blue 0000FF
  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;
  }

  /// Convert an int to a hex string
  /// tested for range int 0 to 255
  public String IntToHex(int p)
  {
   String rv = p.ToString("X");
   if (rv == "0")
   {
    rv = "00";
   }
   return rv;
  }

  /// Convert hex string to an int
  /// tested for range hex 00 to FF
  public int HexToInt(String p)
  {
   int rv = int.Parse(p, System.Globalization.NumberStyles.HexNumber);
   return rv;
  }
 }
}

提供灵感和部分源代码的文章

  • 使用 GDI+ 和 Windows Forms 的 C# 可调整大小的模拟时钟
  • 制作 C# 屏保

关注点

Analog Digital Clock 屏保和应用以我喜欢且适合单个程序员小型项目的风格编写。其他组织风格可能更适合团队编程工作或大型项目。

我用来实现应用程序之间持久化(Persistence)的技术很有趣。

编写这款软件、记录它以及撰写这篇文章都很有趣。已在 Windows 7、Vista、MS Server 2003 和 XP 上进行测试。

历史

首个版本:2012 年 5 月 7 日

© . All rights reserved.