每周源代码45-在Win7 *和*WinXP 上点击按钮
[原文发表地址]The Weekly Source Code 45 - Kicking Butt on Windows 7 *and* Windows XP
[原文发表时间]2009-08-31 06:53 PM
我真的建议大家尽可能多读一些源代码,因为能读得像写的一样多的话,你将会成为更好的代码书写者。这是每周源代码的宗旨——读代码以便成为更好的开发者。
现在正在举行一个很酷的开发者竞赛活动,叫"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(另外一个图片程序)的事实,可以把它当作一个松散耦合的示例集和。
该程序很好的地方是它可以在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”。
用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)。你会注意到一个按钮旁的小盾牌图标,在下面的对话框中该按钮需要来自用户的响应。
他们的程序在几个地方用到这个。首先,我们可以显示下小盾牌图标吗?我们只有在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多个示例。这里是其中的几个示例。
电源管理
如果你的程序知道机器当前的电源状态,避免在用电池的时候做一些疯狂的事情,这是很棒的。
你可以获取所有种类的很棒的与电量有关的信息。
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中有一些素材图标可用,你可以通过程序访问它们。
这就是说如果你的BluRayRom 或 ZipFile需要素材图标,你只要向它请求就可以了。
任务栏进程
Win7 最好用的微妙功能之一就是:如果在你的程序处理某些事件时有一个进度条,你就可以在任务栏图标上显示进度。这对像文件复制等长时间运行的程序来说是很棒的。
注意这个程序中的进度条,右下方的任务栏按钮显示了这个。
还有一些图标/图象叠加以及其它很好的功能。更妙的是,这非常简单:
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 7 和 SDK
2. 开发测试你的应用程序
获取 Windows API 代码包
了解 应用程序兼容性
3. 获取 Windows 7 徽标
了解 保证程序
获取 Windows 7徽标
4. 用Windows 7点亮你的应用程序
理解怎样 开发Windows 7