Windows 7:使用 .NET 解释新功能






4.65/5 (78投票s)
使用简单的演示应用程序解释新的 Win7 功能。
- 文章来源 - 合集 - 677 KB
- 应用程序重启演示 - 36 KB
- 任务栏示例 - 550 KB
- 网络示例 - 10 KB
- 电源管理示例 - 25 KB
- 任务对话框示例 - 158 KB
- 传感器示例 - 35 KB
- 下载 PictureViewer_Sample.zip - 1.18 MB
目录
引言
Windows 7 是微软最新的操作系统版本。正如许多人想知道它与 Windows Vista 相比有哪些基本功能是缺失的,或者为什么你应该选择它一样,这最初也是我的想法,但在我尝试之后,我发现它比我之前使用的版本要好得多。
Windows 7 的功能
Windows 现在比其他操作系统(如 Vista)运行得更快,同时消耗的资源更少。它通过在真正需要时才触发重要服务的启动来减少后台活动。因此,网络发现服务仅在你实际将计算机连接到网络时才启动,而不是在后台一遍又一遍地进行此过程。因此,服务仅在需要时运行,停止它们将释放它所利用的所有资源。
我发现最有趣的事情是,我们不仅可以依赖后台 Windows 服务,还可以通过切换到“触发启动服务”或“计划任务”来轻松配置我们自己的服务来实现此目的。如果你想使用此功能创建自己的 Windows 服务,可以阅读文章 Windows 触发启动服务。
在本文中,我们将讨论 Windows 7 为我们带来的一些激动人心的新功能,这些功能与用户界面的外观和感觉、API 更改等有关。
API 代码包中公开的 Windows 7 新功能
- 应用程序重启和恢复 API
- Windows 7 任务栏跳转列表、图标叠加、进度条、标签式缩略图和缩略图工具栏
- 传感器平台 API
- Windows 7 任务对话框
- Windows 7 公共文件对话框,包括自定义控件
- Explorer 浏览器控件
- Windows 7 Shell 搜索 API 支持,Shell 对象的拖放功能等。
- 网络列表管理器 API
- 扩展语言服务 API
- Shell 属性系统
- Windows 7 库、已知文件夹、非文件系统容器
- 电源管理 API
- Direct 3D 对 11.0、10.1/10.0 的支持,Direct 2D、Directwrite、Windows Imaging Component (WIC) API 等。
- 更多...
如果你想了解 Windows 在此版本中引入的所有其他功能,请访问此 链接。
Windows API 代码包
在 .NET 4.0 中,Windows 7 的功能(除少数之外)没有得到很好的公开。因此,我们需要通过创建互操作服务直接调用 API。为了直接为应用程序提供这些功能,Windows 发布了一个开源项目,可以在 这里 找到。该项目基本上是一个 COM 包装器,可以减少代码的复杂性。在本文中,我将通过 Windows API 代码包演示 Windows 7 引入的大部分有趣功能。
最低要求
运行示例应用程序的最低要求是 Visual Studio 2008(最好是 2010),安装了 .NET Framework 3.5 SP1,当然还有 Windows 7 环境。
注意:所有示例均为 Windows 窗体应用程序,以减少复杂性,也方便那些不太熟悉 WPF 应用程序的用户。
入门
在继续之前,请先解压 **Windows API 代码包**,然后在 Visual Studio 2010 / Visual Studio 2008 SP1 中打开 _\WindowsAPICodePack\WindowsAPICodePack.sln_ 并编译应用程序。这将生成所有编译项目的 _Bin\debug_ 文件夹中的 DLL。现在关闭应用程序,然后重新启动 Visual Studio。(最好是 VS 2010,因为我使用它创建了所有示例应用程序),然后创建一个新的 Windows 应用程序。
将创建一个包含一个空白窗体的项目。现在你有两个选择:
- 添加对 `WindowsAPICodePack` DLL 的引用。为此,只需右键单击 **项目**,然后选择 **添加引用**,并添加所有必需的 DLL。
- 直接添加所需的项目。只需右键单击 **解决方案资源管理器**,然后选择 **添加现有项目** 以添加相应的项目。通常,所有应用程序都需要添加 `Core`。
完成此操作后,你就可以创建你的第一个 Windows 7 应用程序了。
在所有示例应用程序中,我都将项目直接添加到了应用程序中。因此,当你在尝试这些示例时,如果遇到项目无法加载的错误消息,请按照此处提到的相同方式将其从解决方案中删除。
应用程序重启和恢复 API
应用程序重启 API 是 Windows Vista 引入的一项独特功能,可以在应用程序崩溃或意外终止时恢复丢失的数据。微软为所有应用程序提供了 API 支持,以恢复丢失的数据。你可能已经在 Vista 甚至 Office 应用程序中熟悉这项功能了,这些应用程序可以在恢复过程中轻松恢复未保存的数据。在 Vista 中,如果程序终止,会弹出一个关于问题的对话框,并在关闭应用程序之前调用恢复功能,以确保应用程序中的数据不会因该错误而丢失。

