Win32 组合框控件的使用

⌚Time: 2023-01-15 14:01:48

👨‍💻Author: Jack Ge

使用CreateWindowEx创建ComboBox控件


#define COMBOBOX_0 1000

#define COMBOBOX_1 1001

#define COMBOBOX_2 1002

...

CreateWindowEx(0,//扩展窗体风格

        "ComboBox",//窗体类名称

        NULL,//窗体名字

        WS_VISIBLE| WS_CHILD| WS_BORDER| CBS_HASSTRINGS| CBS_SIMPLE,//窗体风格

        10, 10, 200, 130,//窗体位置和大小

        hwnd,//父窗体句柄

        (HMENU)COMBOBOX_0,//菜单句柄

        ((LPCREATESTRUCT)lParam)->hInstance,//实例句柄

        0);//

通过向组合框发送消息进行操作,消息类型


主题  目录

CB_ADDSTRING    将字符串添加到组合框的列表框中。 如果组合框没有 CBS_SORT 样式,则字符串将添加到列表末尾。 否则,字符串将插入到列表中,并且对列表进行排序。

CB_DELETESTRING 删除组合框的列表框中的字符串。

CB_DIR  将名称添加到组合框显示的列表。 该消息添加与指定字符串和文件属性集匹配的目录和文件的名称。 CB_DIR 还可以将映射的驱动器号添加到列表中。

CB_FINDSTRING   在组合框的列表框中搜索以指定字符串中的字符开头的项目。

CB_FINDSTRINGEXACT  查找与 lParam 参数中指定的字符串匹配的组合框中的第一个列表框字符串。

CB_GETCOMBOBOXINFO  获取有关指定组合框的信息。

CB_GETCOUNT 获取组合框列表框中的项数。

CB_GETCUEBANNER 获取组合框的编辑控件中显示的提示横幅文本。 显式发送此消息或使用 ComboBox_GetCueBannerText 宏发送。

CB_GETCURSEL    应用程序在组合框的列表框中发送 CB_GETCURSEL 消息以检索当前所选项(如果有)的索引。

CB_GETDROPPEDCONTROLRECT    应用程序发送 CB_GETDROPPEDCONTROLRECT 消息以检索组合框的屏幕坐标,该组合框处于下拉状态。

CB_GETDROPPEDSTATE  确定组合框的列表框是否下拉。

CB_GETDROPPEDWIDTH  获取具有 CBS_DROPDOWN 或 CBS_DROPDOWNLIST 样式的组合框列表框的最小允许宽度(以像素为单位)。

CB_GETEDITSEL   获取组合框的编辑控件中当前所选内容的起始和结束字符位置。

CB_GETEXTENDEDUI    确定组合框是具有默认用户界面还是扩展用户界面。

CB_GETHORIZONTALEXTENT  获取列表框可以水平滚动的宽度(以像素为单位), (可滚动宽度) 。 仅当列表框具有水平滚动条时,此选项才适用。

CB_GETITEMDATA  应用程序将 CB_GETITEMDATA 消息发送到组合框,以检索与组合框中指定项关联的应用程序提供的值。

CB_GETITEMHEIGHT    确定组合框中列表项或选择字段的高度。

CB_GETLBTEXT    从组合框列表中获取字符串。

CB_GETLBTEXTLEN 获取组合框中字符串的长度(以字符为单位)。

CB_GETLOCALE    获取组合框的当前区域设置。 区域设置用于确定使用CB_ADDSTRING消息添加CBS_SORT样式和文本的组合框显示文本的正确排序顺序。

CB_GETMINVISIBLE    获取组合框下拉列表中可见项的最小数目。

CB_GETTOPINDEX  应用程序发送 CB_GETTOPINDEX 消息,以检索组合框列表框部分第一个可见项的从零开始的索引。 最初,索引为 0 的项位于列表框的顶部,但如果列表框内容已滚动,则另一个项目可能位于顶部。

