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

WPF:将我们的应用程序与 Windows 7 任务栏集成(II)

2010 年 8 月 3 日

CPOL

7分钟阅读

viewsIcon

27864

downloadIcon

490

让您的用户通过 Windows 7 任务栏的新功能与您的应用程序进行交互。

引言

在上篇文章中,我们讨论了如何在 Windows 7 中将我们的应用程序与任务栏集成(您可以在这里找到它),我们讨论了 Windows 7 任务栏如何通过使用图标叠加和进度条来向用户传达信息。

任何程序都需要双向通信,一方面向用户传达信息,另一方面用户向我们的应用程序提供信息以供处理。既然我们已经设法让我们的用户从任务栏获得信息的方式适应 Windows 7,那么我们现在可以轻松直观地让我们的用户从任务栏向我们传达信息。

为此,在本文中,我们将讨论 JumpList 和 Thumbnail Toolbars。

  • Jumplist: Jumplist 是指向我们应用程序的各个部分的快捷方式,当您右键单击任务栏中的应用程序图标时会出现。我们可以让我们的应用程序直接跳转到特定窗口,即使它尚未启动。
  • Thumbnail Toolbars: 当您将鼠标悬停在活动应用程序的图标上时,Windows 7 会提供该应用程序窗口的预览。使用 Thumbnail Toolbars,我们可以为该视图添加按钮,这些按钮可以在我们的应用程序中执行。

.NET 3.5 vs .NET 4

为了访问所有这些功能,.NET 3.5 只有一种方法:与非托管 Win32 API 互操作(如有关电源管理的文章)。然而,.NET 4 将 Windows 7 任务栏的功能直接融入框架本身,因此“使用和享受”这些功能更加容易。所以本文中的代码仅适用于 .NET 4。

开始吧

让我们开始吧。您必须首先创建一个新的 WPF 应用程序项目(文件 > 新建 > 项目)。一旦设置好,我们将设计主屏幕文件MainWindow.xaml

我在本应用程序中使用的样式可在下载文件Application.xaml 中找到。如果您对如何使用/创建样式有疑问,请参阅我关于此主题的两篇文章:这里这里

好了,为了开始使用任务栏,我们向 XAML 中添加一个类型为 TaskbarItemInfo 的对象。

<Window.TaskbarItemInfo>
    <TaskbarItemInfo/>
</Window.TaskbarItemInfo>

这样,我们就可以轻松快速地访问 Windows 7 任务栏的许多属性。

JumpList

Jumplist.PNG

我们将开始处理 JumpList。我们首先要做的就是打开application.xaml 代码文件,并为 Startup 事件添加一个新的事件处理程序。

Private Sub Application_Startup(ByVal sender As Object, 
                                ByVal e As System.Windows.StartupEventArgs) 
                                Handles Me.Startup
End Sub

Jumplist 中的元素与我们的应用程序通信的方式是使用传递给可执行文件的参数来启动。因此,在 Startup 事件中,我们将执行两项工作:首先检查我们是否收到了参数并运行关联的代码,然后在该事件中,我们将创建我们的列表并将其通知应用程序。

为了处理传递给应用程序的参数,我们将使用事件的 e 变量的 Args 属性,使用 Select Case 块来执行,如下所示:

If e.Args.Count > 0 Then
    Select Case e.Args(0)
        Case "update"
            MessageBox.Show("No updates needed")
        Case "searchclient"
            MessageBox.Show("You have picked Clients")
        Case "searchinvoice"
            MessageBox.Show("You have picked Invoices")
    End Select
End If

您可以看到,这非常简单。在创建 JumpList 时,每个元素都有一个关联的参数(updatesearchinvoice searchclient)。选择列表中的一个项目时,该元素会运行您的应用程序,发送我们关联的参数。

现在我们创建 JumpList 的元素。为此,我们将使用 Shell 命名空间中的 JumpTask 对象。

