C语言通过ITaskbarList3控制Windows7任务栏图标上的进度条

ITaskbarList3是一种COM组件。使用COM组件前,需要先调用CoInitializeEx函数初始化COM。程序退出前也要执行CoUninitialize函数释放相关资源。
在GUI线程中必须使用COINIT_APARTMENTTHREADED选项,不能使用COINIT_MULTITHREADED选项,否则某些窗口控件可能无法正常工作。
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
CoUninitialize();

初始化COM完成后,就可以创建ITaskbarList3对象了。XP系统下返回的taskbar指针为NULL。
ITaskbarList3 *taskbar;

CoCreateInstance(&CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, &IID_ITaskbarList3, &taskbar);
if (taskbar != NULL)
    ITaskbarList3_HrInit(taskbar);

程序退出前要记得释放ITaskbarList3对象。
if (taskbar != NULL)
{
    ITaskbarList3_Release(taskbar);
    taskbar = NULL;
}

[Win7任务栏图标进度条操作方法]
进度条显示绿色(表示正常):ITaskbarList3_SetProgressState(taskbar, 表示窗口的HWND变量, TBPF_NORMAL);
设置当前进度:ITaskbarList3_SetProgressValue(taskbar, 表示窗口的HWND变量, 当前值, 最大值);
关闭进度条显示:ITaskbarList3_SetProgressState(taskbar, 表示窗口的HWND变量, TBPF_NOPROGRESS);

进度条显示红色(表示错误):ITaskbarList3_SetProgressState(taskbar, 表示窗口的HWND变量, TBPF_ERROR);
进度条显示黄色(表示暂停):ITaskbarList3_SetProgressState(taskbar, 表示窗口的HWND变量, TBPF_PAUSED);
进度条循环滚动:ITaskbarList3_SetProgressState(taskbar, 表示窗口的HWND变量, TBPF_INDETERMINATE);

[普通窗口进度条操作方法]
获取表示进度条控件的HWND变量:HWND progress_wnd = GetDlgItem(hDlg, 控件ID);
设置当前进度:SendMessage(表示进度条控件的HWND变量, PBM_SETPOS, 进度值, 0);
              进度值的默认最小值为0,最大值为100。
              第四个参数必须为0。函数返回之前的进度。
设置最小值和最大值(16位整数):SendMessage(表示进度条控件的HWND变量, PBM_SETRANGE, 0, MAKELPARAM(最小值, 最大值));
设置最小值和最大值(32位整数):SendMessage(表示进度条控件的HWND变量, PBM_SETRANGE32, 最小值, 最大值);

进入循环滚动模式:
LONG_PTR style = GetWindowLongPtr(表示进度条控件的HWND变量, GWL_STYLE);
if ((style & PBS_MARQUEE) == 0)
{
    SetWindowLongPtr(表示进度条控件的HWND变量, GWL_STYLE, style | PBS_MARQUEE);
    SendMessage(表示进度条控件的HWND变量, PBM_SETMARQUEE, TRUE, 0);
}

退出循环滚动模式:
LONG_PTR style = GetWindowLongPtr(表示进度条控件的HWND变量, GWL_STYLE);
if (style & PBS_MARQUEE)
{
    SendMessage(表示进度条控件的HWND变量, PBM_SETMARQUEE, FALSE, 0);
    SetWindowLongPtr(表示进度条控件的HWND变量, GWL_STYLE, style & ~PBS_MARQUEE);
}

[任务栏图标橙黄色闪烁]
XP系统也可以使用。必须在后台使用(也就是说目标窗口不是当前窗口)。
闪烁次数结束后任务栏图标一直是橙色,直到用户切换到目标窗口才恢复。

FLASHWINFO flash;

flash.cbSize = sizeof(FLASHWINFO);
flash.dwFlags = FLASHW_TIMERNOFG | FLASHW_TRAY; // 一直闪烁到用户切换回窗口
flash.dwTimeout = 0;
flash.hwnd = 表示窗口的HWND变量;
flash.uCount = 3; // 闪烁次数
FlashWindowEx(&flash);

【程序代码】

main.c:

#define COBJMACROS
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <CommCtrl.h>
#include <ShlObj.h>
#include "resource.h"

// 必须启用XP风格
// 否则窗口显示后需要等待几秒钟动画才开始播放
#pragma comment(lib, "comctl32.lib")
#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

#define TIMER_ID 1

HINSTANCE main_instance;
HWND animate_wnd;
ITaskbarList3 *taskbar; // Win7任务栏进度条

void CALLBACK timer_proc(HWND hDlg, UINT uMsg, UINT iTimerID, DWORD dwTime)
{
	const int money[] = {1500, 1000, 500, 200, 0};
	const int progress[] = {25, 50, 75, 90, 100};
	static int step = 0;
	static BOOL paused = FALSE;
	char str[20];

	if (paused)
		return;
	
	_snprintf_s(str, sizeof(str), sizeof(str) - 1, "剩余%d块", money[step]);
	SetDlgItemTextA(hDlg, IDC_STATIC3, str);

	SendDlgItemMessage(hDlg, IDC_PROGRESS1, PBM_SETPOS, progress[step], 0);
	if (taskbar != NULL)
		ITaskbarList3_SetProgressValue(taskbar, hDlg, progress[step], 100);
	
	if (step == 3)
	{
		paused = TRUE;
		if (MessageBoxA(hDlg, "确定要上缴所有钱钱,不留零花钱吗?", "工资上缴", MB_ICONQUESTION | MB_YESNO) == IDYES)
		{
			step = 4;
			paused = FALSE;
		}
		else
			EndDialog(hDlg, 0);
	}
	else if (step == 4)
	{
		SetDlgItemTextA(hDlg, IDC_STATIC2, "上缴完毕! 你是世上最诚实的男人!");
		SetDlgItemTextA(hDlg, IDCANCEL, "完成");
		KillTimer(hDlg, TIMER_ID);
	}
	else
		step++;
}

