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

Clipz -Windows 7 任务栏功能的友好介绍

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.91/5 (49投票s)

2009年12月17日

CPOL

9分钟阅读

viewsIcon

77615

downloadIcon

1579

Windows 7 任务栏功能的概述,以及如何在您自己的应用程序中使用它们。

Clipz

目录

引言

我最近在我的工作和家用电脑上都安装了 Windows 7,至少可以说,我对新版本印象深刻。试用了一些新功能(更不用说它比 Vista 快了多少),我可以肯定地说我再也不会回去了。

我最喜欢的新功能之一是任务栏的改进。如果您已经在使用 Windows 7,请继续将您那渴望的小指针悬停在任务栏上正在运行的程序上。漂亮的弹出窗口,是不是?现在,右键单击任务栏图标。我敢肯定您刚才看到的跳转列表肯定让您想放声歌唱!我知道我是。

这个令人兴奋的新任务栏可以做得很棒——在这篇文章中,我们将深入探讨它许多精彩的功能。

演示

我几乎总是围绕一些可用甚至有用的东西来撰写我的 CodeProject 文章。本文的源代码是一个我亲切地命名为“Clipz”的友好小工具。它驻留在您的任务栏上,并密切监视您的剪贴板以记录您复制的内容。当您需要再次使用您复制的内容时,Clipz 会很乐意将您最近复制的 10 个项目中的任何一个放回 Windows 剪贴板。如果您觉得这没什么用,至少 Clipz 可以教您一两个关于新任务栏的知识。

顺便说一句,您应该知道 Clipz 有一个最好的朋友。Clipz 在没有 Microsoft .NET 的 Windows API Code Pack 的帮助下什么也做不了。它们配合得很好。 您可以在这里了解 Clipz 的朋友的一切

不要害怕原生代码

请记住,各位男士女士们,任务栏是内置于 Windows 中的。这意味着有时我们将不得不使用 Windows 的原生语言与其交流。不过不用担心。我们将让 Clipz 直接处理原生 Windows 方法。它们其实并没有那么糟糕,不是吗?很好。前进!

使用 Windows 7 任务栏

API Code Pack:Clipz 大量使用了 API Code Pack,所以我们应该花一些时间来了解它。Code Pack 是一组库,它们用托管代码封装了许多 Windows 7 的功能。对于本文来说,最重要的是 TaskbarManager。我们探索的大部分内容都始于这个类。TaskbarManager 负责设置剪裁区域、缩略图预览、工具栏按钮以及所有其他任务栏功能。如果您应该记住一个类,那就是这个。

预览是如何工作的

刚才当您将鼠标悬停在正在运行的程序上时,您看到了一个非常详细的应用程序关联预览。默认情况下,Windows 7 会在任务栏预览中显示活动窗口的全部内容。这可能是您想要的行为,但 Clipz 不是。Clipz 更愿意在预览区域显示活动剪贴板项目(以位图格式)。这更有意义,也更有趣。看看 Clipz 的主窗口及其预览。注意预览区域只显示图片框中的内容?

绘制选定区域就像吃派一样容易。代码如下

// a rectangle that represents the position and size of the picturebox.
var pictureboxBounds = new Rectangle(630, 0, 150, 150);

// Tell the taskbar to use this rectangle area for drawing a preview
TaskbarManager.Instance.TabbedThumbnail.SetThumbnailClip(Handle, pictureboxBounds);

图片框位于客户端区域右侧 630 像素,向下 0 像素。Handle 属性是一个 IntPtr(指针),这是 Windows(包括早期版本)用来引用不同窗口的方式。调用任务栏管理器的 SetThumbnailClip 就足够了。一行代码!很简单,不是吗?

渲染区域

Clipz 很聪明也很友好,但任务栏有时需要帮助。它只会做它被告知的事情,仅此而已。看看下面的截图(Clipz 很上镜,不是吗?)。注意任务栏预览是如何被切断的?这是因为父窗口(预览左侧的窗口)被调整了大小,并且隐藏了预览图片框。

故事的寓意是,任务栏只会绘制它能看到的部分。这意味着您会遇到最小化、调整大小或隐藏窗口的问题。

工具栏按钮

什么比漂亮的预览更好?带有工具栏的漂亮预览!Windows 任务栏允许您在预览窗口中添加多达 7 个(巧合?)工具栏按钮。Clipz 使用四个方便的小按钮来帮助您随意复制和粘贴。