CB_INITSTORAGE  应用程序在将大量项添加到组合框的列表框部分之前发送 CB_INITSTORAGE 消息。 此消息分配用于存储列表框项的内存。

CB_INSERTSTRING 将字符串或项数据插入组合框列表中。 与 CB_ADDSTRING 消息不同, CB_INSERTSTRING 消息不会导致具有 CBS_SORT 样式的列表进行排序。

CB_LIMITTEXT    限制用户可在组合框的编辑控件中键入的文本长度。

CB_RESETCONTENT 从列表框中删除所有项,并编辑组合框的控件。

CB_SELECTSTRING 在组合框列表中搜索以指定字符串中的字符开头的项。 如果找到匹配项,则会选择它并将其复制到编辑控件。

CB_SETCUEBANNER 设置组合框的编辑控件显示的提示横幅文本。

CB_SETCURSEL    应用程序发送 CB_SETCURSEL 消息,以在组合框中选择字符串。 如有必要,列表会将字符串滚动到视图中。 组合框的编辑控件中的文本将更改以反映新选择,并删除列表中以前的任何选定内容。

CB_SETDROPPEDWIDTH  应用程序发送 CB_SETDROPPEDWIDTH 消息,以设置具有 CBS_DROPDOWN 或 CBS_DROPDOWNLIST 样式的组合框列表框的最大允许宽度(以像素为单位)。

CB_SETEDITSEL   应用程序发送 CB_SETEDITSEL 消息以选择组合框的编辑控件中的字符。

CB_SETEXTENDEDUI    应用程序发送 CB_SETEXTENDEDUI 消息,以选择具有 CBS_DROPDOWN 或 CBS_DROPDOWNLIST 样式的组合框的默认 UI 或扩展 UI。

CB_SETHORIZONTALEXTENT  应用程序发送 CB_SETHORIZONTALEXTENT 消息以设置宽度(以像素为单位),列表框可以水平滚动 (可滚动宽度) 。 如果列表框的宽度小于此值,水平滚动条水平滚动列表框中的项目。 如果列表框的宽度等于或大于此值,则隐藏水平滚动条;如果组合框具有 CBS_DISABLENOSCROLL 样式,则禁用。

CB_SETITEMDATA  应用程序发送 CB_SETITEMDATA 消息以设置与组合框中指定项关联的值。

CB_SETITEMHEIGHT    应用程序发送 CB_SETITEMHEIGHT 消息以设置组合框中的列表项或选择字段的高度。

CB_SETLOCALE    应用程序发送 CB_SETLOCALE 消息以设置组合框的当前区域设置。 如果组合框具有 使用 CB_ADDSTRING 添加CBS_SORT 样式和 字符串,组合框的区域设置会影响列表项的排序方式。

CB_SETMINVISIBLE    应用程序发送 CB_SETMINVISIBLE 消息,以在组合框的下拉列表中设置最小可见项数。

CB_SETTOPINDEX  应用程序发送 CB_SETTOPINDEX 消息,以确保特定项在组合框的列表框中可见。 系统滚动列表框内容,以便指定的项显示在列表框顶部或已达到最大滚动范围。

CB_SHOWDROPDOWN 应用程序发送 CB_SHOWDROPDOWN 消息以显示或隐藏具有 CBS_DROPDOWN 或 CBS_DROPDOWNLIST 样式的组合框的列表框。

CB_ADDSTRING消息用于向组合框添加消息


wParam

未使用此参数。

lParam

要添加的 NULL 终止字符串的 LPCTSTR 指针。 如果使用所有者绘制样式创建组合框,但

没有 CBS_HASSTRINGS 样式, 则 lParam 参数的值将存储为项数据,而不是将它指向的

字符串。 可以通过发送 CB_GETITEMDATA 或 CB_SETITEMDATA 消息来检索或修改项数

据。

应用程序发送 CB_SETCURSEL 消息,以在组合框中选择字符串。 如有必要,列表会将字

符串滚动到视图中。 组合框的编辑控件中的文本将更改以反映新选定内容,并删除列表

中任何以前的选定内容。