INT_PTR CALLBACK dlg_proc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	int id;
	HICON icon;

	switch (uMsg)
	{
	case WM_COMMAND:
		/* 响应窗口命令 */
		id = LOWORD(wParam);
		switch (id)
		{
		case IDOK:
		case IDCANCEL:
			KillTimer(hDlg, TIMER_ID);
			EndDialog(hDlg, 0);
			break;
		}
		break;
	case WM_INITDIALOG:
		/* 初始化窗口 */
		// 设置窗口图标
		icon = (HICON)LoadImage(main_instance, MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
		SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)icon);
		icon = (HICON)LoadImage(main_instance, MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
		SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)icon);

		// 初始化进度条
		SendDlgItemMessage(hDlg, IDC_PROGRESS1, PBM_SETPOS, 4, 0);
		if (taskbar != NULL)
		{
			ITaskbarList3_SetProgressState(taskbar, hDlg, TBPF_NORMAL);
			ITaskbarList3_SetProgressValue(taskbar, hDlg, 4, 100);
		}

		// 初始化动画
		animate_wnd = GetDlgItem(hDlg, IDC_ANIMATE1);
		Animate_Open(animate_wnd, MAKEINTRESOURCE(IDR_AVI1));
		SetTimer(hDlg, TIMER_ID, 1000, timer_proc);
		break;
	}
	return 0;
}

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
	CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
	CoCreateInstance(&CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, &IID_ITaskbarList3, &taskbar);
	if (taskbar != NULL)
		ITaskbarList3_HrInit(taskbar);

	main_instance = hInstance;
	InitCommonControls();
	DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, dlg_proc);

	if (taskbar != NULL)
	{
		ITaskbarList3_Release(taskbar);
		taskbar = NULL;
	}
	CoUninitialize();
	return 0;
}

【Win7系统下的运行效果】

【XP系统下的运行效果】

【开发环境】

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
网上下载了emule0.50a-Xtreme8.1-sources源码,声称可以在VS2008下直接编译成功,经我实际测试,系统会报错,其中第一类错误,由于系统中为了兼容VISTA/WIN7,增加了相关定义,而这些定义在XP/WIN2003环境下会报错,共771个错误,如: 错误 2 error C2065: “ITaskbarList3”: 未声明的标识符 d:\emule相关资料\emule0.50a-xtreme\emule0.50a-xtreme8.1-sources\srchybrid\emuleDlg.h 195 emule 错误 3 error C2146: 语法错误 : 缺少“;”(在标识符“m_thbButtons”的前面) d:\emule相关资料\emule0.50a-xtreme\emule0.50a-xtreme8.1-sources\srchybrid\emuleDlg.h 196 emule 错误 4 error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int d:\emule相关资料\emule0.50a-xtreme\emule0.50a-xtreme8.1-sources\srchybrid\emuleDlg.h 196 emule 错误 5 error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int d:\emule相关资料\emule0.50a-xtreme\emule0.50a-xtreme8.1-sources\srchybrid\emuleDlg.h 196 emule 错误 6 error C2146: 语法错误 : 缺少“;”(在标识符“m_currentTBP_state”的前面) d:\emule相关资料\emule0.50a-xtreme\emule0.50a-xtreme8.1-sources\srchybrid\emuleDlg.h 198 emule 错误 7 error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int d:\emule相关资料\emule0.50a-xtreme\emule0.50a-xtreme8.1-sources\srchybrid\emuleDlg.h 198 emule 错误 8 error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int d:\emule相关资料\emule0.50a-xtreme\emule0.50a-xtreme8.1-sources\srchybrid\emuleDlg.h 198 emule 错误 10 error C2065: “ITaskbarList3”: 未声明的标识符 d:\emule相关资料\emule0.50a-xtreme\emule0.50a-xtreme8.1-sources\srchybrid\emuleDlg.h 195 emule ...... 此类错误中,ITaskbarList3是VISTA/WIN7环境下与任务栏相关的变量,只要屏闭掉相关定义就能正常。 除此之外还报有下面 5 个错误(实际引起错误的位置只有两个): 错误 135 error C2059: 语法错误 : “:” d:\eMule\srchybrid\BaseClient.cpp 1603 emule 错误 136 error C2065: “tagName”: 未声明的标识符 d:\eMule\srchybrid\BaseClient.cpp 1604 emule 错误 137 error C2228: “.WriteTagToFile”的左边必须有类/结构/联合 d:\eMule\srchybrid\BaseClient.cpp 1604 emule 错误 139 error C2001: 常量中有换行符 d:\eMule\srchybrid\BaseClient.cpp 4832 emule 错误 140 fatal error C1057: 宏展开中遇到意外的文件结束 d:\eMule\srchybrid\BaseClient.cpp 4832 emule 此类错误中,实际上是是两个语法错误,由于太过简单,我与网友都怀疑是作者故意制造的错误,若是完全不懂C++的人,即使拿到源码,编也会报错,从而止步于此。而稍懂C++的人(本人即是此类菜鸟),则可以找出错误之处。 为方便诸多象我一样的初学者,我把修正之后,可以在 XP/WIN2003 +VS2003SP1 环境下直接编译成功的emule0.50a-Xtreme8.1-sources源码发布上来,以便互相学习交流。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

巨大八爪鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值