Windows 7 API 支持应用程序重启恢复。我们可以通过注册应用程序到 `ApplicationRestartRecoveryManager` 来轻松地在自己的应用程序中使用此功能。
ApplicationRestartRecoveryManager.RegisterForApplicationRestart(
new RestartSettings("/recover", RestartRestrictions.NotOnPatch));
RecoveryData data = new RecoveryData(new RecoveryCallback(RecoverData), null);
RecoverySettings settings = new RecoverySettings(data, 0);
ApplicationRestartRecoveryManager.RegisterForApplicationRecovery(settings);
上面的代码会将应用程序注册到 `RestartRecoveryManager`,前提是应用程序被 Windows 错误报告终止。需要注意的是,Windows 会自动使用 `/recover` 命令行参数打开崩溃的应用程序。因此,我们使用此参数来确保应用程序在崩溃后重新启动。
`ApplicationRestartRecoveryManager.RegisterForApplicationRestart` 注册应用程序以在应用程序重新启动时调用重启功能。
RecoveryData data = new RecoveryData(new RecoveryCallback(RecoverData), null);
通过这一行,我们定义了回调函数 `RecoverData`,该函数将在每次重启时自动调用。`RegisterForApplicationRecovery` 接受一个 `RecoverySettings` 参数,该参数实际上注册了应用程序以进行恢复。
恢复期间存储数据
在 `RecoverData` 中,我们编写:
if(ApplicationRestartRecoveryManager.ApplicationRecoveryInProgress())
Environment.Exit(2);
//Code to save Data
ApplicationRestartRecoveryManager.ApplicationRecoveryFinished(true);
`ApplicationRecoveryInProgress` 在进行活动数据恢复时返回 `true`。奇怪的是,当用户在恢复管理器对话框中单击 **取消** 按钮时,它也会返回 `true`。因此,我们退出应用程序而不保存恢复数据。否则,我们编写代码来存储数据,最后调用 `ApplicationRecoveryFinished` 以确保数据已正确写入。
检索恢复数据
由于我已经注册了应用程序在重启时传递 /restart 命令行参数,我们只需要找到这个参数并相应地恢复数据。
string[] arguments = System.Environment.GetCommandLineArgs();
if(arguments.Contains<string>("/restart"))
{
//Recover the data here.
}
你可以从 这里 尝试示例工作应用程序。
Windows 7 任务栏跳转列表、图标叠加、进度条、标签式缩略图和缩略图工具栏
我接下来要介绍的 Windows 7 的一个有趣功能是任务栏。Windows 7 的任务栏与其他 Windows 不同。它具有许多功能,如 `JumpLists`(跳转列表)、`Icon Overlay`(图标叠加)、`Progress Bar`(进度条)、`Tabbed Thumbnails`(标签式缩略图)等,以增强用户体验。让我们在自己的应用程序中实现它。
进度条
如果你将 `TaskbarManager.Instance.SetProgressValue(0, 100); TaskbarManager.Instance.SetOverlayIcon(this.Icon, "NewIcon");` 放在窗体的 `Shown` 事件中,它将在任务栏上显示一个图标,就像所有其他应用程序一样,并将进度值设置为 0。100 是进度条可以拥有的最大值。因此,要从你的程序设置进度值,请再次调用 `SetProgressValue` 并传入适当的值,进度将在 `TaskBarButton` 上显示。如下图所示:

