技术开发 频道

VS2010与Win7共舞 :任务栏缩略图

【VS2010与Windows 7共舞系列】

    【IT168专稿】
在本系列的上一篇文章中,我们介绍了任务栏中Jumplist的开发,在本文中,我们继续对Windows 7的任务栏进行编程开发,以充分利用Windows 7所提供的任务栏新特性。

第一篇:与7共舞:Jumplist
第三篇:与7共舞 :任务栏状态提示

    在前文中我们曾经介绍过Windows 7革命性的任务栏,除了任务栏的Jumplist之外,它的另外一个引人瞩目的新特性就是应用程序缩略图:通过任务栏中实时的缩略图,我们可以不用点击任务栏按钮切换到应用程序主窗口而可以知道应用程序的界面情况。想象一下,我们的任务栏中停靠着十几个应用程序窗口,如果我们一一点击激活这些应用程序来查找自己需要的窗口(在以前的操作系统中,我们就是这么做的),费时又费力。那将极大的降低我们的工作效率。通过任务栏缩略图,我们可以直接在任务栏中对窗口进行预览,从而可以快速地选取我们需要的窗口。

    任务栏缩略图除了可以帮助我们快速地对窗口进行选择外,我们还可以对应用程序的缩略图进行自定义。通过对应用程序任务栏缩略图的自定义,我们可以通过缩略图为用户提供更多更有意义的信息,便于用户快速地作出决策。

    总之,通过任务栏缩略图,Windows 7极大地提高和优化了用户的体验。为了让我们的应用程序可以同样借力于这一操作系统的新特性,提升应用程序本身的用户体验,下面我们来了解一下应用程序任务栏缩略图的开发。

    任务栏缩略图的主要作用就是为我们在选择窗口的时候提供决策支持:通过实时地对窗口进行预览,我们可以准确地选择我们需要的窗口,而无需像以前一样,逐个点击窗口进行查看,最终才能确定我们需要的窗口。


图1  实时的应用程序任务栏缩略图

     更进一步地,我们甚至可以通过任务栏按钮,方便地在任务栏缩略图中直接对应用程序进行控制,简化了先进行窗口切换然后再对应用程序进行操作的过程。
 


图2  在缩略图中对应用程序进行控制

    下面,我们还是在前一篇文章的简易图片浏览器的基础上,介绍如何对任务栏缩略图进行编程开发,借力Windows 7任务栏缩略图的种种新特性,使其可以满足我们的特定需求。

    对缩略图进行剪裁

    默认情况下,Windows 7已经为每个应用程序提供了一个默认的任务栏缩略图,实际上这个缩略图就是窗口激活后的样子。我们自己开发的应用程序无需做任何改动就可以免费地拥有任务栏缩略图的功能。但是,很多时候,由系统提供的默认缩略图并不能满足我们的要求。由系统提供的缩略图实际上是应用程序窗口激活后的缩小显示。某些情况下,当应用程序界面缩小显示后,并不能提供足够的有用的信息给我们。这时,我们就需要对系统提供的默认缩略图进行剪裁和缩放,以满足我们的需求。
 

    在前一篇文章中,我们创建了简易的图片浏览程序。当然,当我们运行程序的时候,Windows 7会为停留在任务栏的应用程序创建一个默认的缩略图。


图3  Windows 7创建的默认缩略图

    但是我们发现,这个缩略图包含了所有应用程序的界面,包括程序界面上的功能按钮,标题栏等等。对于一个图片浏览器程序而言,最重要的是图片显示区域。为了让用户从缩略图中获取更多有价值的信息,我们需要对这个默认的缩略图进行剪裁,保留有价值的图片区域,去掉没有参考价值的程序主界面。

    我们在程序主界面上添加一个按钮“剪裁缩略图”,并将其点击函数实现如下:

// 是否处于剪切状态
private bool _clipToggled;
private void ToggleClipBtn_Click(object sender, EventArgs e)
{
// 切换缩略图剪切状态
_clipToggled = !_clipToggled;
if (_clipToggled)
{
// 剪切缩略图
SetClip();
}

}

