参考:https://learn.microsoft.com/zh-cn/windows/win32/controls/progress-bar-control
Comctl的全称是Common Controls,也就是公共控件的意思,属于Windows系统的一部分,提供了一组标准的UI控件,如Button、ListView等等。
Comctl32主要有两个大版本,v5和v6,最明显的两个区别:
外观,一个是古老的Windows 98风格,一个是跟随系统的风格。
5.X的控件样式,是固定的样式。

6.X的控件样式,会随着系统主题变化。

兼容性,6.0以后的某些控件对多字节字符集的应用存在兼容性问题。
公共控件库提供的窗口类名称
ANIMATE_CLASS
创建动画控件。 这些控件以无提示方式显示音频视频交错 (AVI) 剪辑。
DATETIMEPICK_CLASS
创建日期和时间选取器控件。 这些控件提供一个简单的界面,用于与用户交换日期和时间信息。
HOTKEY_CLASS
创建热键控件。 通过这些控件,用户可以轻松定义热键。
LINK_CLASS
创建 syslink 控件。 这些控件与链接一起使用。
MONTHCAL_CLASS
创建月历控件。 这些控件为用户从熟悉的界面中选择日期提供了一种简单方法。
NATIVEFNTCTL_CLASS
创建本机字体控件。 这些控件与本机字体一起使用。
PROGRESS_CLASS
创建进度栏。 这些控件指示长时间操作的进度。
REBARCLASSNAME
创建 rebar 控件。 这些控件充当子窗口的容器。
STANDARD_CLASSES
创建内部 User32 控件,例如按钮、编辑和滚动条。
STATUSCLASSNAME
创建状态窗口。 这些控件在水平窗口中显示状态信息。
TOOLBARCLASSNAME
创建工具栏。 这些控件包含执行菜单命令的按钮。
TOOLTIPS_CLASS
创建工具提示控件。 这些控件显示一个小弹出窗口,其中包含描述应用程序中工具用途的文本行。
TRACKBAR_CLASS
创建跟踪条。 这些控件允许用户通过移动滑块从一系列值中进行选择。
UPDOWN_CLASS
创建向上控件。 这些控件将箭头配对与编辑控件组合在一起。 单击箭头递增或递减编辑控件中的值。
WC_BUTTON
创建按钮控件。 这些控件使用户能够启动操作。
WC_COMBOBOX
创建组合框控件。 这些控件包含一个下拉列表,可从中选择单个项。
WC_COMBOBOXEX
创建 ComboBoxEx 控件。 这些控件提供组合框控件的扩展,该控件提供对项图像的本机支持。
WC_EDIT
创建编辑控件。 这些控件包含可编辑的文本。
WC_HEADER
创建标头控件。 这些控件显示信息列顶部的标题,让用户通过单击标题对信息进行排序。
WC_LISTBOX
创建 listbox 控件。 这些控件包含项列表。
WC_IPADDRESS
创建 IP 地址控件。 这些控件类似于编辑控件,但它们允许你以 Internet 协议 (IP) 格式输入数字地址。
WC_LINK
创建 SysLink 控件。 这些控件包含超文本链接。
WC_LISTVIEW
创建列表视图控件。 这些控件显示项目集合,每个项由图标和标签组成,并提供多种排列项的方法。
WC_NATIVEFONTCTL
创建本机字体控件。 这些是后台工作的不可见控件,使对话框的预定义控件能够显示当前系统语言。
WC_PAGESCROLLER
创建寻呼控件。 这些控件用于包含和滚动另一个窗口。
WC_SCROLLBAR
创建滚动条控件。 这些控件使用户能够滚动窗口的内容。
WC_STATIC
创建静态控件。 这些控件包含不可编辑的文本。
WC_TABCONTROL
创建选项卡控件。 这些控件为窗口或对话框的同一区域定义多个页面。 每个页面由一组信息或应用程序在用户选择相应选项卡时显示的一组控件组成。
WC_TREEVIEW
创建树视图控件。 这些控件显示项的分层列表。 每个项都包含一个标签和一个可选的位图。
进度条实现
普通进度条

Marquee样式进度条