此外,你还可以设置进度的状态。
TaskbarManager.Instance.SetProgressState(TaskbarProgressBarState.Error);
它将定义进度的不同状态:
- `NoProgress`:禁用 `Progressbar`(进度条)
- `Indeterminate`:显示滚动的 `Progressbar`
- `Normal`:显示正常的绿色 `progressbar`
- `Error`:显示红色的错误 `progressbar`
- `Paused`:显示黄色的暂停 `progressbar`
通过这种方式,你可以广泛使用 `progressbar`。
跳转列表
接下来想到一个重要的事情是 `JumpList`(跳转列表)。`JumpList` 是 Windows 7 任务栏的一个非常重要的功能。你可以使用 `Jumplist` 在右键单击任务栏按钮时定义常用项的快捷方式。假设你在运行应用程序的过程中经常打开计算器。你可以添加自定义的 JumpList 来打开记事本。
除了任务列表,你还可以增强跳转列表来创建自定义类别。让我们看看代码是什么样的:
JumpList list = JumpList.CreateJumpList();
JumpListCustomCategory jcategory = new JumpListCustomCategory("My New Category");
list.ClearAllUserTasks();
string desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
jcategory.AddJumpListItems(new JumpListItem(Path.Combine(desktop, "a.abc")));
list.AddCustomCategories(jcategory);
string systemFolder = Environment.GetFolderPath(Environment.SpecialFolder.System);
//Add links to Tasks
list.AddUserTasks(new JumpListLink(Path.Combine(systemFolder, "notepad.exe"),
"Open Notepad")
{
IconReference = new IconReference(Path.Combine(systemFolder, "notepad.exe"), 0)
});
list.AddUserTasks(new JumpListLink(Path.Combine(systemFolder, "calc.exe"),
"Open Calculator")
{
IconReference = new IconReference(Path.Combine(systemFolder, "calc.exe"), 0)
});
list.AddUserTasks(new JumpListSeparator()); //Acts as a separator
list.AddUserTasks(new JumpListLink(Path.Combine(systemFolder, "mspaint.exe"),
"Open Paint")
{
IconReference = new IconReference(Path.Combine(systemFolder, "mspaint.exe"), 0)
});
只需将上述代码放在 `Form_Shown` 事件中,即可获得自定义的 `Jumplist`。
我们调用 `JumpList.CreateJumpList` 来获取 `JumpList` 对象。`JumpList` 包含菜单项的集合。`Jumplist` 对象有几个部分:
- `User Tasks`:此部分表示常用任务。
- `Recent`:此部分用于显示最近使用的文件。
- `Custom`:你还可以使用自定义类别定义自己的 `Jumplist` 部分。
我们调用 `AddUserTasks` 来添加用户任务。如果你右键单击 `taskbar` 按钮,你会在任务部分看到三个链接。`JumpListLink` 用于定义 `ListItem`(列表项)。我们使用 `Environment.GetFolderPath` 来传递路径,这可以用来获取特殊文件夹路径,并定义链接。`JumpListLink` 的 `IconReference` 属性将决定显示在链接旁边的图标。我们还可以使用 `JumpListSeparator` 来在 `Jumplist` 中生成菜单分隔符项。
要定义自定义类别,我们创建一个 `JumpListCustomCategory` 对象并调用 `AddJumpListItems`,或者要定义到最近列表,我们调用 `Jumplist` 对象的 `AddToRecent` 方法。
注意:对于 `AddToRecent` 和 `JumpListCustomCategory`,你需要先将你的应用程序注册到你正在使用的用于显示文件的自定义扩展。在这里,只有当我将我的应用程序注册到该扩展名时,才能打开 `a.abc`。你可以创建一个安装程序来注册扩展,或者在运行应用程序之前手动完成此操作。
缩略图和标签式缩略图
当你将鼠标悬停在按钮上时,会创建 `Thumbnails`(缩略图)和 `TabbedThumbnails`(标签式缩略图)。在窗体中放置一个 `picturebox`,并在 `Form_Shown` 事件中调用此代码,即可看到缩略图已被创建。
例如,我这样写:
TaskbarManager.Instance.TabbedThumbnail.SetThumbnailClip(this.Handle, New Rectangle
(pictureBox1.Location, pictureBox1.Size));
这将生成 `picturebox` 中显示的图像的 `Thumbnail`。`SetThumnailClip` 用于在 `Taskbar` 的 `Thumbnail` 部分设置图像的 `thumbnail` 预览。请注意,你无法看到你选择的 `Image`,只能看到一个与图片大小相同的矩形。你可以生成实际的图片并在此处显示。
工具栏按钮也可以轻松添加到 `Thumbnail` 上。你可以使用 `ThumbnailToolbarButton` 来为 `Thumbnail` 预览部分定义自定义 `Toolbar` 按钮。在 `Form_Shown` 事件中,如果你添加:
this.thumbButtonNext = new ThumbnailToolbarButton(this.Icon, "Next");
this.thumbButtonNext.Enabled = true;
this.thumbButtonNext.Click +=
new EventHandler<thumbnailbuttonclickedeventargs>(thumbButtonNext_Click);
this.thumbButtonPrev = new ThumbnailToolbarButton(this.Icon, "Prev");
this.thumbButtonPrev.Enabled = true;
this.thumbButtonPrev.Click +=
new EventHandler<thumbnailbuttonclickedeventargs>(thumbButtonPrev_Click);
TaskbarManager.Instance.ThumbnailToolbars.AddButtons(this.Handle,
this.thumbButtonPrev, this.thumbButtonNext);

