Win32公共控件使用,进度条实现Marquee样式

⌚Time: 2023-01-11 12:25:34

👨‍💻Author: Jack Ge

参考: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);

}