一、效果展示

二、源码分享
工程使用qmake编译
1、.pro
qt += widgets printsupport
config += c++17
# you can make your code fail to compile if it uses deprecated apis.
# in order to do so, uncomment the following line.
#defines += qt_disable_deprecated_before=0x060000 # disables all the apis deprecated before qt 6.0.0
sources += \
main.cpp \
mainwindow.cpp
headers += \
mainwindow.h
forms += \
mainwindow.ui
win32 {
libs += -luser32 -lole32
}
# default rules for deployment.
qnx: target.path = /tmp/$${target}/bin
else: unix:!android: target.path = /opt/$${target}/bin
!isempty(target.path): installs += target
resources += \
resources.qrc

2、mainwindow.h
#ifndef mainwindow_h
#define mainwindow_h
#include <qmainwindow>
#include <qtimer>
#ifdef q_os_win
#define initguid
#include <windows.h>
#include <shobjidl.h>
#endif
class mainwindow : public qmainwindow
{
q_object
public:
explicit mainwindow(qwidget *parent = nullptr);
~mainwindow() override;
private slots:
void ontimertick();
private:
void inittaskbar();
void releasetaskbar();
void settaskbarprogress(qint64 completed, qint64 total, tbpflag state = tbpf_normal);
void cleartaskbarprogress();
qtimer m_timer;
int m_progressvalue = 0;
#ifdef q_os_win
itaskbarlist3* m_taskbarinterface = nullptr;
hwnd m_hwnd = nullptr;
#endif
};
#endif // mainwindow_h
3、mainwindow.cpp
#include "mainwindow.h"
#include <qdebug>
mainwindow::mainwindow(qwidget *parent)
: qmainwindow(parent)
{
setwindowtitle("qt6 任务栏进度演示");
resize(600, 400);
#ifdef q_os_win
m_hwnd = reinterpret_cast<hwnd>(winid());
inittaskbar();
#endif
connect(&m_timer, &qtimer::timeout, this, &mainwindow::ontimertick);
m_timer.start(30);
}
mainwindow::~mainwindow()
{
#ifdef q_os_win
cleartaskbarprogress();
releasetaskbar();
#endif
}
void mainwindow::inittaskbar()
{
#ifdef q_os_win
hresult hr = coinitializeex(null, coinit_apartmentthreaded);
if (failed(hr))
{
qwarning() << "com初始化失败";
return;
}
hr = cocreateinstance(
clsid_taskbarlist,
nullptr,
clsctx_all,
iid_itaskbarlist3,
reinterpret_cast<void**>(&m_taskbarinterface)
);
if (failed(hr) || m_taskbarinterface == nullptr)
{
qwarning() << "创建任务栏接口失败";
couninitialize();
return;
}
m_taskbarinterface->hrinit();
#endif
}
void mainwindow::releasetaskbar()
{
#ifdef q_os_win
if (m_taskbarinterface)
{
m_taskbarinterface->release();
m_taskbarinterface = nullptr;
}
couninitialize();
#endif
}
// 修复参数类型 tbpflag
void mainwindow::settaskbarprogress(qint64 completed, qint64 total, tbpflag state)
{
#ifdef q_os_win
if (!m_taskbarinterface || m_hwnd == nullptr)
return;
m_taskbarinterface->setprogressvalue(m_hwnd, ulonglong(completed), ulonglong(total));
// 现在state是原生tbpflag枚举,无类型转换报错
m_taskbarinterface->setprogressstate(m_hwnd, state);
#endif
}
void mainwindow::cleartaskbarprogress()
{
#ifdef q_os_win
if (m_taskbarinterface && m_hwnd)
{
m_taskbarinterface->setprogressstate(m_hwnd, tbpf_noprogress);
}
#endif
}
void mainwindow::ontimertick()
{
m_progressvalue++;
if (m_progressvalue > 100)
{
m_progressvalue = 0;
cleartaskbarprogress();
}
#ifdef q_os_win
tbpflag progressstate = tbpf_normal;
if (m_progressvalue < 25)
{
progressstate = tbpf_normal; // 绿色
}
else if (m_progressvalue < 50)
{
progressstate = tbpf_paused; // 黄色暂停
}
else if (m_progressvalue < 75)
{
progressstate = tbpf_error; // 红色错误
}
else if (m_progressvalue < 90)
{
// 无限转圈
settaskbarprogress(0, 0, tbpf_indeterminate);
return;
}
else
{
progressstate = tbpf_normal;
}
settaskbarprogress(m_progressvalue, 100, progressstate);
#endif
}
4、main.cpp
#include <qapplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
qapplication a(argc, argv);
// windows 高dpi适配(可选推荐)
#if defined(q_os_win)
qapplication::sethighdpiscalefactorroundingpolicy(qt::highdpiscalefactorroundingpolicy::passthrough);
#endif
mainwindow w;
w.show();
return a.exec();
}
三、任务栏进度条详解
1、 技术原理
windows 任务栏进度条功能是通过 windows 7 引入的 itaskbarlist3 com 接口实现的。该接口提供了丰富的任务栏交互能力,包括:
- 进度显示:在应用程序图标上显示进度条
- 缩略图工具栏:添加自定义按钮到任务栏预览
- 叠加图标:在图标上显示状态指示器
- 缩略图预览:自定义任务栏预览内容
qt 作为跨平台框架,需要通过平台特定的代码来调用这些 windows api。
2、 核心 api 解析
itaskbarlist3 接口
// 主要进度相关方法 hresult setprogressstate(hwnd hwnd, tbpflag tbpflags); hresult setprogressvalue(hwnd hwnd, ulonglong ullcompleted, ulonglong ulltotal);
参数说明:
hwnd:窗口句柄,通过qwidget::winid()获取tbpflags:进度状态标志,控制进度条外观和行为ullcompleted:已完成的工作量ulltotal:总工作量
进度状态标志 (tbpflag)
typedef enum tbpflag {
tbpf_noprogress = 0x00000000, // 无进度条
tbpf_indeterminate = 0x00000001, // 不确定进度(转圈动画)
tbpf_normal = 0x00000002, // 绿色正常进度
tbpf_error = 0x00000004, // 红色错误状态
tbpf_paused = 0x00000008 // 黄色暂停状态
} tbpflag;
3、实现步骤详解
环境配置
项目文件 (.pro) 配置:
win32 {
libs += -luser32 -lole32 # 链接 windows api 库
}
头文件包含:
#ifdef q_os_win #define initguid #include <windows.h> #include <shobjidl.h> // itaskbarlist3 接口定义 #endif
com 初始化
windows com 组件需要正确初始化和清理:
// 初始化 com(单线程公寓模式)
hresult hr = coinitializeex(null, coinit_apartmentthreaded);
if (failed(hr)) {
qwarning() << "com初始化失败";
return;
}
// 创建 itaskbarlist3 实例
hr = cocreateinstance(
clsid_taskbarlist,
nullptr,
clsctx_all,
iid_itaskbarlist3,
reinterpret_cast<void**>(&m_taskbarinterface)
);
// 清理资源
void releasetaskbar() {
if (m_taskbarinterface) {
m_taskbarinterface->release();
m_taskbarinterface = nullptr;
}
couninitialize();
}
进度控制方法
设置进度值:
void settaskbarprogress(qint64 completed, qint64 total, tbpflag state = tbpf_normal) {
#ifdef q_os_win
if (!m_taskbarinterface || m_hwnd == nullptr)
return;
// 设置进度值(0-100)
m_taskbarinterface->setprogressvalue(m_hwnd,
ulonglong(completed),
ulonglong(total));
// 设置进度状态
m_taskbarinterface->setprogressstate(m_hwnd, state);
#endif
}
清除进度:
void cleartaskbarprogress() {
#ifdef q_os_win
if (m_taskbarinterface && m_hwnd) {
m_taskbarinterface->setprogressstate(m_hwnd, tbpf_noprogress);
}
#endif
}
4、实际应用场景
文件下载/上传进度
// 模拟文件下载进度
void ondownloadprogress(qint64 bytesreceived, qint64 bytestotal) {
int percent = (bytestotal > 0) ?
(bytesreceived * 100 / bytestotal) : 0;
tbpflag state = tbpf_normal;
if (percent >= 100) {
state = tbpf_noprogress; // 下载完成
} else if (networkerror) {
state = tbpf_error; // 网络错误
}
settaskbarprogress(percent, 100, state);
}
视频/音频播放进度
// 媒体播放进度
void onmediapositionchanged(qint64 position, qint64 duration) {
int percent = (duration > 0) ?
(position * 100 / duration) : 0;
tbpflag state = tbpf_normal;
if (ispaused) {
state = tbpf_paused; // 暂停状态
} else if (isbuffering) {
state = tbpf_indeterminate; // 缓冲中
}
settaskbarprogress(percent, 100, state);
}
批量任务处理
// 批量图片处理
void processimages(const qstringlist& imagepaths) {
int total = imagepaths.count();
for (int i = 0; i < total; ++i) {
// 处理单张图片
processsingleimage(imagepaths[i]);
// 更新进度
int progress = (i + 1) * 100 / total;
settaskbarprogress(progress, 100);
// 根据处理状态设置颜色
tbpflag state = tbpf_normal;
if (haserror) state = tbpf_error;
else if (iswarning) state = tbpf_paused;
settaskbarprogress(progress, 100, state);
}
// 处理完成
cleartaskbarprogress();
}
5、注意事项与最佳实践
平台兼容性
// 使用条件编译确保只在 windows 平台编译
#ifdef q_os_win
// windows 特定代码
#endif
// 或者使用运行时检测
if (qsysinfo::producttype() == "windows") {
// windows 平台逻辑
}
资源管理
- 及时释放 com 资源:在窗口关闭时调用
release()和couninitialize() - 异常处理:检查 com 调用返回值,处理可能的失败
- 线程安全:com 初始化应在主线程进行
用户体验优化
// 进度状态智能切换
void updateprogresswithstate(int value, int total, processstatus status) {
tbpflag flag = tbpf_normal;
switch (status) {
case processstatus::normal:
flag = tbpf_normal;
break;
case processstatus::paused:
flag = tbpf_paused;
break;
case processstatus::error:
flag = tbpf_error;
break;
case processstatus::indeterminate:
flag = tbpf_indeterminate;
break;
case processstatus::completed:
flag = tbpf_noprogress;
break;
}
settaskbarprogress(value, total, flag);
}
6、常见问题与解决方案
问题1:进度条不显示
可能原因:
- com 初始化失败
- 窗口句柄无效
- itaskbarlist3 接口创建失败
解决方案:
// 添加调试信息 qdebug() << "窗口句柄:" << m_hwnd; qdebug() << "接口指针:" << m_taskbarinterface; qdebug() << "com初始化结果:" << hr;
问题2:进度状态不更新
可能原因:
- 未在主线程调用
- 进度值超出范围
- 状态标志设置错误
问题3:内存泄漏
预防措施:
// 在析构函数中确保资源释放
mainwindow::~mainwindow() {
#ifdef q_os_win
cleartaskbarprogress();
releasetaskbar();
#endif
}
7、扩展功能
任务栏按钮
除了进度条,itaskbarlist3 还支持任务栏按钮:
// 添加任务栏按钮(需要额外实现) // m_taskbarinterface->thumbbaraddbuttons() // m_taskbarinterface->thumbbarupdatebuttons()
叠加图标
在任务栏图标上显示状态指示器:
// 设置叠加图标 // m_taskbarinterface->setoverlayicon()
8、总结
qt6 实现 windows 任务栏进度条的关键点:
- 平台特定代码:使用
#ifdef q_os_win条件编译 - com 接口:正确初始化和释放 itaskbarlist3 接口
- 进度控制:合理使用
setprogressvalue和setprogressstate - 状态管理:根据业务逻辑切换不同的进度状态
- 资源清理:确保在程序退出时释放所有 com 资源
通过本文的示例代码和详细解析,您应该能够:
- 理解 windows 任务栏进度条的工作原理
- 在 qt6 项目中正确集成该功能
- 根据实际需求定制进度显示逻辑
- 处理常见的兼容性和稳定性问题
以上就是基于qt实现windows任务栏进度条显示(附源码)的详细内容,更多关于qt任务栏进度条的资料请关注代码网其它相关文章!
发表评论