这将生成两个工具栏按钮,它们具有与之关联的点击处理程序。你可以在提供的示例中看到这一点。标签式缩略图用于当你有多个同一页面的选项卡时。你可以使用 `TaskbarManager.Instance.TabbedThumbnail.SetActiveTab` 来设置活动选项卡的预览居中。你也可以预览其他窗口。
我们就此结束。你可以在网上找到很多关于任务栏功能的文章,所以写太多也没有意义。这个概念非常简单(即使它可能对你来说很有趣),**你可以从这里轻松探索它**。
你可以从 这里 尝试示例工作应用程序。
你可以在 http://www.fishbowlclient.com/ 查看一个基于任务栏功能的很棒的应用程序。
网络列表管理 API
使用 Windows 7 API 代码包,检测网络和获取系统相关网络信息现在变得非常简单。网络 API 提供了一个 `Network` 类,它接口一个网络。`NetworkCollection` 是所有网络的集合。如果你使用网络类型调用 `NetworkListManager.GetNetworks`,它将返回机器上安装的所有网络。
你可能需要使用 `NetworkConnectivityLevels` 来过滤网络。如果你调用 `NetworkListManager.GetNetworks` (`NetworkConnectivityLevels.Connected`),它将返回你的计算机当前连接到的所有网络。
`Network` 对象枚举每个网络的所有属性。
另一方面,`NetworkConnection` 代表与网络的 `Connection`。你可以通过 `Network.Connections` 获取一个网络的 `NetworkConnectionCollection`。你可以轻松地从 `NetworkConnections` 获取 `DomainType`、`ConnectionId` 等信息。
NetworkCollection networks = NetworkListManager.GetNetworks(NetworkConnectivityLevels.All);
foreach (Network n in networks)
{
string name = n.Name;
string desc = n.Description;
string domainType= n.DomainType.ToString();
string isConnected = n.IsConnected.ToString();
string netid =n.NetworkId.ToString();
//You can use the other info too.
NetworkConnectionCollection connections = n.Connections;
foreach (NetworkConnection nc in connections)
{
string connectionid = nc.ConnectionId;
string domainType = nc.DomainType;
string adapterid= nc.AdapterId;
string connectivity= nc.Connectivity;
// You can use this info
}
}
你可以从 这里 尝试示例工作应用程序。
电源管理 API
如果你使用的是笔记本电脑/平板电脑或任何设备来运行你的应用程序,这应该是最令人兴奋的功能。有时,如果你正在处理需要长时间运行进程的服务,你可能有时需要从应用程序中查看电池电量。确实,你可以通过直接 API 调用从你的设备中做到这一点,但使用 Windows API 代码包,这将会比你现在做的更容易。
this.lblPowerSource.Text = PowerManager.PowerSource.ToString();
if (PowerManager.IsBatteryPresent)
{
this.prgBatteryLength.Value = PowerManager.BatteryLifePercent;
}
PowerManager.BatteryLifePercentChanged += new EventHandler
(PowerManager_BatteryLifePercentChanged);
这里,`lblPowerSource` 将显示电源和电压的来源。
void PowerManager_BatteryLifePercentChanged(object sender, EventArgs e)
{
this.prgBatteryLength.Value = PowerManager.BatteryLifePercent;
}
当 `BatteryLife`(电池寿命)改变时,将调用 `EventHandler`。我在这个事件中改变了 `progressbar` 的值。你可以在这个事件中轻松地添加逻辑来减少功耗。`PowerManager` 还提供了一些有用的属性,如 `IsMonitorOn`(显示器是否开启)或 `IsUpsPresent`(UPS 是否存在),以及 `IsMonitorOnChanged`(显示器状态改变)或 `PowerSourceChanged`(电源改变)等事件,这些可能会非常方便。
你可以从 这里 尝试示例工作应用程序。
Windows 7 任务对话框
Windows 任务对话框是旧版 Windows `MessageBox` 的替代品。你们都熟悉 Windows 的 `MessageBox` 及其局限性。引入 `TaskDialog` 是为了显示更高级的 `Message` 版本。让我们看看代码:
TaskDialog taskdlg = new TaskDialog();
TaskDialogStandardButtons button = TaskDialogStandardButtons.Ok |
TaskDialogStandardButtons.Cancel | TaskDialogStandardButtons.Retry;
taskdlg.Icon = TaskDialogStandardIcon.Shield;
taskdlg.Caption = "TaskDialogDemo Application Dialog";
taskdlg.InstructionText = "Text here goes as Instruction";
taskdlg.Text = "Text here goes as Details";
taskdlg.StandardButtons = button;
taskdlg.DetailsExpandedLabel = "Label Shown when content is expanded";
taskdlg.DetailsExpandedText = "Expanded Text";
taskdlg.ExpansionMode = TaskDialogExpandedDetailsLocation.ExpandFooter;
taskdlg.ProgressBar = new TaskDialogProgressBar("Task ProgressBar")
{
Maximum = 100,
Minimum = 0,
State = TaskDialogProgressBarState.Normal,
Value=0
};
taskdlg.Tick += new EventHandler<taskdialogtickeventargs>(taskdlg_Tick);
}
TaskDialogResult res = taskdlg.Show();
这将生成一个增强的 `MessageBox`。`TaskDialog` 按钮通过 `TaskDialogStandardButtons` 传递。你可以添加 `Instruction`(说明)、`Text`(文本)、`Collapsible Panel Text`(可折叠面板文本)和一个 `ProgressBar`,它将响应 `TaskDialog.Tick` 事件。
`TaskDialogProgressBar` 是一个特殊的 `progressbar`,你可以用它来定义 `Maximum`(最大值)、`Minimum`(最小值)、`State`(状态,如 Error、Pause、Normal、Marquee)和 `Value`(值)。

