Share via


每周源代码45-在Win7 *和*WinXP 上点击按钮

[原文发表地址]The Weekly Source Code 45 - Kicking Butt on Windows 7 *and* Windows XP

[原文发表时间]2009-08-31 06:53 PM

clip_image002

我真的建议大家尽可能多读一些源代码,因为能读得像写的一样多的话,你将会成为更好的代码书写者。这是每周源代码的宗旨——读代码以便成为更好的开发者。

现在正在举行一个很酷的开发者竞赛活动,叫"Code7"。如果你在现在到十月七号之间编写一个Windows 7的应用程序,你就可能会赢得巨额奖金和/或者参加PDC(译者注:专业开发人员大会)的一次机会。

Windows 7中有很多新的API(以及现在已经存在的有用的Vista API),像下面这些:

* Windows 7 Taskbar Integration

* Transactional File System

* I/O Optimization

* Event Tracing for Windows (ETW)

* Windows 7 Libraries

* Windows 7 Sensor and Location Platform

* Aero Glass

在其中的一些实际使用的例子中,(还)没有针对像环境光感应器(Ambient Light Sensors)这些东西的硬件。有人已经能把网络摄像头关联到Windows 7 Sensors API,并用新的显示器配置 API*做了一个程序使其显示器变成黑屏。他甚至可以让它在他离开的时候关掉机器。

XP2Win7 - Windows 7样本代码/应用程序

我已经找出一些可以作为Win7起步学习的应用程序示例。目前为止最好的是“PhotoView”。不要惊于它是YAPA(另外一个图片程序)的事实,可以把它当作一个松散耦合的示例集和。

clip_image004

该程序很好的地方是它可以在Windows XP Windows Vista Windows 7上运行。 这对你来说可能是显而易见的甚至很傻的陈述,但是亲爱的读者,值得着重指出的是应用程序在三个平台上运行得都很棒。我使用的程序99%在Win7上工作很好。当然,需要更新一些驱动和古怪的VPN(译者注: 虚拟专用网络),但是令我感到欣慰的是,我知道可以编写一个Windows程序,嗯,它可以运行在所有Windows平台上。J

这个PhotoView应用程序(也叫XP2Win7 是用托管代码编写,用插件“在更高级平台上自动照亮(light up on up-level platforms)”。这是幽默的Microsoft 说法,意思是如果你的操作系统有个功能,程序会检测并使用该功能。

有个不错的概述Word文档,解释该程序以及它是如何编写的。MSI会安装程序,如果你找不到,它的源代码根据需要安装在~\MyDocuments\Xp2Win7目录下。如果你想编译几个部分的话,你需要Visual C++……读一下readme文件。这是个很好的非常广义的示例,示范了如何制作MMC 报告查看器、snapins、延迟服务、注册计划任务、堆。

(不幸的是,编写这个的人没有将MEF用于他们的插件模型,但我会跟他们交谈。这会让他们可以删除很多没用的样本插件代码。)

它用Windows API Code Pack(下面会谈到)来做很多工作。这里是一些有趣的部分。

任务栏弹出列表

如果程序在Win7下运行,当你在任务栏按钮右击(或刷一下)时,会出现一个”jumplists”。

image

用Taskbar API这个很容易添加。请注意多个分类目录、用户任务、最近项目以及自定义类别。

  1: Taskbar.JumpList.CustomCategories.Clear();
  2: Taskbar.JumpList.UserTasks.Clear();
  3: Taskbar.JumpList.KnownCategoryToDisplay = KnownCategoryType.Recent;
  4: 
  5: CustomCategory allAlbumsCategory = new CustomCategory("All Albums");
  6: //...snip out enumerating of the filesystem to get photo albums
  7: Taskbar.JumpList.CustomCategories.Add(allAlbumsCategory);
  8: 
  9: Taskbar.JumpList.UserTasks.Add(
  10: new JumpListLink()
  11: {
  12: Title = "Reset configuration",
  13: Path = typeof(XP2Win7.VistaPlugins.ConfigurationResetter.Program).Assembly.Location,
  14: Arguments = XP2Win7.VistaPlugins.ConfigurationResetter.Program.ResetCommand
  15: });
  16: Taskbar.JumpList.UserTasks.Add(
  17: new JumpListLink
  18: {
  19: Title = "Launch indexing task",
  20: Path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Constants.ServiceCommandLine),
  21: Arguments = Constants.ServiceAsTaskCommandLine
  22: });
  23: Taskbar.JumpList.UserTasks.Add(
  24: new JumpListLink { Title = "Open albums directory", Path = Host.UserConfiguration.AlbumRepositoryPath });
  25: 
  26: Taskbar.JumpList.RefreshTaskbarList();