'Create our Jumplist Tasks
Dim SearchUpdates As New Shell.JumpTask
SearchUpdates.Title = "Search for Updates"
SearchUpdates.Arguments = "update"
SearchUpdates.Description = "Find new updates for the application"
SearchUpdates.CustomCategory = "Management"
SearchUpdates.IconResourcePath = Assembly.GetEntryAssembly().CodeBase
SearchUpdates.ApplicationPath = Assembly.GetEntryAssembly().CodeBase
Dim SearchClient As New Shell.JumpTask
SearchClient.Title = "Search clients"
SearchClient.Arguments = "searchclient"
SearchClient.Description = "Search the Clients database"
SearchClient.CustomCategory = "Clients"
SearchClient.IconResourcePath = Assembly.GetEntryAssembly().CodeBase
SearchClient.ApplicationPath = Assembly.GetEntryAssembly().CodeBase
Dim SearchInvoice As New Shell.JumpTask
SearchInvoice.Title = "Search Invoice"
SearchInvoice.Arguments = "searchinvoice"
SearchInvoice.Description = "Search the Invoices database"
SearchInvoice.CustomCategory = "Invoices"
SearchInvoice.IconResourcePath = Assembly.GetEntryAssembly().CodeBase
SearchInvoice.ApplicationPath = Assembly.GetEntryAssembly().CodeBase

只需定义每个 JumpTask 的功能,现在我们只需将它们添加到 JumpList 中。

Dim List As New Shell.JumpList
List.JumpItems.Add(SearchUpdates)
List.JumpItems.Add(SearchClient)
List.JumpItems.Add(SearchInvoice)

最后,我们必须告诉系统将此列表与您的应用程序关联,使用 JumpList 类的 SetJumpList 方法。

Shell.JumpList.SetJumpList(Application.Current, List)

尽管这段代码将在每次启动应用程序时运行,但系统永远不会重复 JumpList 元素。每当我们传递一个 JumpList 时,它都会更新分配给我们的应用程序的元素。如果我们进行了更改、创建了新项目或删除了不再存在的项目。

通过这一点,如果您运行应用程序并在任务栏图标上按右键,您将看到我们创建的元素。如果您选择其中一个,您将看到相应的消息出现,并打开应用程序的新实例。

Jumplist2.PNG

总的来说,为我们的应用程序提供 JumpList 并不复杂,但最终它可以为我们带来许多好处。当我们可以通过两次单击提供更多常用操作并直接启动应用程序到用户所需位置时,用户如何才能到达多个窗口以进行数据查询或更新?如果您仔细想想,肯定能想到成千上万种您非常乐于拥有此系统的情况。至少在我个人的经验中,这是 Windows 7 中我发现最有用的功能之一。

缩略图工具栏

Toolbar.PNG

这样,用户与我们的应用程序的交互就与我们上一篇文章的内容无缝结合,在那篇文章中,我们解释了如何告知用户我们应用程序的进度,但仍然显示相同的窗口。好的,通过 Thumbnail Toolbars 的支持,在收到此信息后,用户可以通过执行应用程序中的命令来响应,而无需最大化窗口。

我们首先要做的就是使用 DrawingImage 类作为我们窗口的资源来创建按钮的图像。

<Window.Resources>
    <DrawingImage x:Key="IconUpdate">
        <DrawingImage.Drawing>
            <ImageDrawing Rect="0,0,24,24" ImageSource="/Images/update.png" />
        </DrawingImage.Drawing>
    </DrawingImage>
    <DrawingImage x:Key="IconClient">
        <DrawingImage.Drawing>
            <ImageDrawing Rect="0,0,24,24" ImageSource="/Images/client.png" />
        </DrawingImage.Drawing>
    </DrawingImage>
    <DrawingImage x:Key="IconInvoice">
        <DrawingImage.Drawing>
            <ImageDrawing Rect="0,0,24,24" ImageSource="/Images/invoice.png" />
        </DrawingImage.Drawing>
    </DrawingImage>
</Window.Resources>

我们将用于创建按钮的类是 TaskBarItemInfo.ThumbButtonInfo