使用 SendMessage 函数调用指定窗口的窗口过程,在窗口过程处理消息之前不会返回。
LRESULT SendMessage(
[in] HWND hWnd,
[in] UINT Msg,
[in] WPARAM wParam,
[in] LPARAM lParam
);
参数
[in] hWnd
类型:HWND
窗口过程的句柄将接收消息。 如果此参数 HWND_BROADCAST ( (HWND) 0xffff) ,则会将消息发送到系统中的所有顶级窗口,包括已禁用或不可见的未所有者窗口、重叠窗口和弹出窗口;但消息不会发送到子窗口。
消息发送受 UIPI 的约束。 进程的线程只能将消息发送到较低或等于完整性级别的线程的消息队列。
[in] Msg
类型: UINT
要发送的消息。
有关系统提供的消息的列表,请参阅 系统定义的消息。
[in] wParam
类型: WPARAM
其他的消息特定信息。
[in] lParam
类型: LPARAM
其他的消息特定信息。
返回值
类型: LRESULT
返回值指定消息处理的结果;这取决于发送的消息。
通过向进度条窗口发送消息可以控制进度条的范围、位置、获取位置等操作
PBM_SETRANGE消息
设置进度栏的最小值和最大值,并重新绘制条以反映新范围。
参数
wParam
必须为零。
lParam
LOWORD 指定最小范围值,HIWORD 指定最大范围值。 最小范围值不得为负值。 默认情况下,最小值为零。 最大范围值必须大于最小范围值。 默认情况下,最大范围值为 100。
返回值
如果成功,则返回以前的区域值,否则返回零。 LOWORD 指定以前的最小值,HIWORD 指定以前的最大值。
PBM_SETPOS消息
设置进度栏的当前位置,并重新绘制条以反映新位置。
参数
wParam
成为新位置的带符号整数。
lParam
必须为零。
返回值
返回上一位置。
PBM_GETPOS消息
检索进度栏的当前位置。
参数
wParam
必须为零。
lParam
必须为零。
返回值
返回一个 UINT 值,该值表示进度栏的当前位置。
PBM_SETMARQUEE消息
如果不知道完成进度量,但希望指示正在进行进度,请使用此消息。
发送 PBM_SETMARQUEE 消息以启动或停止动画。
wParam
指示是打开还是关闭Marquee模式。
lParam
在选线动画更新之间,时间(以毫秒为单位)。 如果此参数为零,则每 30 毫秒更新一次Marquee动画。
返回值
始终返回 TRUE
备注
在尝试启动动画之前,必须将控件样式设置为 PBS_MARQUEE 。
备注
此消息需要ComCtl32.dll版本 6.00 或更高版本。
添加下面的代码,使用新版ComCtl32 6.0控件 进度条才有PBS_MARQUEE属性
#if defined _M_IX86
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_IA64
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_X64
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#else
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif
头文件包含:CommCtrl.h
测试:
main.cpp
//头文件
#include <windows.h>
#include <CommCtrl.h>
//使用ComCtl32 6.0库
#if defined _M_IX86
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_IA64
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_X64
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#else
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif
//宏定义
#define IDC_BUTTON_0 1000
#define IDC_BUTTON_1 1001
#define IDC_PROGRESS_0 1010
#define IDC_PROGRESS_1 1011
//
using namespace std;
//函数声明
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
//变量定义
HWND g_hButton0;
HWND g_hButton1;
HWND g_hProgress0;
HWND g_hProgress1;
//win32入口函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine, int nCmdShow)
{
const char CLASS_NAME[] = "acaca";
WNDCLASSA wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClassA(&wc);
HWND hwnd = CreateWindowExA(
0, // Optional window styles.
CLASS_NAME, // Window class
"TProgress", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, nCmdShow);
//消息循环
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE://窗体创建消息
{
CreateWindow(WC_STATIC,
"MARQUEE",
WS_CHILD | WS_VISIBLE,
10,10,50,30,
hwnd,
NULL,
((LPCREATESTRUCT)lParam)->hInstance,
NULL);
g_hProgress0 = CreateWindowEx(
0,
PROGRESS_CLASS,
NULL,
WS_CHILD | WS_VISIBLE,
70,10,300,30,
hwnd,
(HMENU)IDC_PROGRESS_0,
((LPCREATESTRUCT)lParam)->hInstance,
NULL);
CreateWindow(WC_STATIC,
"normal",
WS_CHILD | WS_VISIBLE,
10,100,50,30,
hwnd,
NULL,
((LPCREATESTRUCT)lParam)->hInstance,
NULL);
g_hProgress1 = CreateWindowEx(
0,
PROGRESS_CLASS,
NULL,
WS_CHILD | WS_VISIBLE,
70,100,300,30,
hwnd,
(HMENU)IDC_PROGRESS_1,
((LPCREATESTRUCT)lParam)->hInstance,
NULL);
//设置进度条1范围和进度
SendMessage( g_hProgress1,PBM_SETRANGE,(WPARAM)0, MAKELPARAM(0,100));
SendMessage( g_hProgress1,PBM_DELTAPOS,(WPARAM)(20), (LPARAM)0 );
g_hButton0 = CreateWindow("BUTTON",
"开始",
WS_CHILD | WS_VISIBLE,
10, 200, 100, 30,
hwnd,
(HMENU)IDC_BUTTON_0,
((LPCREATESTRUCT)lParam)->hInstance,
NULL);
g_hButton1 = CreateWindow("BUTTON",
"停止",
WS_CHILD | WS_VISIBLE,
150, 200, 100, 30,
hwnd,
(HMENU)IDC_BUTTON_1,
((LPCREATESTRUCT)lParam)->hInstance,
NULL);
}
return 0;
case WM_COMMAND:
switch(wParam)
{
case IDC_BUTTON_0:
{
//设置PBS_MARQUEE属性
LONG_PTR style = GetWindowLongPtr(g_hProgress0, GWL_STYLE);
SetWindowLongPtr(g_hProgress0, GWL_STYLE, style|PBS_MARQUEE);
//发送消息让他滚动
SendMessage(g_hProgress0,PBM_SETMARQUEE,true,10);
}
return 0;
case IDC_BUTTON_1:
{
//发送消息让他停止滚动
SendMessage(g_hProgress0,PBM_SETMARQUEE,false,0);
//取消PBS_MARQUEE属性
LONG_PTR style = GetWindowLongPtr(g_hProgress0, GWL_STYLE);
SetWindowLongPtr(g_hProgress0, GWL_STYLE, style^PBS_MARQUEE);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
// All painting occurs here, between BeginPaint and EndPaint.
FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1));
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
