24. 下拉框控件

下拉框(Dropdown)控件是一种用于在列表中选择一个或多个元素的控件,我们经常会在网页或者手机APP中见到这种控件。 下拉框控件默认会处于非展开状态并显示当前选定的项目,如果用户点击展开了下拉框控件,则会出现一个列表供用户选择新的项目。

下拉框控件默认开启皮肤色,外观如图 下拉框外观 所示。

下拉框外观

下拉框控件支持5种通知代码,以区分各种不同的操作动作,见表格 下拉框控件支持的通知代码

下拉框控件支持的通知代码

这5种通知代码是作为WM_NOTIFY_PARENT消息的一部分发送到其父窗口的。当用户点击按钮后, 窗口管理器会让下拉框向父窗口发送WM_NOTIFY_PARENT消息,并且会在消息结构的Data.v成员中附加相应的通知代码, 用户程序可以读取此成员来检测不同的按钮动作以及实现各种功能。

同时下拉框控件也支持输入焦点,它可以接收如表格 下拉框支持的按键消息 所示的按键消息。

下拉框支持的按键消息

24.1. 创建下拉框控件

24.1.1. 下拉框控件API

下拉框控件API

24.1.2. 下拉框控件创建函数

24.2. 下拉框控件基础实验

接下来我们来讲解如何以对话框的方式间接创建一个下拉框控件,通过API函数直接创建的实验可参考官方例程WIDGET_Dropdown.c,例程路径如下:

SeggerEval_WIN32_MSVC_MinGW_GUI_V548\Sample\Tutorial\WIDGET_Dropdown.c

24.2.1. 代码分析

24.2.1.1. 创建对话框

代码清单:下拉框-3 创建对话框(DropdownDLG.c文件)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/* 控件ID */
#define ID_FRAMEWIN_0 (GUI_ID_USER + 0x00)
#define ID_DROPDOWN_0 (GUI_ID_USER + 0x01)
#define ID_DROPDOWN_1 (GUI_ID_USER + 0x02)
#define ID_TEXT_0 (GUI_ID_USER + 0x03)

/* 资源表 */
static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = {
    { FRAMEWIN_CreateIndirect, "Framewin", ID_FRAMEWIN_0, 0, 0, 800,
    480, 0, 0x0, 0 },
    { DROPDOWN_CreateIndirect, "Dropdown1", ID_DROPDOWN_0, 150, 180,
    130, 25, 0, 0x0, 0 },
    { DROPDOWN_CreateIndirect, "Dropdown2", ID_DROPDOWN_1, 480, 180,
    130, 25, 0, 0x0, 0 },
    { TEXT_CreateIndirect, "", ID_TEXT_0, 315, 180, 130, 25, 0, 0x0, 0
    },
};

/**
* @brief 以对话框方式间接创建控件
* @note 无
* @param 无
* @retval hWin:资源表中第一个控件的句柄
*/
WM_HWIN CreateFramewin(void)
{
    WM_HWIN hWin;

    hWin = GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(
        _aDialogCreate), _cbDialog, WM_HBKWIN, 0, 0);
    return hWin;
}

代码清单:下拉框-3 中我们定义了4个ID:一个框架窗口ID、2个下拉框控件ID和一个文本控件ID。 你也可以使用emWin预定义好的下拉框控件ID,但最多只有GUI_ID_DROPDOWN0到GUI_ID_DROPDOWN3,共4个ID可供使用。 上述代码中的文本控件,我们用它来显示下拉框中的某个选项。

24.2.1.2. 对话框回调函数

