Contents
I recently installed Windows 7 on my work and home machines, and I’m impressed with the new version to say the least. Having played with some of the new features (not to mention how much faster it is than Vista), I can safely say I’ll never go back.
Some of my favorite new features are the improvements made to the task bar. If you’re running Windows 7 already, go ahead and hover your eager little pointer over a running program in the task bar. Beautiful popup, isn’t it? Now, right click the task bar icon. I’m sure the jump list you just saw made you want to sing! I know I did.
This exciting new task bar can do amazing things – and we’re going to take a deep dive in this article to explore its many wonderful features.
I almost always wrap my CodeProject articles around something usable, if not useful. The source code that goes with this article is a friendly little tool I’ve affectionately named “Clipz”. It sits in your task bar and watchfully inspects your clipboard for things you copy. And when you need those things you copied again, Clipz is happy to put any of the last 10 items you’ve copied back onto the Windows clipboard for you. And if you don’t find that useful, at least Clipz can teach you a thing or two about the new task bar.
By the way, you should know that Clipz has a best friend. Clipz doesn’t do anything without help from the Windows API Code Pack for Microsoft .NET. The two play well together. You can learn all about Clipz’ friend here.
Remember, boys and girls, the taskbar is built into Windows. That means that there are times when we’ll have to talk to Windows in its native language. Not to worry, though. We’ll let Clipz tackle native Windows methods head-on. They’re really not so bad, now are they? Good. Onward!
API Code Pack: Clipz makes heavy use of the API Code Pack, so we should spend some time getting to know it. The code pack is a set of libraries that wrap a number of Windows 7 features in managed code. Most notably for this article is the TaskbarManager
. Almost everything we'll explore starts with this class. The TaskbarManager
is responsible for setting the clipping areas, thumbnail previews, toolbar buttons, and all other task bar features. If there's one class you should remember, it's this one.
When you held your mouse over a running program a moment ago, you saw a wonderfully detailed preview of the associated application. By default, Windows 7 will show the entire contents of an active window in a task bar preview. That may be the behavior you want, but not Clipz. Clipz would rather display the active clipboard item (in bitmap format) in the preview area. That’s much more meaningful, and fun to look at too. Take a look at the main windows in Clipz along side its preview. Notice how the preview area only shows what’s in the picture box?
Drawing the select area is as easy as pie. The code looks like this:
var pictureboxBounds = new Rectangle(630, 0, 150, 150);
TaskbarManager.Instance.TabbedThumbnail.SetThumbnailClip(Handle, pictureboxBounds);
The picture box is 630 pixels to the right of the client area, and 0 pixels down. The Handle
property is an IntPtr
(a pointer), and is what Windows (even previous versions) use to reference different windows. A call to the task bar manager's SetThumbnailClip
is all it takes. One line of code! Simple, isn’t it?
As smart and friendly as Clipz may be, the task bar sometimes needs a helping hand. It’ll only do what it’s told, and no more than that. Take a look at the following screenshot (isn't Clipz photogenic?). Notice how the task bar preview is cut off at the knees? That is because the parent window (the window on the left of the preview) has been re-sized and is hiding the preview picture box.
The moral of the story is that the task bar will only draw what it can see. That means you’ll run into problems for minimized, re-sized, or hidden windows.
What’s better than a beautiful preview? A beautiful preview with toolbars! The Windows task bar lets you add up to 7 (coincidence?) toolbar buttons to a preview window. Clipz uses four convenient little buttons to help you copy and paste to your heart’s content.
The arrow buttons page through the clipboard history, the X deletes the selected preview from history, and the little yellow clipboard copies the item back into the clipboard.
Adding toolbar buttons couldn’t be easier. Take a look:
_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 });
Not only do these handy little toolbar buttons support icon files, they have tooltips too! I’m not sure they could be more useful.
You’re probably wondering how you know when one of these buttons is clicked. And rightly so. It’s as simple as adding an event handler like you would with any other button.
_copy.Click += _copy_Click;
private void _copy_Click(object sender, ThumbnailButtonClickedEventArgs e){
...
}
Would you believe that the task bar supports not one, but two types of previews? You may be familiar with this if you’ve seen Internet Explorer’s preview when multiple tabs are open.
Clipz is a big fan of tabbed previews. So much, in fact, that Clipz supports two preview modes – one for each style Windows 7 supports. The paging mode (shown above) shows one preview at a time with toolbar buttons for navigation.
The Auto preview mode shows all the active clipboard previews at the same time. Have a look at Clipz with 3 clipboard items:
Each tab item represents a custom bitmap that's set on the current task bar instance. All good things in moderation, though. The tabbed preview mode in Windows 7 won’t show toolbar buttons. The only way to interact with the tabbed preview mode is to click on one of the tabbed previews.
Let’s take a look at how Clipz puts multiple preview tabs on to the taskbar:
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 adds a task bar tabbed thumbnail for each item in the clipboard history. You can add thumbnail previews over and over and over again. The more thumbnails you add, the smaller they get.
Showing 7 Items
Showing 10 Items
And when you run out of horizontal room, and they get too small to see, Windows wraps them all up in a neat little package and shows them in a popup menu!
Clipz has a little helper, a sort of sidekick, that sits in your tray and lets you change preview modes or shut Clipz down (although I’m not sure why anyone would want to do that). This little tray icon was perfectly happy until jump lists came along. Right click on the Clipz icon on your task bar. Notice anything? Clipz has the same preview mode change function here too. And a link for deleting the current clipboard history as well.
Jump lists are unusual, though. Unlike toolbar buttons and thumbnail previews, jump list links don’t have click events. Instead, they start up another instance of the running application. That’s fine for browsers or word processors, but Clipz wants to stand alone.
Since only one running instance is allowed, Clipz uses a creative little trick to get jump list link click events into the running instance. Let’s have a look.
Here’s how jump list links are added in the first place:
_jumpList = JumpList.CreateJumpList();
_jumpList.KnownCategoryToDisplay = JumpListKnownCategoryType.Neither;
var path = Path.GetDirectoryName(Application.ExecutablePath);
_jumpList.AddUserTasks(new JumpListLink(Assembly.GetExecutingAssembly().Location,
"Change Modes")
{
Arguments = “-1”,
IconReference = new IconReference(Path.Combine(path, "CopyIcon.ico"), 0)
});
_jumpList.AddUserTasks(new JumpListLink(Assembly.GetExecutingAssembly().Location,
"Clear Contents"){
Arguments = “-2”,
IconReference = new IconReference(Path.Combine(path, "CopyIcon.ico"), 0)
});
_jumpList.Refresh();
The key points are:
- You have to use an EXE with an icon resource or a .ico file if you want a custom icon.
- You have to create a new jump list any time you want to change items in the list.
- You always have to call the
Refresh
method.
The two jump list items above have arguments of “-1” and “-2”, respectively. Without any more code, clicking on these links will start a new instance of Clipz and pass in the argument in the command line.
Let’s take a look at how we can get that argument without allowing an instance to start up.
[STAThread]
static void Main()
{
bool firstInstance;
var mutex = new Mutex(true, "Clipz", out firstInstance);
if (!firstInstance)
{
ProcessAgruments();
}
else
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
if (TaskbarManager.IsPlatformSupported)
{
Application.Run(new Form1());
}
}
}
public static void ProcessAgruments()
{
if (Environment.GetCommandLineArgs().Length <= 1) return;
switch (Environment.GetCommandLineArgs()[1])
{
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;
}
}
The Mutex
in the code above is what Clipz is using to check for running instances. If there is another instance, Clipz passes the incoming command line arguments to the Windows subsystem using the User32 SendMessage
method.
Remember, native methods don’t have to be scary. Clipz is perfectly happy to help with receiving these messages on the other side. Here’s how:
protected override void WndProc(ref Message message)
{
if (message.Msg == User32.ChangeModeMessage)
{
ChangeMode();
return;
}
if (message.Msg == User32.ClearContents)
{
ClearContents();
return;
}
base.WndProc(ref message);
}
The WndProc
method is the Windows Forms method responsible for handling all incoming messages from Windows. Clipz is only interested in messages the jump list links send from the command line. That’s not entirely true – Clipz is also watching for clipboard changes. But that’s a topic for another day.
What’s important is that our jump list links send a command argument to a new Clipz instance which is intercepted and pulled into the existing instance. You should be having all kinds of fun by now!
I’ve tried to stick to Windows taskbar features, but I’d be remiss if I didn’t explain what it is that Clipz is displaying. Clipz takes audio, images, rich text, and plain text, and converts them into 150x150 pixel bitmap representations. There are plenty of other formats that could be added like file drop or document specific targets. For now, though, these four examples are enough to give you a general idea of how to visualize various clipboard formats, and more importantly how to show taskbar previews.
I haven't looked into why some browsers fire clipboard change events multiple times. At least Clipz lets you delete items you don't want. It's a hack, but good enough for the demo.
One thing Clipz is not is a hammer in search of nails. There are many more features the new Windows 7 taskbar supports, like overlays and progress indication, to name a few. Now, it’s your turn to explore. Don’t be shy… download this project and some of the other excellent articles here, and get going!