在Delphi中应用Windows7任务栏新特性(1)

Windows7 对任务栏的改变比较大,比如任务栏按钮合并、显示进度条、缩略图按钮等等。最近想试试在 Delphi 中使用 Windows7 的任务栏新特性,于是百度了一下,只找到一些实例,而且貌似还是相同的。最后还是在 MSDN 找到了详细的说明,于是发这篇文章记录一下,权当是学习笔记。

系统支持

既然是 Windows7 任务栏的特性,所以在使用前对操作系统版本进行一下检测是有必要的。实际上之后要说到的各个函数并非只支持 Windows7 ,但支持的操作系统也各不相同。
Delphi 中可以使用 CheckWin32Version 函数进行检测。CheckWin32Version 的定义是:

function CheckWin32Version(AMajor: Integer; AMinor: Integer = 0): Boolean;

其中 AMajor 和 AMinor 分别是主版本号和次版本号。检测 Windows7 即是 CheckWin32Version(6, 1) 。例如:

if CheckWin32Version(6, 1) then
	ShowMessage('Windows 7')
else
	ShowMessage('Not Windows 7');

具体的使用,参见之后各个接口及函数的版本需求。

准备工作

在 Delphi 中对任务栏按钮进行操作,需要在 uses 中加入 ComObj 和 ShlObj 两个单元,因为之后要用到的类还有函数之类的在这两个单元中有声明。
Windows 的任务栏组件提供了四个接口类,分别是 ITaskbarList 、 ITaskbarList2 、 ITaskbarList3 、 ITaskbarList4 。使用方法和一般的类基本相同。

首先声明对象:

TaskbarList: ITaskbarList;
TaskbarList2: ITaskbarList2;
TaskbarList3: ITaskbarList3;
TaskbarList4: ITaskbarList4;

然后通过传递 CLSID_TaskBarList 参数调用 CreateComObject 函数来释放这四个接口,并且做一些初始化的操作。例如:

TaskbarList := CreateComObject(CLSID_TaskbarList) as ITaskbarList;
TaskbarList.HrInit;
Supports(TaskbarList, IID_ITaskbarList2, TaskbarList2);
Supports(TaskbarList, IID_ITaskbarList3, TaskbarList3);
Supports(TaskbarList, IID_ITaskbarList4, TaskbarList4);

其中,有关 HrInit 的说明后面会提到。

下面分别对这四个接口进行说明。

ITaskbarList 接口

下面是 ITaskbarList 的定义:

{ interface ITaskbarList }
	ITaskbarList = interface(IUnknown) 
		[SID_ITaskbarList]
		function HrInit: HRESULT; stdcall;
		function AddTab(hwnd: HWND): HRESULT; stdcall;
		function DeleteTab(hwnd: HWND): HRESULT; stdcall;
		function ActivateTab(hwnd: HWND): HRESULT; stdcall;
		function SetActiveAlt(hwnd: HWND): HRESULT; stdcall;
	end;
	{$EXTERNALSYM ITaskbarList}

可以看出 ITaskbarList 接口主要用来执行添加、删除和激活任务栏按钮等操作。
要使用此接口,至少需要 Windows 2000 Professional , Windows XP , Windows 2000 Server 以上。没有特别说明,其中的函数的系统需求也是如此。

接下来对它的函数做个简单的说明。
其中的参数 hwnd 是应用程序或主窗口的句柄,以下不再单独说明。
HrInit
HrInit 函数用于初始化,必须要在使用其他函数前执行。这就是为什么在前面的初始化代码中调用了 HrInit 函数的缘故。
AddTab
用于添加按钮到任务栏上。
一般来说可以添加任意窗口,但是建议最好是带有标题栏的窗口。
用 AddTab 添加的任务栏按钮在窗体释放之后必须使用 DeleteTab 释放。
DeleteTab
从任务栏上删除指定按钮。
ActivateTab
激活任务栏上的按钮。要注意的是,窗口并不会被激活,仅仅是在任务栏上显示为激活状态。
SetActiveAlt
将任务栏上的按钮标记为激活,但并不激活。
SetActiveAlt 在某一进程中将指定的按钮比较为当前激活的项目,但并不改变实际的状态。此进程中,任何用户操作试图激活其他不同的按钮,都会被指定的按钮取而代之。进程未激活时,指定按钮的激活状态不受影响。要确保指定按钮总是激活的,每次激活其他窗口前都调用 SetActiveAlt 。使用空句柄调用时,将会清除这一状态。
不知道各位是否理解,因为我也不确定我的理解就是正确的。简单地说就是,使用 SetActiveAlt 可以在某一进程中使得其他任务栏按钮无法被激活。用一个不恰当的比方就是:无论打谁疼得都是自己。

删除任务栏按钮的例子:

var
	FormHandle: THandle;
begin
	if not Application.MainFormOnTaskBar then
		FormHandle := Application.Handle
	else
		FormHandle := Application.MainForm.Handle;
	TaskbarList.DeleteTab(FormHandle);
end;

添加任务栏按钮的代码:

var
	FormHandle: THandle;
begin
	if not Application.MainFormOnTaskBar then
		FormHandle := Application.Handle
	else
		FormHandle := Application.MainForm.Handle;
	TaskbarList.AddTab(FormHandle);
end;

其他:
1、我们可以利用 DeleteTab 来隐藏程序在任务栏的图标,恢复时调用 AddTab 就可以了。
2、从上面例子可以看出我分情况使用了 Application.Handle 和 Application.MainForm.Handle 。个人认为,没有窗体的程序或者隐藏了窗体(MainFormOnTaskBar 设置为 False)的程序用前者,有窗体且 MainFormOnTaskBar 设置为 True 的程序用后者。
两者的区别,体现在 ActivateTab 的结果中:对一个有窗体且 MainFormOnTaskBar 设置为 True 的程序使用 ActivateTab(Application.MainForm.Handle),对应的按钮会被设置为激活。而若使用 ActivateTab(Application.Handle),会看到激活的并不是指定的窗体,而是多出来的一个没有缩略图的新按钮。

先到这儿吧。关于进度条以及其他的应用下次再写。

对了,欢迎各位高手纠错。

在Delphi中应用Windows7任务栏新特性(1)》有2个想法

    1. @IronBlood ITaskbarList2继承自ITaskbarList,ITaskbarList3继承自ITaskbarList2,依此类推。
      后面的继承了前面的方法,同时拥有自己独有的方法,也就是功能扩充了。
      之所以这样我觉得是为了适应不同的Windows版本,因为:
      ITaskbarList要求2000以上,ITaskbarList2要求XP/2003以上,ITaskbarList3和ITaskbarList4要求7/2008R2以上。
      个人愚见。 /呲牙

评论已关闭。