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

Silverlight 4:使用新的 COM API 访问 Windows 7 任务栏

2010年6月16日

CPOL

10分钟阅读

viewsIcon

86431

downloadIcon

1033

Silverlight 4 能够通过 COM API 与任何其他应用程序进行通信。阅读本文后,您将能够直接从 Silverlight 4 浏览器外应用程序将任何 Windows 应用程序固定/取消固定到 Windows 7 任务栏。

目录

引言

微软去年发布了 Windows 7,它具有许多功能,包括漂亮的 UI。在这些功能中,最用户友好的功能之一是将应用程序固定/取消固定到任务栏。您可以开发 WPF 或 Windows Forms 应用程序,并在其中实现此功能。但您知道 Silverlight 也可以做到这一点吗?是的,Silverlight 4 能够通过 COM API 与任何其他应用程序进行通信。您可以阅读我之前的一篇文章 [Silverlight 4:使用 COM 对象与 Excel 进行互操作]。

那么,我如何在我的 Silverlight 4 应用程序中开发这样的功能呢?在这里,我将一步一步地进行描述,以便您了解该功能。阅读本文后,您将能够直接从 Silverlight 4 浏览器外应用程序将任何 Windows 应用程序固定/取消固定到 Windows 7 任务栏。

背景

在 Windows 7 操作系统中,您可以固定任何应用程序以方便访问,就像以前的快速启动工具栏一样。一旦您右键单击任务栏图标,您就会在上下文菜单中看到一些快速任务,就像您日常活动一样。有一个选项可以将应用程序固定/取消固定到任务栏。固定后,您可以直接从任务栏打开该应用程序。请看下面的截图

pic_01.png

已固定但未打开的应用程序将显示为扁平图标,而已打开的应用程序(无论是否已固定)将具有矩形边框和一些闪亮背景,如下图所示

当您右键单击任务栏上未固定的应用程序时,您会看到一个菜单,其中有一个选项可以将该程序固定到任务栏,如下所示

pic_02.png

一旦固定到任务栏,如果您再次右键单击图标,您会发现“将此程序固定到任务栏”菜单项已更改为“将此程序从任务栏取消固定”。请看下图

pic_03.png

Silverlight 4 具有通过 COM API 访问任务栏的出色功能。在我之前的文章中,我演示了另一项功能,称为“使用 Silverlight 4 COM API 访问 Microsoft Excel 应用程序”。在本文中,我将演示如何访问任务栏。请阅读全文并提供您的反馈/建议。

先决条件

要开发这个简单的应用程序,您需要在开发环境中安装以下工具

  • Windows 7 操作系统(运行应用程序所需)
  • Visual Studio 2010
  • 适用于 Visual Studio 2010 的 Silverlight 4 工具

请记住,Silverlight 4 应用程序只能在 Visual Studio 2010 中开发。因此,如果您在 PC 上安装了 Visual Studio 2008,可以并排安装 Visual Studio 2010 来探索 Silverlight 4。

入门

如果您的开发环境已准备就绪,那么我们可以继续创建一个新的 Silverlight 应用程序项目。在本文档的最后,我们将能够在浏览器内运行我们的第一个 Silverlight 应用程序。

  1. 打开您的 Visual Studio 2010 IDE
  2. 选择“文件”>“新建项目”或直接按 CTRL + SHIFT + N 打开“新建项目”对话框
  3. 展开“Visual C#”节点,然后转到子节点“Silverlight”
  4. 在右侧窗格中选择“Silverlight 应用程序”
  5. 选择合适的目录来存储您的应用程序(例如,“D:\Sample Apps\”)
  6. 现在为您的项目输入一个合适的名称(称之为:“Silverlight4.Interoperability.Taskbar”)
  7. 从顶部的组合框中选择 .NET Framework 版本(我使用的是 .NET Framework 4.0)
  8. 单击“确定”继续
  9. 在下一个对话框中,确保选择了“在新的网站中承载 Silverlight 应用程序”选项
  10. 选择“Silverlight 4”作为 Silverlight 版本,然后点击“确定”

稍等片刻,Visual Studio 将为您创建一个 Silverlight 解决方案,其中包含一个 Silverlight 项目和一个用于承载 Silverlight 应用程序的 Web 应用程序项目。在您的 Silverlight 项目中,您会找到 IDE 模板已为您创建的“MainPage.xaml”和“App.xaml”文件。