在 `eventhandler` 中,我写道:
void taskdlg_Tick(object sender, TaskDialogTickEventArgs e)
{
TaskDialog dlg = sender as TaskDialog;
if (dlg.ProgressBar.Value == 100)
dlg.ProgressBar.Value = 0;
dlg.ProgressBar.Value += 1;
}
因此,`taskbar progressbar`(任务栏进度条)将无限地进行。你可以通过这种方式很容易地显示长时间运行的进程。
如果你正在运行 WPF 应用程序,请向项目中添加一个清单文件并添加以下内容:
<dependentAssembly>
<assemblyIdentity type="win32"
name="Microsoft.Windows.Common-Controls" version="6.0.0.0"
processorArchitecture="*" publicKeyToken="6595b64144ccf1df"
language="*" />
</dependentAssembly>
将此添加到应用程序的清单文件中将修复讨厌的错误。
TaskDialog feature needs to load Version 6 of Comctl32.dll but a different version is loaded.
你可以从 这里 尝试工作示例应用程序。
一点扩展(使 `TaskDialog` 成为模态对话框)
你可能会想,为什么我们显示的 `TaskDialog` 不是父窗口的模态对话框。我们可以使用以下代码轻松实现这一点:
taskdlg.OwnerWindowHandle = this.Handle;
如果这是一个 WPF 应用程序,你应该这样做:
WindowInteropHelper ohelper = new WindowInteropHelper(this);
TaskDialog.OwnerWindowHandle = ohelper.Handle;
如果你愿意,你还可以使用以下方法为 `ShowDialog` 创建一个扩展方法:
public static class TaskDialogExtension
{
public static TaskDialogResult ShowDialog(this TaskDialog dlg)
{
dlg.OwnerWindowHandle = Form.ActiveForm.Handle;
return dlg.Show();
}
}
只需将该类添加到你的 Windows 应用程序项目中。
传感器平台 API
传感器是 Windows 7 API 的另一个惊人补充。它使你能够感知当前环境并相应地更改你的应用程序。这意味着你的应用程序将根据光线和加速度开始做出反应。例如,你有两种类型的应用程序,一种在光线充足的环境下显示明亮,另一种在光线较暗的环境下显示。使用 `Sensor` API,你可以轻松做到这一点。
`Sensor` API 支持两种类型的 `Sensor`:
环境光传感器 (AmbientLightSensor)
三维加速度计 (Accelerometer3D)
目前,我将讨论 `AmbientLightSensor`。你可以以几乎相同的方式轻松探索 `Accelerometer3D` 传感器。
要使用 `Sensor`,你需要考虑的第一件事是 `SensorManager`。它是一个 `static` 类,用于管理所有已安装的传感器。你可以调用 `GetAllSensors` 来获取所有 `Sensor`,调用 `GetSensorsByTypeId` 来根据传入的通用类型对象过滤所有已安装的可用传感器。你还可以调用 `GetSensorBySensorId` 来通过其 ID 获取确切的传感器。要调用 `AmbientLightSensor`,我们使用 `AmbientLightSensor` 类。首先,在窗体构造函数中调用:
SensorManager.SensorsChanged += new SensorsChangedEventHandler(
SensorManager_SensorsChanged);
这将确保窗体中显示的数据在传感器更改时得到反映。当 `System` 传感器列表更改时,会发生此事件。这对于你的应用程序来说不是强制性的。
public void SensorManager_SensorsChanged(SensorsChangedEventArgs change)
{
BeginInvoke(new MethodInvoker(delegate
{
PopulateData();
}));
}
请注意,`SensorsChanged` 事件不在 UI 线程上触发,因此你不能直接调用 `PopulateData`,而是需要使用 `MethodInvoker` 调用该方法,因为这是向 UI 线程进行封送的主要方法。
或者,也可以使用 `SynchronizationContext` 调用 UI 线程的新概念。你可以使用:
public void SensorManager_SensorsChanged(SensorsChangedEventArgs change)
{
SynchronizationContext context = SynchronizationContext.Current;
if(context == null)
context = new SynchronizationContext();
context.Send(new SendOrPostCallback( (s) => PopulateData()), null);
}
如果你想了解更多关于 `SynchronizationContext` 的信息,请在此 阅读。
Populate Data 的主要思想是显示来自可用 `Sensor` 的光强度。我们可以轻松使用 `CurrentLuminousIntensity.Intensity`,它返回当前光强度。
this.currentSensor = new Guid("b4133ea3-c284-4626-a6e3-10bfaf50299f");
AmbientLightSensor sensor = SensorManager.GetSensorBySensorId<ambientlightsensor>(this.currentSensor);
lblSensor.Text = "SensorId = " + sensor.SensorId.ToString();
float current = sensor.CurrentLuminousIntensity.Intensity;
prgSensorProgress.Value = Math.Min((int)current, prgSensorProgress.Maximum);
// Set up automatic data report handling.
sensor.AutoUpdateDataReport = true;
sensor.DataReportChanged += new DataReportChangedEventHandler(DataReportChanged);
`DataReportChanged` 事件仅在当前传感器强度改变时触发。因此,我们使用它来重新初始化进度条的值。
public void DataReportChanged(Sensor sender, EventArgs e)
{
AmbientLightSensor als = sender as AmbientLightSensor;
BeginInvoke(new MethodInvoker(delegate
{
// report data (clamp value to progress bar maximum )
float current = als.CurrentLuminousIntensity.Intensity;
prgSensorProgress.Value = Math.Min((int)current, prgSensorProgress.Maximum);
}));
}
同样,事件在非 UI 线程上调用,因此你需要使用 `BeginInvoke` 来更改 `Progressbar` 的值。