wParam

指定要选择的字符串的从零开始的索引。 如果此参数为 -1,则删除列表中的任何当前选

定内容,并清除编辑控件。

lParam

未使用此参数。

如果消息成功,则返回值是所选项的索引。 如果 wParam 大于列表中的项数,或者 如果

wParam 为 -1,则返回值CB_ERR并清除所选内容。

CB_GETCURSEL消息

应用程序在组合框的列表框中发送 CB_GETCURSEL 消息以检索当前所选项(如果有)的

索引。


wParam

未使用;必须为零。

lParam

未使用;必须为零。

返回值为当前所选项的从零开始的索引。 如果未选择任何项,则CB_ERR。

CB_GETLBTEXT消息

从组合框列表中获取字符串。


wParam

要检索的字符串的从零开始的索引。

lParam

指向接收字符串的缓冲区的指针。 缓冲区必须有足够的空间用于字符串和终止 null 字

符。 可以在CB_GETLBTEXT消息之前发送CB_GETLBTEXTLEN消息,以检索字符串的长度

(以 TCHARs 为单位)。 如果是 ANSI 字符串,则为字节数,但如果它是 Unicode 字符

串,则为字符数。

返回值是字符串的长度(以 TCHAR 为单位),不包括终止 null 字符。 如果 wParam 未

指定有效的索引,则返回值CB_ERR。

示例


            const char* text[4] = {"aaa","bbb","ccc","ddd"};

            for(int i=0; i<4; i++){

                //添加文本到组合框

                SendMessage(GetDlgItem(hwnd,COMBOBOX_0), CB_ADDSTRING, i, (LPARAM)text[i]);

                SendMessage(GetDlgItem(hwnd,COMBOBOX_1), CB_ADDSTRING, i, (LPARAM)text[i]);

                SendMessage(GetDlgItem(hwnd,COMBOBOX_2), CB_ADDSTRING, i, (LPARAM)text[i]);

        

            }

            //设置默认选择文本

            SendMessage(GetDlgItem(hwnd,COMBOBOX_0), CB_SETCURSEL, 0, 0);

            SendMessage(GetDlgItem(hwnd,COMBOBOX_1), CB_SETCURSEL, 0, 0);

            SendMessage(GetDlgItem(hwnd,COMBOBOX_2), CB_SETCURSEL, 0, 0);


通知类型


主题  目录

CBN_CLOSEUP 关闭组合框的列表框时,将发送 CBN_CLOSEUP 通知代码。 组合框的父窗口通过 WM_COMMAND 消息接收此通知代码。

CBN_DBLCLK  当用户双击组合框列表框中的字符串时,将发送 CBN_DBLCLK 通知代码。 组合框的父窗口通过 WM_COMMAND 消息接收此通知代码。

CBN_DROPDOWN    当组合框的列表框即将可见时,将发送 CBN_DROPDOWN 通知代码。 组合框的父窗口通过 WM_COMMAND 消息接收此通知代码。

CBN_EDITCHANGE  用户执行了可能更改组合框的编辑控件部分中的文本的操作后,将发送 CBN_EDITCHANGE 通知代码。 与 CBN_EDITUPDATE 通知代码不同,系统更新屏幕后会发送此通知代码。 组合框的父窗口通过 WM_COMMAND 消息接收此通知代码。

CBN_EDITUPDATE  当组合框的编辑控件部分即将显示更改的文本时,将发送 CBN_EDITUPDATE 通知代码。 此通知代码在控件设置文本格式后发送,但在显示文本之前。 组合框的父窗口通过 WM_COMMAND 消息接收此通知代码。

CBN_ERRSPACE    当组合框无法分配足够的内存以满足特定请求时,将发送 CBN_ERRSPACE 通知代码。 组合框的父窗口通过 WM_COMMAND 消息接收此通知代码。

CBN_KILLFOCUS   组合框失去键盘焦点时,将发送 CBN_KILLFOCUS 通知代码。 组合框的父窗口通过 WM_COMMAND 消息接收此通知代码。