完成项目设置后,您需要向 Silverlight 项目添加程序集引用。我们将使用“dynamic”关键字,为此我们需要添加“Microsoft.CSharp”程序集引用。

  1. 右键单击 Silverlight 项目中的“Reference”文件夹,然后从上下文菜单中选择“Add Reference”菜单项。

    pic_04.png

  2. 这将打开屏幕上的“Add Reference”对话框。滚动窗口在 .NET 选项卡中查找名为“Microsoft.CSharp”的程序集。选中它,然后单击“OK”。这将把 Microsoft.CSharp 程序集引用添加到您的 Silverlight 项目中。添加后,您的项目将支持动态变量声明。

    pic_05.png

配置浏览器外设置

完成 Silverlight 项目设置后,我们就可以为应用程序实现自定义的浏览器外窗口了。您可以从 CodeProject 阅读有关创建 Silverlight 4 自定义浏览器外窗口的完整文章。

设计完浏览器外窗口后,转到 Silverlight 项目的属性。在 Silverlight 窗格中,确保您使用的是“Silverlight 4”作为目标版本。然后选择“Enable running application out of browser”(启用浏览器外运行应用程序),这将使“Out-of-Browser Settings…”(浏览器外设置…)按钮可用。单击它以获取更多设置。

pic_06.png

在“Settings”(设置)对话框窗口中,选择“Show install menu”(显示安装菜单),这将会在 Silverlight 上下文菜单中创建一个菜单项。当您运行应用程序并右键单击应用程序时,您会在菜单中看到一个“Install”(安装)菜单项。我稍后会回到这一部分。

pic_07.png

现在,勾选“Require elevated trust when running outside the browser”(运行在浏览器外时需要提升的信任)以及如上所示,并将“Window Style”(窗口样式)选择为“No Border”(无边框)。完成这些设置后,单击“OK”保存配置。您也可以在此处更改“Window Title”(窗口标题)、“Size”(大小)和其他可用选项。

设计 XAML 页面

让我们开始设计 XAML 页面来展示我们的示例。在我们的演示示例中,我们将添加三个 TextBox 控件和三个 Buttons 。当应用程序启动时,它将在 TextBox 中填充我们要固定/取消固定到 Windows 7 任务栏的文件的位置(例如,Wordpad、Paint 和 Calculator)。每个 Textbox 旁边都有一个按钮。单击该按钮,它将把应用程序固定到任务栏(前提是应用程序尚未被固定)。如果应用程序已被固定到任务栏,它将从那里取消固定。

以下是我的示例的完整 XAML 代码