<Window.TaskbarItemInfo>
    <TaskbarItemInfo>
        <TaskbarItemInfo.ThumbButtonInfos>
            <ThumbButtonInfo x:Name="btnUpdate"
                             ImageSource="{StaticResource IconUpdate}"
                             Description="Find updates for the application"
                             IsBackgroundVisible="True">
            </ThumbButtonInfo>
            <ThumbButtonInfo x:Name="btnClient"
                             ImageSource="{StaticResource IconClient}"
                             Description="Search Clients"
                             IsBackgroundVisible="True">
            </ThumbButtonInfo>
            <ThumbButtonInfo x:Name="btnInvoice"
                             ImageSource="{StaticResource IconInvoice}"
                             Description="Search Invoices"
                             IsBackgroundVisible="True">
            </ThumbButtonInfo>
        </TaskbarItemInfo.ThumbButtonInfos>
    </TaskbarItemInfo>
</Window.TaskbarItemInfo>

ThumbButtonInfo 类有几个属性,可以让我们自定义按钮的外观。

  • Description:指示当鼠标悬停在按钮上时显示的文本。
  • IsInteractive:此属性允许您以两种方式使用按钮。
    • True:按钮的行为像一个普通按钮,这是默认行为。
    • False:交互式按钮仅显示给用户,不响应用户的操作。
  • IsBackgroundVisible:指示按钮是否通过将鼠标悬停在其上方来高亮显示,默认值为 True
  • DismissWhenClicked:如果我们将其设置为 True,当您按下按钮时,缩略图将关闭。如果为 False,则直到您将鼠标离开任务栏图标,缩略图才会保持打开状态。默认值为 False

我们已经创建了按钮。如果您运行应用程序并将鼠标悬停在任务栏图标上,您会看到我们创建的三个按钮出现,但如果您点击它们,则什么也不会发生。

现在我们设置按钮的行为,可以通过两种方式完成:使用事件,就像其他任何按钮一样,或者使用命令。

这两种方法可以完成相同的工作,但使用命令可能更可取,因为通常这些按钮与其他按钮(位于主应用程序工具栏或菜单选项上)相同,使用相同的代码可以使用命令将两者关联起来。我将稍微详细地解释这两种情况。

使用事件

ThumbnailButtonInfo 与事件一起工作非常简单,与您应用程序中的其他控件完全一样,只需从 XAML 添加我们响应的事件。

<Window.TaskbarItemInfo>
    <TaskbarItemInfo>
        <TaskbarItemInfo.ThumbButtonInfos>
            <ThumbButtonInfo x:Name="btnUpdate"
                             ImageSource="{StaticResource IconUpdate}"
                             Description="Find updates for the application"
                             IsBackgroundVisible="True"
        Click="btnUpdate_Click">
            </ThumbButtonInfo>
            <ThumbButtonInfo x:Name="btnClient"
                             ImageSource="{StaticResource IconClient}"
                             Description="Search Clients"
                             IsBackgroundVisible="True"
        Click="btnClient_Click">
            </ThumbButtonInfo>
            <ThumbButtonInfo x:Name="btnInvoice"
                             ImageSource="{StaticResource IconInvoice}"
                             Description="Search Invoices"
                             IsBackgroundVisible="True"
        Click="btnInvoice_Click">
            </ThumbButtonInfo>
        </TaskbarItemInfo.ThumbButtonInfos>
    </TaskbarItemInfo>
</Window.TaskbarItemInfo>

如您所见,我们在每个按钮上都添加了一个点击事件,现在在代码中编写每个事件处理程序所需的代码。

Private Sub btnUpdate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
    MessageBox.Show("Click on Update using events")
End Sub
Private Sub btnClient_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
    MessageBox.Show("Click on Clients using events")
End Sub
Private Sub btnInvoice_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
    MessageBox.Show("Click on invoice using events")
End Sub

通过这一点,如果我们运行我们的应用程序并点击按钮,将出现相应的 messagebox

Toolbar2.PNG

使用命令

这种方法涉及的工作量稍多一些,但它更代表应用程序实际会做什么。第一步是为每个按钮创建一个新类。

comandos1.PNG

如您所见,我们为我们执行的每个操作创建了一个类:ClientInvoice Update。这些类必须实现 ICommand 接口才能在我们的应用程序中用作命令。