CBN_SELCHANGE   当用户更改组合框列表框中的当前选定内容时,将发送 CBN_SELCHANGE 通知代码。 用户可以通过单击列表框或使用箭头键来更改选择。 组合框的父窗口以 WM_COMMAND 消息的形式接收此通知,该消息采用 wParam 参数的高序单词CBN_SELCHANGE。

CBN_SELENDCANCEL    当用户选择某个项时,将发送 CBN_SELENDCANCEL 通知代码,但随后选择另一个控件或关闭对话框。 它指示用户的初始选择将被忽略。 组合框的父窗口通过 WM_COMMAND 消息接收此通知代码。

CBN_SELENDOK    当用户选择列表项或选择某个项,然后关闭列表时,将发送 CBN_SELENDOK 通知代码。 它指示要处理用户的选择。 组合框的父窗口通过 WM_COMMAND 消息接收此通知代码。

CBN_SETFOCUS    当组合框接收键盘焦点时,将发送 CBN_SETFOCUS 通知代码。 组合框的父窗口通过 WM_COMMAND 消息接收此通知代码。

WM_COMPAREITEM  系统发送 WM_COMPAREITEM 消息,以确定新项在所有者绘制组合框或列表框的排序列表中的相对位置。 每当应用程序添加新项时,系统就会将此消息发送到使用 CBS_SORT 或 LBS_SORT 样式创建的组合框或列表框的所有者。

WM_DRAWITEM 当按钮、组合框、列表框或菜单的可视方面发生更改时, WM_DRAWITEM 消息将发送到所有者绘制按钮、组合框、列表框或菜单的父窗口。

WM_MEASUREITEM  创建控件或菜单时 ,WM_MEASUREITEM 消息发送到组合框、列表框、列表视图控件或菜单项的所有者窗口。

CBN_SELCHANGE通知代码

当用户在组合框的列表框中更改当前所选内容时发送。 用户可以通过单击列表框或使用

箭头键来更改所选内容。 组合框的父窗口以 WM_COMMAND 消息的形式接收此通知代

码。


CBN_SELCHANGE 

    WPARAM wParam; 

    LPARAM lParam;

    wParam

LOWORD 包含组合框的控制标识符。 HIWORD 指定通知代码。

lParam

组合框的句柄。

若要获取当前所选内容的索引,请将 CB_GETCURSEL 消息发送到控件。

使用CB_SETCURSEL消息设置当前选择时,不会发送 CBN_SELCHANGE 通知代码。 

在窗体过程函数中,对WM_COMMAND消息,判断wParam的低位是否是对应的组合框控件,判断wParam的高位,获取通知类型是否为CBN_SELCHANGE,并进行处理


...

case WM_COMMAND:

        {

            switch(LOWORD(wParam)){

            case COMBOBOX_0:

                {

                    if(HIWORD(wParam) == CBN_SELCHANGE){

                        int iSel;

                            iSel = SendMessage(GetDlgItem(hwnd,COMBOBOX_0), CB_GETCURSEL, 0, 0);

                        char text[128] = {0};

                        SendMessage(GetDlgItem(hwnd,COMBOBOX_0), CB_GETLBTEXT, (WPARAM)iSel, (LPARAM)text);

                        printf("combobox 0 current choose:%s\n",text);  

                }

                    

            }

            break;

示例代码


#include <windows.h>

#include <stdio.h>

#define COMBOBOX_0 1000

#define COMBOBOX_1 1001

#define COMBOBOX_2 1002

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);



int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine, int nCmdShow)