<UserControl x:Class="Silverlight4.Interoperability.Taskbar.MainPage"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d">
    <Border BorderBrush="Black"
            Height="177"
            Width="600">
        <Grid x:Name="LayoutRoot"
              Background="White">
            <Grid.RowDefinitions>
                <RowDefinition Height="31" />
                <RowDefinition />
            </Grid.RowDefinitions>

            <Border BorderBrush="Black"
                    CornerRadius="10,10,0,0">
                <Border.Background>
                    <LinearGradientBrush EndPoint="0.5,1"
                                         StartPoint="0.5,0">
                        <GradientStop Color="Black" />
                        <GradientStop Color="Black"
                                      Offset="1" />
                    </LinearGradientBrush>
                </Border.Background>
            </Border>
            <Border BorderBrush="Black"
                    CornerRadius="10,10,0,0"
                    MouseLeftButtonDown="Border_MouseLeftButtonDown"
                    Margin="2,2,2,0">
                <Border.Background>
                    <LinearGradientBrush EndPoint="0.5,1"
                                         StartPoint="0.5,0">
                        <GradientStop Color="White" />
                        <GradientStop Color="Transparent"
                                      Offset="0.69" />
                    </LinearGradientBrush>
                </Border.Background>
                <Border x:Name="brdClose"
                        BorderBrush="#FFE9D710"
                        BorderThickness="1"
                        HorizontalAlignment="Right"
                        MouseLeftButtonDown="brdClose_MouseLeftButtonDown"
                        Margin="0,5,8,6"
                        Width="22"
                        Height="18"
                        Background="#FF700C0C">
                    <TextBlock TextWrapping="Wrap"
                               Text="X"
                               HorizontalAlignment="Center"
                               VerticalAlignment="Center"
                               FontSize="13.333"
                               Foreground="White"
                               IsHitTestVisible="False" />
                </Border>
            </Border>
            <Border BorderBrush="Black"
                    BorderThickness="1"
                    Grid.Row="1" />
            <TextBlock HorizontalAlignment="Left"
                       Margin="9,7,0,8"
                       TextWrapping="Wrap"
                       Text="Windows 7 Taskbar Demo"
                       IsHitTestVisible="False"
                       d:LayoutOverrides="Height"
                       FontWeight="Bold"
                       FontSize="13.333"
                       Foreground="White" />
            <TextBox x:Name="txtWordpad"
                     Height="22"
                     Margin="8,8,91,0"
                     Grid.Row="1"
                     TextWrapping="Wrap"
                     VerticalAlignment="Top"
                     IsReadOnly="True"
                     Background="White" />
            <Button x:Name="btnWordpad"
                    Content="Pin/Unpin"
                    Height="25"
                    Click="btnWordpad_Click"
                    Grid.Row="1"
                    Width="80"
                    Margin="0,6,6,0"
                    HorizontalAlignment="Right"
                    VerticalAlignment="Top"
                    d:LayoutOverrides="Width, Height"
                    Foreground="White" />
            <TextBox x:Name="txtPaint"
                     Height="22"
                     Margin="8,36,91,0"
                     Grid.Row="1"
                     TextWrapping="Wrap"
                     VerticalAlignment="Top"
                     IsReadOnly="True"
                     Background="White" />
            <Button x:Name="btnPaint"
                    Content="Pin/Unpin"
                    Height="25"
                    Click="btnPaint_Click"
                    Grid.Row="1"
                    Width="80"
                    Margin="0,34,6,0"
                    HorizontalAlignment="Right"
                    VerticalAlignment="Top"
                    d:LayoutOverrides="Width, Height"
                    Foreground="White" />
            <TextBox x:Name="txtCalculator"
                     Margin="8,66,91,58"
                     Grid.Row="1"
                     TextWrapping="Wrap"
                     IsReadOnly="True"
                     Background="White" />
            <Button x:Name="btnCalculator"
                    Content="Pin/Unpin"
                    Height="25"
                    Click="btnCalculator_Click"
                    Grid.Row="1"
                    Width="80"
                    Margin="0,64,6,57"
                    HorizontalAlignment="Right"
                    Foreground="White"
                    d:LayoutOverrides="Width" />
            <TextBlock x:Name="txbMessage"
                       Margin="8,0,8,22"
                       Grid.Row="1"
                       TextWrapping="Wrap"
                       FontWeight="Bold"
                       Foreground="Red"
                       VerticalAlignment="Bottom"
                       TextAlignment="Center"
                       FontSize="12" />
        </Grid>
    </Border>
</UserControl>

玩转代码

让我们来编写一些代码。首先,我们将用三个不同应用程序(Wordpad、Paint 和 Calculator)的位置填充我们的 TextBox 。请记住,Silverlight 在访问本地文件时有一些限制。因此,在这种情况下,我们将使用一些受信任的位置。

GetFolderPath() 方法将返回“开始菜单”->“所有程序”->“附件”目录,我们将通过附加文件名来设置它作为 TextBox 的值。在设置路径之前,让我们讨论一下方法中的代码行。

  1. 第一步,我们需要从 AutomationFactory 创建 Shell Application 对象。
  2. 获得 Shell Application 实例后,我们可以获取通用程序文件夹。我们可以通过将值“23”传递给 NameSpace 方法来获取它。23 是 Windows 通用程序目录路径的命名空间。我们将它存储在名为“commonPrograms”的本地动态变量中供以后使用。
  3. commonPrograms.Self.Path 将返回通用程序文件夹的确切路径。
  4. 我们将“Accessories”附加到此路径,以便获得必须从中选择应用程序文件的确切位置。
private string GetFolderPath()
{
    using (dynamic shellApplication = AutomationFactory.CreateObject("Shell.Application"))
    {
        // get the common programs folder using the namespace
        dynamic commonPrograms = shellApplication.NameSpace(23);

        // commonPrograms.Self.Path will return =>	
        // "C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs"
        string folderPath = string.Format("{0}\\{1}",
            commonPrograms.Self.Path, "Accessories");

        return folderPath;
    }
}

在页面加载时,我们将调用此方法并将 TextBox 字段填充为确切的位置。这是代码

void MainPage_Loaded(object sender, RoutedEventArgs e)
{
    txtWordpad.Text = string.Format(@"{0}\{1}.lnk", GetFolderPath(), "Wordpad");
    txtPaint.Text = string.Format(@"{0}\{1}.lnk", GetFolderPath(), "Paint");
    txtCalculator.Text = string.Format(@"{0}\{1}.lnk", GetFolderPath(), "Calculator");
}

如果您现在运行该应用程序,它看起来会像这样

pic_12.png

