【COM API】心心念的 ITaskbarList3 使用方法

本文最后更新于:5 天前

简介

ITaskbarList3: 你可能不认识我,但你一定见过我的样子:

这就是 ITaskbarList 的功能之一,任务栏进度条。ITaskbarList3 是 ITaskbarList 的第三版,也就是在这个版本,微软加入了任务栏进度条的功能。

使用条件

  • 系统:Windows 7 及以上
  • COM 运行环境:STA
  • CLSID:CLSID_TaskbarList
  • IID:IID_ITaskbarList3

创建头文件

声明引用和导出函数。命名为 TaskbarProgress.h

1
2
3
4
5
6
7
8
9
#pragma once

#include <ShObjIdl.h>
#include <Windows.h>

cexport(void) InitializeTaskbarList(HWND hWnd);
cexport(void) SetTaskbarProgressState(TBPFLAG tbpFlags);
cexport(void) SetTaskbarProgressValue(ULONGLONG ullCompleted, ULONGLONG ullTotal);
cexport(void) ReleaseTaskbarList();

创建源文件

声明我们的接口指针以及必要的字段。命名为 TaskbarProgress.cpp

1
2
3
4
5
6
#include "pch.h"
#include "TaskbarProgress.h"

static ITaskbarList3* pList = nullptr;
static HWND targetHwnd = nullptr;
static BOOL initialized = FALSE;

初始化 COM 和 接口指针

由于我们这里导出给 WinForms 应用程序的 UI 线程中调用,该线程本身处于 STA,所以就不用初始化 COM 运行时了。

1
2
3
4
5
6
7
8
9
10
void InitializeTaskbarList(HWND hWnd)
{
if (!initialized && hWnd && // 确保是在没有初始化过且传入的 HWND 有效的情况下才进行
SUCCEEDED(CoCreateInstance(CLSID_TaskbarList, nullptr, CLSCTX_ALL, IID_ITaskbarList3, (LPVOID*)&pList)))
{
targetHwnd = hWnd; // 保存目标窗口的 HWND
pList->HrInit(); // 调用 TaskbarList 提供的初始化
initialized = TRUE; // 设置标志
}
}

设置进度状态

设置进度条的状态。

1
2
3
4
5
6
7
void SetTaskbarProgressState(TBPFLAG tbpFlags)
{
if (initialized)
{
pList->SetProgressState(targetHwnd, tbpFlags);
}
}

TBPFLAG 为我们提供了可用的状态枚举:

枚举 含义
TBPF_NOPROGRESS 关闭进度条
TBPF_INDETERMINATE 不停的滚动
TBPF_NORMAL 正常样式,蓝色 (系统主题颜色)
TBPF_ERROR 发生错误,红色
TBPF_PAUSED 暂停,黄色

设置进度值

设置进度条的进度值。两个参数分别表示 当前、总共

1
2
3
4
5
6
7
void SetTaskbarProgressValue(ULONGLONG ullCompleted, ULONGLONG ullTotal)
{
if (initialized)
{
pList->SetProgressValue(targetHwnd, ullCompleted, ullTotal);
}
}

由于类型是 ULONGLONG (C#->ulong),所以我们可以不用将最大值设置为 100。

这样的设计有个好处就是,比如我们想显示下载文件时的进度,此时就可以直接分别传入 已下载大小 和 总大小,由 ITaskbarList 帮我们计算百分比并反映在 UI 上。

如果把 ulong.MaxValue (18,446,744,073,709,551,615, 即 2^64 - 1) 看作单位为 B (byte) 的文件大小的话,约等于 18,446,744 TB,对于一个文件来说相当于无穷大了,然鹅并不会有这么大的文件,所以我们也不用担心会溢出。

释放资源

在窗体关闭时,我们可以调用此函数来释放所有 ITaskbarList 占用的资源

1
2
3
4
5
6
7
8
9
10
void ReleaseTaskbarList()
{
if (initialized)
{
if (pList) pList->Release(); // 调用 IUnknown 提供的释放函数
pList = nullptr; // 置空
targetHwnd = nullptr; // 置空
initialized = FALSE; // 重置标志
}
}

注意事项

上述代码实现仅保证单例运行,也就是不能同时在多个窗体中进行初始化和使用。

如果各位有多实例需求的话,那就不需要保存 targetHwnd 了,只需要直接加个参数在每一次调用 SetTaskbarProgressState 或 SetTaskbarProgressValue 时传入 HWND 就行了,因为 TaskbarList 原生支持多实例,也不需要再初始化一个 ITaskbarList3。

链接


【COM API】心心念的 ITaskbarList3 使用方法
https://wanghaonie.github.io/posts/a92b9edaa723/
作者
WangHaonie
发布于
2025-07-24 16:40:24
更新于
2025-07-27 18:39:40
许可协议