箭头按钮用于在剪贴板历史记录中翻页,X 删除历史记录中选定的预览,黄色剪贴板按钮将项目复制回剪贴板。

添加工具栏按钮再简单不过了。看看

_previous = new ThumbnailToolbarButton(PreviousIcon, “Previous”);
_next = new ThumbnailToolbarButton(NextIcon, “Next);
_delete = new ThumbnailToolbarButton(DeleteIcon, “Delete”);
_copy = new ThumbnailToolbarButton(CopyIcon, ”Copy”);
TaskbarManager.Instance.ThumbnailToolbars.AddButtons(Handle, 
               new[] { _previous, _delete, _copy, _next });

这些方便的小工具栏按钮不仅支持图标文件,还支持工具提示!我不确定它们还能有多大用处。

您可能想知道如何知道其中一个按钮何时被点击。这是理所当然的。这就像您为任何其他按钮添加事件处理程序一样简单。

_copy.Click += _copy_Click;

private void _copy_Click(object sender, ThumbnailButtonClickedEventArgs e){
    ...
}

缩略图预览

您会相信任务栏支持不仅一种,而是两种预览类型吗?如果您看到 Internet Explorer 在打开多个标签页时的预览,您可能已经熟悉了。

Clipz 是标签式预览的忠实拥护者。事实上,Clipz 支持两种预览模式——对应 Windows 7 支持的两种风格。分页模式(上图所示)一次显示一个预览,并带有用于导航的工具栏按钮。

自动预览模式同时显示所有活动的剪贴板预览。看看 Clipz 的 3 个剪贴板项目

每个标签项代表当前任务栏实例上设置的自定义位图。不过,万事皆有度。Windows 7 中的标签式预览模式不显示工具栏按钮。与标签式预览模式交互的唯一方法是单击其中一个标签式预览。

让我们看看 Clipz 如何将多个预览标签添加到任务栏

var thumbnail = new TabbedThumbnail(Handle, image);
thumbnail.SetImage(e.Thumbnail);
thumbnail.TabbedThumbnailClosed += thumbnail_TabbedThumbnailClosed;
thumbnail.TabbedThumbnailActivated += thumbnail_TabbedThumbnailActivated;

TaskbarManager.Instance.TabbedThumbnail.AddThumbnailPreview(thumbnail);

private void thumbnail_TabbedThumbnailActivated(object sender, TabbedThumbnailEventArgs e){
    ....
}
 
private void thumbnail_TabbedThumbnailClosed(object sender, TabbedThumbnailEventArgs e){
    ....
}

Clipz 为剪贴板历史记录中的每个项目添加一个任务栏标签式缩略图。您可以一遍又一遍地添加缩略图预览。添加的缩略图越多,它们就越小。

显示 7 个项目

显示 10 个项目

当您用完水平空间,它们变得太小而无法查看时,Windows 会将它们全部打包成一个整洁的小包裹,并在弹出菜单中显示它们!

跳转列表

Clipz 有一个小助手,一种副手,它驻留在您的系统托盘中,让您可以更改预览模式或关闭 Clipz(尽管我不确定为什么有人想这样做)。这个小小的托盘图标直到跳转列表出现之前一直都很开心。右键单击任务栏上的 Clipz 图标。注意到什么了吗?Clipz 在这里也有相同的预览模式更改功能。还有一个用于删除当前剪贴板历史记录的链接。

跳转列表有点不寻常。与工具栏按钮和缩略图预览不同,跳转列表链接没有点击事件。相反,它们会启动应用程序的另一个实例。对于浏览器或文字处理器来说这很好,但 Clipz 想独立运行。

由于只允许一个正在运行的实例,Clipz 使用了一个巧妙的小技巧来将跳转列表链接的点击事件传递给正在运行的实例。让我们来看看。

首先,这是如何添加跳转列表链接

_jumpList = JumpList.CreateJumpList();
// Don't display the "Frequent" or "Recent" documents categories
_jumpList.KnownCategoryToDisplay = JumpListKnownCategoryType.Neither;

// The jump list link's IconReference needs the icon's physical file path
var path = Path.GetDirectoryName(Application.ExecutablePath);

// Add the jump list link with a command of "-1".
// That command, when clicked, is passed in
// to the exe as a command line agrument.
_jumpList.AddUserTasks(new JumpListLink(Assembly.GetExecutingAssembly().Location, 
                       "Change Modes")
{
        Arguments = “-1”,
    IconReference = new IconReference(Path.Combine(path, "CopyIcon.ico"), 0)
});