代码清单:下拉框-4 对话框回调函数(DropdownDLG.c文件)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/**
* @brief 对话框回调函数
* @note pMsg:消息指针
* @param 无
* @retval 无
*/
static void _cbDialog(WM_MESSAGE * pMsg)
{
    WM_HWIN hItem;
    int     NCode;
    int     Id;
    int     value;
    char    Dropdown_buf[8] = {0};

    switch (pMsg->MsgId) {
    case WM_INIT_DIALOG:
        /* 初始化Framewin控件 */
        hItem = pMsg->hWin;
        FRAMEWIN_SetFont(hItem, GUI_FONT_32_ASCII);
        FRAMEWIN_SetTitleHeight(hItem, 32);
        FRAMEWIN_SetText(hItem, "STemWIN@EmbedFire STM32F429");
        /* 初始化DROPDOWN0 */
        hItem = WM_GetDialogItem(pMsg->hWin, ID_DROPDOWN_0);
        DROPDOWN_SetListHeight(hItem, 100);
        DROPDOWN_SetFont(hItem, GUI_FONT_24B_1);
        DROPDOWN_AddString(hItem, "Item1-0");
        DROPDOWN_AddString(hItem, "Item1-1");
        DROPDOWN_AddString(hItem, "Item1-2");
        DROPDOWN_AddString(hItem, "Item1-3");
        DROPDOWN_AddString(hItem, "Item1-4");
        DROPDOWN_AddString(hItem, "Item1-5");
        DROPDOWN_AddString(hItem, "Item1-6");
        DROPDOWN_AddString(hItem, "Item1-7");
        DROPDOWN_SetAutoScroll(hItem, 1);
        DROPDOWN_SetScrollbarWidth(hItem, 20);
        /* 初始化DROPDOWN1 */
        hItem = WM_GetDialogItem(pMsg->hWin, ID_DROPDOWN_1);
        DROPDOWN_SetListHeight(hItem, 100);
        DROPDOWN_SetFont(hItem, GUI_FONT_24B_1);
        DROPDOWN_AddString(hItem, "Item2-0");
        DROPDOWN_AddString(hItem, "Item2-1");
        DROPDOWN_AddString(hItem, "Item2-2");
        DROPDOWN_AddString(hItem, "Item2-3");
        DROPDOWN_AddString(hItem, "Item2-4");
        DROPDOWN_AddString(hItem, "Item2-5");
        DROPDOWN_AddString(hItem, "Item2-6");
        DROPDOWN_AddString(hItem, "Item2-7");
        DROPDOWN_SetAutoScroll(hItem, 1);
        DROPDOWN_SetScrollbarWidth(hItem, 20);
        DROPDOWN_SetUpMode(hItem, 1);
        /* 初始化TEXT */
        hItem = WM_GetDialogItem(pMsg->hWin, ID_TEXT_0);
        TEXT_SetTextAlign(hItem, GUI_TA_HCENTER | GUI_TA_VCENTER);
        TEXT_SetFont(hItem, GUI_FONT_COMIC24B_ASCII);
        break;
    case WM_NOTIFY_PARENT:
        Id    = WM_GetId(pMsg->hWinSrc);
        NCode = pMsg->Data.v;
        switch (Id) {
        case ID_DROPDOWN_0: // Notifications sent by 'Dropdown0'
            switch (NCode) {
            case WM_NOTIFICATION_CLICKED:
                break;
            case WM_NOTIFICATION_RELEASED:
                break;
            case WM_NOTIFICATION_SEL_CHANGED:
                hItem = WM_GetDialogItem(pMsg->hWin, ID_DROPDOWN_0);
                value = DROPDOWN_GetSel(hItem);
                DROPDOWN_GetItemText(hItem, value, Dropdown_buf,
                                    GUI_COUNTOF(Dropdown_buf));
                hItem = WM_GetDialogItem(pMsg->hWin, ID_TEXT_0);
                TEXT_SetText(hItem, Dropdown_buf);
                break;
            }
            break;
        case ID_DROPDOWN_1: // Notifications sent by 'Dropdown1'
            switch (NCode) {
            case WM_NOTIFICATION_CLICKED:
                break;
            case WM_NOTIFICATION_RELEASED:
                break;
            case WM_NOTIFICATION_SEL_CHANGED:
                hItem = WM_GetDialogItem(pMsg->hWin, ID_DROPDOWN_1);
                value = DROPDOWN_GetSel(hItem);
                DROPDOWN_GetItemText(hItem, value, Dropdown_buf,
                                    GUI_COUNTOF(Dropdown_buf));
                hItem = WM_GetDialogItem(pMsg->hWin, ID_TEXT_0);
                TEXT_SetText(hItem, Dropdown_buf);
                break;
            }
            break;
        }
        break;
    default:
        WM_DefaultProc(pMsg);
        break;
    }
}
  1. WM_INIT_DIALOG消息

代码清单:下拉框-4 中设置框架窗口的标题栏高度为32像素,字体高度32像素, 并在标题栏中显示 STemWIN@EmbedFire STM32F429

下拉框相关API函数几乎都是使用句柄来操作的,但在建立对话框资源表的时候并没有定义它的句柄, 那就需要通过WM_GetDialogItem函数来自动建立并获取下拉框的句柄。

成功获取句柄后,设置ID_DROPDOWN_0和ID_DROPDOWN_1展开状态的列表高度为100像素,设置字体大小为24, 使能自动使用滚动条并设置滚动条的宽度为20,最后使用DROPDOWN_AddString函数为两个下拉框控件各添加8个选项。 而文本控件ID_TEXT_0只设置文本对齐方式为垂直水平居中及字体24。

  1. WM_NOTIFY_PARENT消息

这个消息是对话框回调函数的重点,所有对话框子控件的具体行为逻辑都在此消息中设置和处理。在此消息中以控件ID来区分各个不同的控件。

下拉框当前选中选项更改后,会进入通知代码WM_NOTIFICATION_SEL_CHANGED。在此通知代码中使用DROPDOWN_GetSel函数获取当前被选中选项的索引号, 接着根据索引号使用DROPDOWN_GetItemText函数返回对应的选项文本信息,然后通过文本控件显示在对话框中。

  1. 其他消息

所有我们不关心或者没有用到的系统消息都可以调用默认消息处理函数WM_DefaultProc进行处理。

24.2.2. 实验现象

下拉框控件基础实验的实验现象如图 下拉框基础实验现象1 和图 下拉框基础实验现象2 所示。

下拉框基础实验现象1 下拉框基础实验现象2