Windows 7 Libraries

你也可以为你的程序添加Windows 7 Libraries。

  1: //Create new shell library under the default Libraries
  2: using (ShellLibrary library = new ShellLibrary("XP2Win7", true))
  3: {
  4: library.LibraryType = LibraryFolderType.Pictures;
  5: library.IconResourceId = GetPictureLibraryIcon(); //Set the same Icon as the Picture library
  6: library.IsPinnedToNavigationPane = true;
  7: 
  8: 
  9: foreach (string folderPath in GetPicturesFolders())
  10: {
  11: library.Add(folderPath);
  12: }
  13: 
  14: library.ShowManageLibraryUI(Application.Current.MainWindow,
  15: "Manage the XP2Win7 library", "You can manualy add or remove folders",
  16: true);
  17: }

用户访问控制( UAC

Windows Vista 和 Windows 7都包含用户访问控制(UAC)。你会注意到一个按钮旁的小盾牌图标,在下面的对话框中该按钮需要来自用户的响应。

Application reconfiguration

他们的程序在几个地方用到这个。首先,我们可以显示下小盾牌图标吗?我们只有在UAC启用的时候才会这么做。

  1: protected override BitmapSource BitmapSource
  2: {
  3: get
  4: {
  5: if (UacHelpers.UserAccountControl.IsUacEnabled)
  6: {
  7: return Microsoft.SDK.Samples.VistaBridge.Library.StockIcons.StockIcons.Shield;
  8: }
  9: else
  10: {
  11: return ImageFromResource(Assembly.GetExecutingAssembly(), 
  12: "UserAccountControl.StartService-128x128.png");
  13: }
  14: }
  15: }

然后,如果他们确实点击按钮,我们想要以管理员的身份启动一些进程时,我们需要调动一个特殊的API来完成。这意味着通过辅助API很容易实现。

  1: if (UacHelpers.UserAccountControl.IsUacEnabled || !UacHelpers.UserAccountControl.IsUserAdmin)
  2: {
  3: UacHelpers.UserAccountControl.CreateProcessAsAdmin(
  4: typeof(ServiceStarter.Program).Assembly.Location, "XP2Win7ImageDataService");
  5: }
  6: else
  7: {
  8: Process.Start(typeof(ServiceStarter.Program).Assembly.Location, "XP2Win7ImageDataService");
  9: }

非常灵活,易于编码。Windows API Code Pack让所有这些以及其它很多APIs对托管代码开发者(C#, VB以及其他任何人)来说更简单。

Windows API Code Pack

另一个不错的Windows示例代码包是Windows API Code Pack. 这是个示例金矿,都是用C# 和VB编写。大约有20多个示例。这里是其中的几个示例。

电源管理

如果你的程序知道机器当前的电源状态,避免在用电池的时候做一些疯狂的事情,这是很棒的。

Power Management

你可以获取所有种类的很棒的与电量有关的信息。

  1: private void GetPowerSettings()
  2: {
  3: settings.PowerPersonality = PowerManager.PowerPersonality.ToString();
  4: settings.PowerSource = PowerManager.PowerSource.ToString();
  5: settings.BatteryPresent = PowerManager.IsBatteryPresent;
  6: settings.UpsPresent = PowerManager.IsUpsPresent;
  7: settings.MonitorOn = PowerManager.IsMonitorOn;
  8: settings.MonitorRequired = PowerManager.MonitorRequired;
  9: 
  10: if (PowerManager.IsBatteryPresent)
  11: {
  12: settings.BatteryShortTerm = PowerManager.IsBatteryShortTerm;
  13: settings.BatteryLifePercent = PowerManager.BatteryLifePercent;
  14: 
  15: BatteryState batteryState = PowerManager.GetCurrentBatteryState();
  16: 
  17: string batteryStateStr = string.Format(
  18: "ACOnline: {1}{0}Max Charge: {2} mWh{0}Current Charge: {3} mWh{0}Discharge Rate: {4} {0}Estimated Time Remaining: {5}{0}Suggested Critical Battery Charge: {6} mWh{0}Suggested Battery Warning Charge: {7} mWh{0}",
  19: Environment.NewLine, 
  20: batteryState.ACOnline, 
  21: batteryState.MaxCharge, 
  22: batteryState.CurrentCharge, 
  23: batteryState.ACOnline == true ? "N/A" : batteryState.DischargeRate.ToString() + " mWh", 
  24: batteryState.ACOnline == true ? "N/A" : batteryState.EstimatedTimeRemaining.ToString(), 
  25: batteryState.SuggestedCriticalBatteryCharge, 
  26: batteryState.SuggestedBatteryWarningCharge
  27: );
  28: 
  29: settings.BatteryState = batteryStateStr;
  30: }
  31: }

也可能被告知很多与电源有关的事件

  1: PowerManager.IsMonitorOnChanged += new EventHandler(MonitorOnChanged);
  2: PowerManager.PowerPersonalityChanged += new EventHandler(
  3: PowerPersonalityChanged);
  4: PowerManager.PowerSourceChanged += new EventHandler(PowerSourceChanged);
  5: if (PowerManager.IsBatteryPresent)
  6: {
  7: PowerManager.BatteryLifePercentChanged += new EventHandler(BatteryLifePercentChanged);
  8: 
  9: // Set the label for the battery life
  10: SetLabelButtonStatus(batteryLifePercentLabel, string.Format("{0}%", PowerManager.BatteryLifePercent.ToString()));
  11: }
  12: 
  13: PowerManager.SystemBusyChanged += new EventHandler(SystemBusyChanged);
素材图标

很多人没有意识到在Windows中有一些素材图标可用,你可以通过程序访问它们。

image

这就是说如果你的BluRayRom 或 ZipFile需要素材图标,你只要向它请求就可以了。

任务栏进程

Win7 最好用的微妙功能之一就是:如果在你的程序处理某些事件时有一个进度条,你就可以在任务栏图标上显示进度。这对像文件复制等长时间运行的程序来说是很棒的。

注意这个程序中的进度条,右下方的任务栏按钮显示了这个。

image

还有一些图标/图象叠加以及其它很好的功能。更妙的是,这非常简单:

  1: // When the user changes the trackBar value,
  2: // update the progress bar in our UI as well as Taskbar
  3: progressBar1.Value = trackBar1.Value;
  4: 
  5: TaskbarManager.Instance.SetProgressValue(trackBar1.Value, 100);

因为程序可以有多个进度条,你不得不手动决定你想让任务栏上的进度显示哪一个。

核心辅助函数

最后,有些不错的“CoreHelpers”让你的程序易于阅读,并可以同时在XP, Vista 和Win7上运行。

  1: //example
  2: if (CoreHelpers.RunningOnXP()) { ... } 
  3: //example
  4: if (CoreHelpers.ThrowifNotWin7() { ... } 
  5: // and all the others you'd expect for XP, Vista, Win7

我只涉及到了这些示例的表面。如果你在做Windows 客户端开发,一定要查看https://windowsclient.net/https://www.msdn.com/windows以了解更多,并开始为https://www.code7contest.com编写你的程序。

1. 获取 Windows 7SDK

* Windows SDK

2. 开发测试你的应用程序

* 获取 Windows API 代码包

* 了解 应用程序兼容性

* 阅读 Windows 7 应用程序质量清单

* 下载 针对开发人员的indows 7 教材

3. 获取 Windows 7 徽标

* 了解 保证程序

* 获取 Windows 7徽标

4. 用Windows 7点亮你的应用程序

* 阅读 Windows 7 开发者指南

* 理解怎样 开发Windows 7