通过桌面上的自定义时钟显示任何时区当前的时刻






4.28/5 (7投票s)
一个简单的智能客户端应用程序,探索本地资源和使用2.0框架进行UI开发。
引言
我非常喜欢智能客户端的概念。越是接触它们,我越是看到它们提供的巨大潜力。在我关于智能客户端的第一篇文章中,我有一个个人目标,即要触及智能客户端设计的要点。在那篇文章中,我触及了智能客户端设计的两个方面,但我想更深入地探讨。这些话题是丰富的(WinForms)UI的目的以及本地资源的作用。
与上一篇文章一样,该项目的所有源代码都基于2.0框架。
摘要
每次你去联邦快递或UPS商店时,他们墙上都有5到6个时钟,显示世界主要城市的时间。我想做一个有趣的智能客户端,利用相同的概念,显示多个时区当前的时刻。这个智能客户端使用了www.worldtime-clock.com提供的网络服务。他们的网络服务有两个方法:一个用于获取时区列表,另一个用于返回给定时间区的当前时间。这个远程数据源与美国海军原子钟同步,并使用户能够查询任何时区,而不仅仅是24个常规区域。
丰富的UI
使用WinForms UI进行智能客户端开发的优势在于,您拥有GDI+等工具的全部功能,这些工具为您的UI增添了光彩。在此应用程序的情况下,我创建了两个自定义控件来创建一个丰富的环境。第一个控件是一个自定义面板,显示带有渐变背景的标题(类似于FotoVision控件)。使用自定义控件没有内在优势,但它使UI更具吸引力。是的,美学和可用性是智能客户端的关注点。
第二个控件是一个完全可定制的时钟控件。该时钟允许在其所有显示属性在设计时或运行时进行配置。对于此应用程序,我为用户设置了一个小型“设计环境”,以便用户可以创建和自定义他们喜欢的时钟。该时钟绑定到主窗体上显示的时间区的时钟,然后它就会一直走动。当然,由于重点在于丰富的UI,该时钟具有工具提示信息、上下文菜单等,这些都使其与基于Web的替代方案区分开来。
本地资源
智能客户端的另一个优势是它们能够使用本地资源(与基于浏览器的应用程序不同)。我使用的第一个本地资源只是本地系统时间。调用网络服务获取某个时区的时间存在一个问题,那就是你不知道请求需要多长时间。慢速网络连接或网站上的重负载可能会导致网络服务返回时的延迟。
例如,假设你在东海岸,时间是下午4:00:00,你正在调用网络服务以获取亚利桑那州的时间。(你这样做是因为亚利桑那州不使用夏令时,你记不清他们是早1个小时还是早2个小时。)如果网络服务有任何延迟,比如15秒,你仍然会得到5:00:00的值。问题是,现在你的本地时间是4:00:15。这意味着网络服务返回的时间有15秒的误差。如果你添加的每个时钟显示的时间秒数都不同,那将是没有意义的。
我正在使用本地系统时间来修复任何延迟问题,通过调整返回的时间以反映本地计算机上的当前秒数。这并不复杂,但它很好地说明了为什么智能客户端不应该完全依赖远程资源。
public DateTime GetCurrentTime(string timeZone)
{
// Call the web service to get the time in a given time zone
WorldTime.WebClock worldTime = new WorldTime.WebClock();
worldTime.GetTime(timeZone);
// It may take several seconds to get a response from
// the web service. This adjusts the returned time to reflect
// the seconds on the local machine.
DateTime adjustedTime = new DateTime(zoneTime.Year, zoneTime.Month,
zoneTime.Day, zoneTime.Hour, zoneTime.Minute,
DateTime.Now.Second);
return adjustedTime;
}
用户设置
下一个本地资源是用户设置。该应用程序允许用户添加无限数量的时钟。应用程序退出时,一个自定义的Settings对象会持久化时钟布局和时区设置。下次应用程序启动时,这些设置会被加载,并重新创建用户的时钟。由于本地时间和时钟时区之间的差异被持久化了,因此无需再次调用网络服务来检查时间。(使用本地资源的优势开始显现了吗?这里的重点不是额外的互联网调用。)
这些设置是使用新的ApplicationSettingsBase
类存储的。我创建了一个自定义类来保存我的设置,一个通用的List<>
,其中包含自定义Settings类。
// Class to hold setting information
public class ClockSetting
{
private int _someValue;public ClockSetting() { }
public int SomeValue
{
get{ return _someValue; }
set{ _someValue = value; }
}
}
// This class inherits from ApplicationSettingsBase.
// The only property being persisted
// is a collection of ClockSetting objects.
// This allows the settings for each clock
// created by the user to be stored and loaded with minimal coding.
public class TimePieceSettings : ApplicationSettingsBase
{
[UserScopedSetting()]
public List<ClockSetting> ClockSettings
{
get { return (List<ClockSetting>)this["ClockSettings"]; }
set { this["ClockSettings"] = (List<ClockSetting>)value; }
}
}
// Loading the settings
_settings = new TimePieceSettings();
foreach (ClockSetting setting in _settings.ClockSettings)
{
AddClock(setting);
}
//Saving the settings
foreach(Clock clock in _layoutPanel.Controls)
{
ClockSetting instance = CreateSetting(clock);
_settings.ClockSettings.Add(instance);
}
_settings.Save();
几乎没什么。加载或保存自定义用户设置到本地的代码不到5行。
好了,就是这样。又一个智能客户端的例子供你尝试。我希望我已经阐明了本地资源为什么是智能客户端开发的重要组成部分,以及丰富的UI有什么优势。
尽情享用!