{

    // Register the window class.

    const char CLASS_NAME[]  = "Sample Window Class";



    WNDCLASSA wc = { };



    wc.lpfnWndProc   = WindowProc;

    wc.hInstance     = hInstance;

    wc.lpszClassName = CLASS_NAME;



    RegisterClassA(&wc);



    // Create the window.



    HWND hwnd = CreateWindowExA(

        0,                              // Optional window styles.

        CLASS_NAME,                     // Window class

        "My first window",    // 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);



    // Run the message loop.



    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:

        {

            CreateWindowEx(0,

                        "ComboBox",

                        NULL,

                    WS_VISIBLE| WS_CHILD| WS_BORDER| CBS_HASSTRINGS| CBS_SIMPLE,

                    10, 10, 200, 130,

                        hwnd,

                    (HMENU)COMBOBOX_0,

                        ((LPCREATESTRUCT)lParam)->hInstance,

                        0);

            CreateWindowEx(0,

                        "ComboBox",

                        NULL,

                    WS_VISIBLE| WS_CHILD| WS_BORDER| CBS_HASSTRINGS| CBS_DROPDOWN,

                    230, 10, 200, 130,

                        hwnd,

                    (HMENU)COMBOBOX_1,

                        ((LPCREATESTRUCT)lParam)->hInstance,

                        0);

            CreateWindowEx(0,

                        "ComboBox",

                        NULL,

                    WS_VISIBLE| WS_CHILD| WS_BORDER| CBS_HASSTRINGS| CBS_DROPDOWNLIST,

                    460, 10, 200, 130,

                        hwnd,

                    (HMENU)COMBOBOX_2,

                        ((LPCREATESTRUCT)lParam)->hInstance,

                        0);

            const char* text[4] = {"aaa","bbb","ccc","ddd"};

            for(int i=0; i<4; i++){

                SendMessage(GetDlgItem(hwnd,COMBOBOX_0), CB_ADDSTRING, i, (LPARAM)text[i]);

                SendMessage(GetDlgItem(hwnd,COMBOBOX_1), CB_ADDSTRING, i, (LPARAM)text[i]);

                SendMessage(GetDlgItem(hwnd,COMBOBOX_2), CB_ADDSTRING, i, (LPARAM)text[i]);

        

            }

            SendMessage(GetDlgItem(hwnd,COMBOBOX_0), CB_SETCURSEL, 0, 0);

            SendMessage(GetDlgItem(hwnd,COMBOBOX_1), CB_SETCURSEL, 0, 0);

            SendMessage(GetDlgItem(hwnd,COMBOBOX_2), CB_SETCURSEL, 0, 0);

        }

        return 0;

    case WM_COMMAND:

        {

            switch(LOWORD(wParam)){

            case COMBOBOX_0:

                {

                    if(HIWORD(wParam) == CBN_SELCHANGE){

                        int iSel;

                            iSel = SendMessage(GetDlgItem(hwnd,COMBOBOX_0), CB_GETCURSEL, 0, 0);

                        char text[128] = {0};

                        SendMessage(GetDlgItem(hwnd,COMBOBOX_0), CB_GETLBTEXT, (WPARAM)iSel, (LPARAM)text);

                        printf("combobox 0 current choose:%s\n",text);  

                    }

                    

                }

                break;

            case COMBOBOX_1:

                {

                    if(HIWORD(wParam) == CBN_SELCHANGE){

                        int iSel;

                            iSel = SendMessage(GetDlgItem(hwnd,COMBOBOX_1), CB_GETCURSEL, 0, 0);

                        char text[128] = {0};

                        SendMessage(GetDlgItem(hwnd,COMBOBOX_1), CB_GETLBTEXT, (WPARAM)iSel, (LPARAM)text);

                        printf("combobox 1 current choose:%s\n",text);  

                    }

                    

                }

                break;

            case COMBOBOX_2:

                {

                    if(HIWORD(wParam) == CBN_SELCHANGE){

                        int iSel;

                            iSel = SendMessage(GetDlgItem(hwnd,COMBOBOX_2), CB_GETCURSEL, 0, 0);

                        char text[128] = {0};

                        SendMessage(GetDlgItem(hwnd,COMBOBOX_2), CB_GETLBTEXT, (WPARAM)iSel, (LPARAM)text);

                        printf("combobox 2 current choose:%s\n",text);  

                    }

                    

                }

                break;

            }

            

        }

        return 0;

    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);

}


结果