// Same thing, but a command to clear all clipboard items
_jumpList.AddUserTasks(new JumpListLink(Assembly.GetExecutingAssembly().Location, 
                       "Clear Contents"){
        Arguments = “-2”,
        IconReference = new IconReference(Path.Combine(path, "CopyIcon.ico"), 0)
});

// Calling refresh displays the jump list links
_jumpList.Refresh();

要点是

  1. 如果您想要自定义图标,则必须使用带有图标资源的 EXE 文件或 .ico 文件。
  2. 任何时候想更改列表中的项目,都必须创建一个新的跳转列表。
  3. 您始终必须调用 Refresh 方法。

上面的两个跳转列表项的参数分别是“-1”和“-2”。如果没有更多的代码,单击这些链接将启动 Clipz 的新实例,并将参数传递到命令行。

让我们看看如何在不允许实例启动的情况下获取该参数。

[STAThread]
static void Main()
{
    bool firstInstance;
    // Check whether the application is already running.
    var mutex = new Mutex(true, "Clipz", out firstInstance);
        
    if (!firstInstance)
    {
        // If there is another instance running, get the command line agruments and
        // send them as a windows message to that instance.
        ProcessAgruments();
    }
    else
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        if (TaskbarManager.IsPlatformSupported)
        {
            Application.Run(new Form1());
        }
    }
}
/// <summary>
/// Processes the command line agruments.
/// </summary>
public static void ProcessAgruments()
{
    if (Environment.GetCommandLineArgs().Length <= 1) return;

    switch (Environment.GetCommandLineArgs()[1])
    {
        // Send a message via the User32 native method.
        // The User32.ChangeModeMessage is a static
        // integer that's registered at startup
        // and holds a value representing a pointer to 
        // a custom message.
        case Form1.ModeCommandArgument:
            User32.SendMessage("Clipz", User32.ChangeModeMessage, 
                               IntPtr.Zero, IntPtr.Zero);
            break;

        case Form1.ClearCommandArgument:
            User32.SendMessage("Clipz", User32.ClearContents, 
                               IntPtr.Zero, IntPtr.Zero);
            break;
    }
}

上面的代码中的 Mutex 是 Clipz 用来检查运行实例的。如果存在另一个实例,Clipz 会使用 User32 的 SendMessage 方法将传入的命令行参数传递给 Windows 子系统。

请记住,原生方法不必令人害怕。Clipz 非常乐意在另一端接收这些消息。这里是方法:

protected override void WndProc(ref Message message)
{
    // Check whether a command line argument was sent via another
    // attempted instance of the application.
    if (message.Msg == User32.ChangeModeMessage)
    {
        ChangeMode();
        return;
    }
    if (message.Msg == User32.ClearContents)
    {
        ClearContents();
        return;
    }
    
    base.WndProc(ref message);
}

WndProc 方法是负责处理所有来自 Windows 的传入消息的 Windows Forms 方法。Clipz 只对跳转列表链接从命令行发送的消息感兴趣。这不完全正确——Clipz 也在监听剪贴板更改。但这将是另一个话题。

重要的是,我们的跳转列表链接将命令参数发送到一个新的 Clipz 实例,该实例被拦截并拉入现有实例。您现在应该玩得很开心了!

关于剪贴板格式的说明

我一直试图坚持 Windows 任务栏功能,但如果我不解释 Clipz 显示的内容,我将失职。Clipz 将音频、图像、富文本和纯文本转换为 150x150 像素的位图表示。还有许多其他格式可以添加,例如文件拖放或文档特定目标。但目前,这四个例子足以让您对如何可视化各种剪贴板格式有一个大致的了解,更重要的是如何显示任务栏预览。

关于浏览器的说明

我还没有研究为什么有些浏览器会多次触发剪贴板更改事件。至少 Clipz 允许您删除不需要的项目。这是一种解决方法,但对于演示来说已经足够了。

摘要

Clipz 并非一无是处,它不是一个到处寻找问题的锤子。新的 Windows 7 任务栏支持许多其他功能,例如叠加和进度指示,仅举几例。现在,该轮到您去探索了。不要害羞……下载此项目以及此处其他一些优秀的文章,然后开始吧!

© . All rights reserved.