现在,让我们深入研究实现一个方法,该方法将文件名作为参数,并检查程序是否已固定到任务栏。如果未固定,代码将固定该应用程序;如果已固定,则会取消固定。让我们编写代码

private void PinToTaskbar(string fileName)
{
    // create the shell application object
    using (dynamic shellApplication = AutomationFactory.CreateObject("Shell.Application"))
    {
        // get the accessories directory
        dynamic directory = shellApplication.NameSpace(GetFolderPath());

        // get the full application path
        dynamic link = directory.ParseName(fileName + ".lnk");

        dynamic verbs = link.Verbs();
        for (int i = 0; i < verbs.Count(); i++)
        {
            dynamic verb = verbs.Item(i);
            string verbName = verb.Name.Replace(@"&", string.Empty).ToLower();

            if (verbName.Equals("pin to taskbar"))
            {
                verb.DoIt();
                ShowMessage(fileName + " has been pinned to your taskbar.");
            }
            else if (verbName.Equals("unpin from taskbar"))
            {
                verb.DoIt();
                ShowMessage(fileName + " has been unpinned from your taskbar.");
            }
        }
    }
}

第一行与前面描述的相同。获得 Shell Application 实例后,我们将通过调用 GetFolderPath() shell 命名空间获取附件目录。现在,将带扩展名的文件名附加到整个路径。我们必须使用.lnk 作为扩展名,因为我们是从“开始菜单”文件夹访问它,在该文件夹中所有应用程序都有一个快捷方式链接,即扩展名为.lnk

获得完整的应用程序路径后,我们可以通过调用 Verbs() 来检索分配给该应用程序的上下文菜单项。现在,我们将遍历每个项并检索项名称

dynamic verb = verbs.Item(i);
string verbName = verb.Name.Replace(@"&", string.Empty).ToLower();

现在我们将检查项名称是否为“pin to taskbar”(固定到任务栏),这意味着应用程序尚未固定到您的任务栏。所以通过调用 verb.DoIt() 将其固定到任务栏。如果项名称是“unpin from taskbar”(从任务栏取消固定),则意味着它已固定到任务栏。因此,我们可以通过再次调用 verb.DoIt() 来取消固定它。调用 verb.DoIt() 实际上会执行 shell 以运行所选的项目命令。

在按钮点击实现中,我们只需通过传递应用程序名称,即“Wordpad”、“Paint”、“Calculator”等来调用此方法,并且在单击时,它将检查名称并执行我们告诉它做的操作。

玩转应用程序

编写应用程序的代码和设计 UI 花费了大量时间。现在让我们运行应用程序,看看我们到目前为止实现了什么。

一旦运行您的应用程序(如果它在浏览器模式下打开,请将其安装为 Silverlight 浏览器外应用程序并在桌面上运行),您将看到以下窗口

pic_12.png

单击“Wordpad”应用程序的 TextBox 旁边的“Pin/Unpin”按钮。您会看到 Wordpad 图标已添加到您的 Windows 7 任务栏(前提是该图标尚未被固定),并会提示消息“Wordpad 已固定到您的任务栏。”让我们也对其他按钮做同样的事情。您将看到,当您单击相应的按钮时,应用程序会固定到任务栏。

pic_08.png

pic_09.png

让我们逐一再次单击按钮。您会注意到,当您单击相应的按钮时,应用程序会逐个从任务栏取消固定,并会提示消息“<APP_NAME> 已从您的任务栏取消固定。”

pic_10.png

pic_11.png

哇,多么棒的功能!!!是的,这太棒了。我们可以直接从 Silverlight 应用程序(仅限 OOB)访问 Windows 7 任务栏。以前只有 Windows 独立应用程序才有权访问它。现在 Silverlight 也可以了。

历史

  • 初始发布 - 2010 年 6 月 18 日

结束语

我认为,通过本文,您对 Silverlight COM API 访问 Windows 7 任务栏有了初步了解。现在您可以考虑在您的业务应用程序中使用 Silverlight 做一些新的事情。还有许多其他功能。不仅如此,您甚至可以访问 Windows 注册表。所以,探索更多 COM API 来满足您的业务需求。

如果您有兴趣,可以下载为本文编写的示例源代码。不仅如此,您甚至可以下载演示 zip 文件。只需运行名为“install”的文件。它将自动安装 Silverlight XAP 应用程序,并在您的桌面和开始菜单中创建应用程序快捷方式。打开文件以执行示例应用程序。

请为本文投票,并不要忘记提供您的反馈/建议。这将给我改进文章的机会。

请在 CodeProject我的博客 上阅读我的文章。 

© . All rights reserved.