'UpdateCommand.vb
Public Class UpdateCommand
    Implements ICommand
    Public Function CanExecute(ByVal parameter As Object) As Boolean 
     Implements ICommand.CanExecute
        'TODO:Test if you can execute the command.
        Return True
    End Function
    Public Event CanExecuteChanged(ByVal sender As Object, ByVal e As System.EventArgs) 
     Implements ICommand.CanExecuteChanged
    Public Sub Execute(ByVal parameter As Object) Implements ICommand.Execute
        MessageBox.Show("Click on update button using Commands")
    End Sub
End Class
'ClientCommand.vb
Public Class ClientCommand
    Implements ICommand
    Public Function CanExecute(ByVal parameter As Object) As Boolean 
     Implements ICommand.CanExecute
        'TODO:Test if you can execute the command.
        Return True
    End Function
    Public Event CanExecuteChanged(ByVal sender As Object, ByVal e As System.EventArgs) 
     Implements ICommand.CanExecuteChanged
    Public Sub Execute(ByVal parameter As Object) Implements ICommand.Execute
        MessageBox.Show("Click on Clients Buttons using Commands")
    End Sub
End Class
'InvoiceCommand.vb
Public Class InvoiceCommand
    Implements ICommand
    Public Function CanExecute(ByVal parameter As Object) As Boolean 
     Implements ICommand.CanExecute
        'TODO:Test if you can execute the command.
        Return True
    End Function
    Public Event CanExecuteChanged(ByVal sender As Object, ByVal e As System.EventArgs) 
     Implements ICommand.CanExecuteChanged
    Public Sub Execute(ByVal parameter As Object) Implements ICommand.Execute
        MessageBox.Show("Click on Invoice Button Using Commands")
    End Sub
End Class

接下来,我们需要做的是有一个通用位置来公开我们的命令,以便我们可以使用 ViewModel。向您的项目添加一个新的类文件,名为 ViewModel ,并为其提供以下代码:

Public Class ViewModel
    Private _UpdateCommand As UpdateCommand = New UpdateCommand()
    Private _ClientCommand As ClientCommand = New ClientCommand()
    Private _InvoiceCommand As InvoiceCommand = New InvoiceCommand()
    Public ReadOnly Property UpdateCommand As ICommand
        Get
            Return _UpdateCommand
        End Get
    End Property
    Public ReadOnly Property ClientCommand As ICommand
        Get
            Return _ClientCommand
        End Get
    End Property
    Public ReadOnly Property InvoiceCommand As ICommand
        Get
            Return _InvoiceCommand
        End Get
    End Property
End Class

我们的 ViewModel 只是将我们命令类型的 public 属性公开给视图层(在这种情况下是 XAML)。因此,我们只需在 XAML 中引用此 ViewModel 和我们的 DataContext

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:viewModel="clr-namespace:WPF_JumpList_And_Thumbnail_Toolbars"
    Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <viewModel:ViewModel></viewModel:ViewModel>
    </Window.DataContext>
</Window>

最后,我们只需要将我们的按钮与它们各自的命令链接起来。为此,我们将使用每个 ThumbButtonInfoCommand 属性。

<ThumbButtonInfo x:Name="btnUpdate"
                 ImageSource="{StaticResource IconUpdate}"
                 Description="Comprueba actualizaciones"
                 IsBackgroundVisible="True"
                 Command="{Binding UpdateCommand}">
</ThumbButtonInfo>
<ThumbButtonInfo x:Name="btnClient"
                 ImageSource="{StaticResource IconClient}"
                 Description="Ver los clientes"
                 IsBackgroundVisible="True"
                 Command="{Binding ClientCommand}">
</ThumbButtonInfo><ThumbButtonInfo x:Name="btnInvoice"
                 ImageSource="{StaticResource IconInvoice}"
                 Description="Ver las facturas"
                 IsBackgroundVisible="True"
                 Command="{Binding InvoiceCommnad}">
</ThumbButtonInfo>

正如您所看到的,我们只是在绑定到我们的命令。如果您再次执行应用程序并点击一个按钮,您可以看到效果与使用事件时相同,只是这次我们的代码更具可重用性,也更有条理。它可以跨多个窗口或控件共享相同的命令,并保持相同的功能。

Commandos2.PNG

历史

  • 2010 年 8 月 3 日 - 初始版本
© . All rights reserved.