private void SetClip()
{
// 获得PictureBox控件的位置,作为缩略图剪切的起点
Point point = pictureShowBox.Location;
int nHeight = pictureShowBox.Height;
int nWide = pictureShowBox.Width;
// 设定剪切范围
Windows7Taskbar.SetThumbnailClip(Handle,
new Rectangle(point, new Size(nWide, nHeight)));
}
 

    在这段代码中,我们首先获得了应用程序中用来显示图片的PictureBox控件的位置和大小,以此作为缩略图的剪切范围。然后我们通过调用SetThumbnailClip()函数设置一个剪切范围,这样我们就实现了对缩略图的剪切。然后,当我们将鼠标移动到任务栏图标上,触发缩略图显示的时候,就可以调用SetClip()函数对缩略图进行剪切了。我们需求重载窗体的WndProc函数并实现如下:

 

protected override void WndProc(ref Message m)
{
if (_clipToggled)
SetClip(); // 剪切缩略图


base.WndProc(ref m);

}
 

 

    现在我们编译运行整个解决方案,就可以看到缩略图剪切后的效果了。经过剪切后的缩略图,更加有效地反映了应用程序的状态,给用户以更多各有价值的信息:
 


图4  剪切后的缩略图

    这里我们只是简单地使用PictureBox控件的范围作为缩略图的范围,在实际应用中,我们还可以在图片中设置选区,对选区内的图像进行缩略图放大显示,从而实现更加高级的应用。

    对缩略图进行自定义

    在上文中,我们对Windows 7操作系统默认的缩略图进行了剪裁,使其一定程度上满足了我们对缩略图的需求。但是对缩略图的剪裁,始终都是在操作系统所提供的缩略图的基础上进行的,它只能对应用程序主窗口进行缩略显示。有时,我们希望可以对缩略图进行自定义,并不使用程序主窗口的样子。如果我们想在缩略图中显示其他的内容,比如我们开发的是一个实时的股票查询软件,主界面显示的是当前的曲线图,但是我们在缩略图中却希望能够更清楚地知道当前的股价,需要在缩略图中显示当前的实时股价。在这种情况下,我们就需要对缩略图进行自定义了。

    对缩略图的自定义是通过Windows7.DesktopIntegration中的CustomWindowsManager类来实现的。例如,我们可以通过这个类处理ThumbnailRequested请求,在其中完成缩略图的自定义。在这个例子中,我们将应用程序中打开的图片灰度化后作为新的自定义的缩略图。我们在应用程序的主界面上添加一个按钮“自定义缩略图”并将其点击函数实现如下:

// 定义Form层级的CustomWindowsManager对象
CustomWindowsManager _customWindowManager;
private void CustomThumbBtn_Click(object sender, EventArgs e)
{
// 判断_customWindowManager是否为空
// 在自定义缩略图和默认缩略图之间切换
if (_customWindowManager != null)
{
// 取消自定义缩略图
_customWindowManager.DisablePreview();
_customWindowManager = null;
}
else
{
// 创建对象
_customWindowManager = CustomWindowsManager.CreateWindowsManager(Handle);
// 使用窗口屏幕截图作为窗口选取的缩略图
_customWindowManager.PeekRequested += (o, args) => args.UseWindowScreenshot = true;
// 对缩略图请求进行自定义
_customWindowManager.ThumbnailRequested += (o, args) =>
{
// 根据PictureBox显示的图片创建缩略图
Bitmap image = (Bitmap)(pictureShowBox.Image.GetThumbnailImage(
200, 199, null, IntPtr.Zero));

// 对图像进行自定义处理
// 将图像处理成灰度图像
BitmapData data = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

//循环处理所有图像像素
unsafe
{
byte* ptr = (byte*)(data.Scan0);
for (int i = 0; i < data.Height; i++)
{
for (int j = 0; j < data.Width; j++)
{
// 图像灰度化
byte nGray, R, G, B;
R = *ptr;
G = *++ptr;
B = *++ptr;
ptr -= 2;
nGray = (byte)(0.299 * (double)R
+ 0.587 * (double)G
+ 0.114 * (double)B);

*ptr = nGray;
ptr++;
*ptr = nGray;
ptr++;
*ptr = nGray;
ptr++;
}
ptr += data.Stride - data.Width * 3;
}
}

image.UnlockBits(data);

// 将灰度化后的图像显示为缩略图
Bitmap bitmap = new Bitmap(args.Width, args.Height);
using (Graphics g = Graphics.FromImage(bitmap))
{
// 绘制到缩略位图上
g.DrawImage(image, 0, 0);
}
bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);

// 替换缩略图,也即将我们绘制的灰度图像显示为缩略图
// 完成缩略图的自定义
args.Bitmap = bitmap;
};
}
}

    然后,我们在重载的窗体WndProc消息处理函数中,将缩略图相关的消息转发给customWindowManager,customWindowManager会接受到跟缩略图相关的消息并对缩略图进行自定义的绘制。自定义的缩略图绘制完毕后,我们刷新customWindowManager的显示,就可以在任务栏中看到我们自定义的缩略图了:

protected override void WndProc(ref Message m)
{
if (_clipToggled)
SetClip();

if (_customWindowManager != null)
{
// 转发消息给customWindowManager
_customWindowManager.DispatchMessage(ref m);
// 刷新customWindowManager的显示
_customWindowManager.InvalidatePreviews();
}

base.WndProc(ref m);}

 

    最后,我们可以看到在主界面上显示的图片被灰度化后显示到缩略图中了:
 


图5  自定义缩略图

    通过缩略图工具栏控制应用程序

    前面两个例子,都只是对缩略图进行处理,让我们可以直观的了解应用程序的状态。更进一步地,在Windows 7的任务栏缩略图中,我们还可以通过缩略图工具栏直接对应用程序进行操作。例如Windows Media Player的任务栏缩略图中的播放按钮等等。
无疑,缩略图工具栏极大地提高了应用程序的操作效率。通过ThumbButtonManager类,我们也可以方便地为我们的应用程序添加缩略图工具栏。在本文的例子中,我们为缩略图添加一个工具栏,这个工具栏只包含一个按钮(Windows 7的缩略图工具栏最多只能包含7个按钮)。当用户点击这个按钮后,就可以得到关于当前加载的图片的相关信息。

    首先,我们在应用程序主界面上添加一个按钮“缩略图按钮”并将其点击响应函数实现如下:

// 定义Form层级的ThumbButtonManager对象
ThumbButtonManager _thumbButtonManager;
private void ThumbToolBarBtn_Click(object sender, EventArgs e)
{
// 切换状态
if (_thumbButtonManager != null)
{
_thumbButtonManager = null;
}
else
{
// 创建ThumbButtonManager对象
_thumbButtonManager = new ThumbButtonManager(Handle);
//创建工具栏按钮
// 这里我们使用系统图标作为按钮的图标
ThumbButton button =
_thumbButtonManager.CreateThumbButton(101,
SystemIcons.Information, "Open Picures");

// 处理按钮点击消息
button.Clicked += delegate
{
// 获取当前加载的图片的信息
string strInfo = string.Format(" FileLocation: {0} \n Height: {1} \n Width:{2}",
pictureShowBox.ImageLocation,
pictureShowBox.Image.Height,
pictureShowBox.Image.Width);
// 通过消息框显示图片信息
MessageBox.Show(strInfo, "Picture Information");
};

// 将按钮添加到缩略图工具栏中
_thumbButtonManager.AddThumbButtons(button);
}
}
 

    完成任务栏按钮的添加后,同样的,我们还需要在WndProc消息处理函数做将相应的消息转发给_thumbButtonManager,这样当我们点击工具栏中的按钮时,_thumbButtonManager才会接受到这个消息并对其进行处理,报告图片的相关信息:

protected override void WndProc(ref Message m)
{
// …

// 转发消息
if (_thumbButtonManager != null)
_thumbButtonManager.DispatchMessage(ref m);
base.WndProc(ref m);}

    现在,我们的缩略图任务栏按钮已经添加完成了,当我们执行应用程序并点击“缩略图按钮”后,就会在缩略图中看到我们新添加的按钮,点击此按钮,我们会得到关于图片的报告信息。


图6  缩略图工具栏


    在这里,我们只是通过缩略图任务栏按钮实现了一个简单的报告功能,在实际开发中,我们可以将应用程序最常用的操作放在缩略图任务栏中,例如一个媒体播放器的播放/暂停,上一首,下一首等等,有了工具栏按钮,对应用程序的操作可以更加方便快捷。

    任务栏缩略图,将我们从黑暗带向了光明!
 

0
相关文章