如果你的机器上没有安装任何传感器,你可以轻松找到一个模拟光传感器,如 这里 所述。
要尝试示例,请从 这里 下载。
为 Windows 7 修改现有应用程序的步骤
在一篇文章中讨论所有增强功能非常困难,所以我们不把这篇文章继续写下去,而是用 Windows 7 的功能来美化一个现有的 WPF 应用程序。我已经制作了一个应用程序,我将在本文中使用它。该应用程序是一个图像管理工具。我将用 Windows 7 的功能来替换这个应用程序。
文章的主要用途是图像管理。它允许你添加一些图像到它本身,并将这些文件保存到一个扩展名为 pkg 的相册中。除此之外,该应用程序还能够递归地在数据库中搜索图像。
当你打开窗口时,“**浏览**”和“**搜索**”按钮会启用。“**浏览**”按钮允许你添加一个包文件,或者你可以在文件打开对话框中选择一个图像文件来添加单个图像文件。选择文件后,将加载文件夹的内容或相册中定义的文件。你可以更改每个注释的注释,然后再次将其保存到包中。“搜索”按钮允许你在指定文件夹内递归地搜索图像。
在我们将其增强到 Windows 7 之前,我们首先需要检查当前操作系统。为了做到这一点,我们添加 _App.xaml_ 并处理 `Application.Startup` 事件。
if (!CoreHelpers.RunningOnWin7)
{
MessageBox.Show("You are not running in Windows 7.
You need windows 7 to run this application",
"Application Error", MessageBoxButton.OK, MessageBoxImage.Error);
Environment.Exit(0);
}
上面的命令将确保操作系统是 Windows 7,否则应用程序将在显示 `messagebox` 后停止运行。
要开始编写代码,我添加了 API 代码包中的 `Core` 和 `Shell` 类库,并为它们添加了引用。以下是步骤:
- 更改公共文件对话框:`Microsoft.Win32` 的 `OpenFileDialog` 和 `SaveFileDialog` 非常僵化。首先,我需要摆脱它们,并包含 `APICodePack` 附带的对话框。我也可以使用 `ExplorerBrowser` 来设计一个全新的窗体并将 explorer 放在里面,但我宁愿在这里使用 `WindowsAPICodePack.Dialogs`。代码如下:
CommonOpenFileDialog fdlg = new CommonOpenFileDialog("Choose an Album or an Image File"); fdlg.Filters.Add(new CommonFileDialogFilter("Picture Albums","*.pkg")); fdlg.Filters.Add(new CommonFileDialogFilter("Image Files", "*.jpg,*.gif,*.png,*.bmp")); fdlg.EnsurePathExists=true; fdlg.InitialDirectory= KnownFolders.Documents.Path; fdlg.IsFolderPicker=false; if(fdlg.ShowDialog() == CommonFileDialogResult.OK) { // ... }
这将打开相同的 `OpenFileDialog`,但具有更多的灵活性和更简洁的方法。类似地,我也用 `CommonSaveFileDialog` 更改了 `SaveFileDialog`。你可能已经注意到这里的一个地方,我将 `filedialog.InitialDirectory` 设置为 `KnownFolders.Documents`。实际上,`KnownFolders` 只是 `APICodePack` 中定义的一个枚举,它允许你访问所有常用文件夹,如 `Documents`、`Computer`、`ControlPanel`、`Desktop`、`Music`、`Pictures`、`Profiles` 等。
- 用 TaskDialog 替换 MessageBox:另一个可能非常有用的简单事情是 `TaskDialog`。`TaskDialog`(如前所述,只是普通 `messagebox` 的替代品,但具有许多内置的灵活性)。因此,我将用 `TaskDialog` 替换 `MessageBox`,示例如下:
TaskDialog.Show("Note: It stores only metadata related to the Image, Renaming the original image will affect it.", "Saved Successfully to Disk", "Operation Successful");
- 应用程序重启恢复: 要添加应用程序重启恢复,我们采用与前面讨论相同的方法。我已将应用程序注册为进行 `Restart`(重启)和 `Recovery`(恢复)。我将通过检查传递的命令行参数来检查恢复。
string[] args = System.Environment.GetCommandLineArgs(); if (args.Length > 1 && args[1].Equals ("/recovery", StringComparison.InvariantCultureIgnoreCase)) { StartRecovery("/recovery"); }
- 任务栏增强:最后,我必须为应用程序添加一些任务栏增强功能。让我们添加所选图像的缩略图视图,并允许用户在图像之间导航。为此,我添加了两个按钮:
private ThumbnailToolbarButton _PreviousButton= new ThumbnailToolbarButton(new System.Drawing.Icon("prevArrow.ico"), "Previous Image"); private ThumbnailToolbarButton _NextButton= new ThumbnailToolbarButton(new System.Drawing.Icon("nextArrow.ico"), "Next Image");
按钮将添加到 `ThumbnailToolbar`。为了使其与应用程序交互,让我们操作 `Window.Loaded` 事件并编写一些代码:
this._PreviousButton.Click += this.ButtonPrevious_Click; this._NextButton.Click += this.ButtonNext_Click; System.Drawing.Rectangle clippingRect = new System.Drawing.Rectangle(new System.Drawing.Point(400, 30), new System.Drawing.Size(Convert.ToInt32(Imgdisplay.ActualWidth), Convert.ToInt32(Imgdisplay.ActualHeight))); WindowInteropHelper interopHelper = new WindowInteropHelper(this); IntPtr handle = interopHelper.Handle; TaskbarManager.Instance.TabbedThumbnail.SetThumbnailClip(handle, clippingRect); TaskbarManager.Instance.ThumbnailToolbars.AddButtons (handle, this._PreviousButton, this._NextButton);
这样,我们在工具栏中添加了两个 `Button`,并在缩略图视图中添加了图像的剪辑。`eventhandler` 也应该添加到按钮以处理事件。
这样,我们新的示例应用程序终于准备就绪了。而不是更改整个应用程序并为运行低于 Windows 7 的用户退出应用程序,你也可以在每一步都进行检查,以确保你的应用程序在所有操作系统上都能完美运行。
- 你可以从 这里 下载示例应用程序。
注意:`Taskbar Thumbnail`(任务栏缩略图)预览在某些版本的 Windows 7 以及在 VPC 中运行的 Windows 7 中可能无法正常工作。
参考文献
- 适用于 Microsoft .NET Framework 的 Windows API 代码包
- 使用 Windows 代码包增强你的应用程序
- Windows 任务栏 API
- 使用 API 代码包创建任务栏跳转列表
- Windows API 代码包的 DirectX 功能
下载示例应用程序
结论
我试图给出类的最基本用法,以便它能够使开发人员在创建应用程序时受益。还有许多其他功能,我在这里无法讨论。如果你想了解更多,你可以轻松尝试 API 代码包中提供的示例。
历史记录
- 2009 年 12 月 28 日:首次发布
- 2009 年 12 月 30 日:第二次发布
- 2010 年 1 月 3 日:第三次发布
- 2010 年 1 月 24 日:第四次发布
展示了如何将普通应用程序转换为添加新功能。
最后,我不是 Windows 开发人员,所以如果你发现代码有问题,请告诉我,也为了方便大家。
感谢阅读,欢迎评论。