Win32 ListBox控件

news2024/12/23 20:58:29

Win32 ListBox控件

创建ListBox控件

  1. 创建窗口函数

    HWND CrateWindowEx(
    	DWORD dwExStyle , // 窗口的扩展风格,基本没用
    	LPCTSTR lpClassName, // 已经注册的窗口类名称
    	LPCTSTR lpWindowName, // 窗口标题栏的名字
    	DWORD dwStyle, // 窗口的基本风格
    	int x, // 左上角水平坐标
    	int y, // 左上角垂直坐标
    	int nWidth,
    	int nHeight,
    	HWND hWndParent, // 窗口的父窗口句柄 --> 如果是子窗口要写这个参数
    	HMENU hMenu,     // 窗口菜单句柄
    	HINSTANCE hInstance, // 应用程序实例句柄 --> WinMain 第一个参数
    	LPVOID lpParam // 窗口创建时附加参数 --> 一般给NULL
    ); // 创建成功返回窗口句柄
    
  2. 创建ListBox

    #define ID_LIST        1001   // 窗口句柄
    
    HWND hListBox = CreateWindowEx(0, TEXT("ListBox"), NULL, WS_VISIBLE | WS_CHILD | WS_BORDER | LBS_HASSTRINGS,10, 10, 200, 200, hWnd, (HMENU)ID_LIST, ((LPCREATESTRUCT)lParam)->hInstance, 0);
    
    const TCHAR *strArray[] = { TEXT("星期一"), TEXT("星期二"), TEXT("星期三"), 
    						  TEXT("星期四"), TEXT("星期五"), TEXT("星期六"), TEXT("星期日")};
    for (int i = 0; i < 7; i++){
        // 添加内容
    	SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)strArray[i]);
    }
    
  3. 效果
    在这里插入图片描述

控件样式

样式说明
LBS_COMBOBOX通知列表框它是组合框的一部分。 这允许两个控件之间的协调,以便它们呈现统一的 UI。 组合框本身必须设置此样式。
LBS_DISABLENOSCROLL当列表框不包含足够的项目滚动时,显示禁用的水平或垂直滚动条。 如果未指定此样式,则当列表框不包含足够的项目时,滚动条将隐藏。 此样式必须与 WS_VSCROLL 或 WS_HSCROLL 样式一起使用。
LBS_EXTENDEDSEL允许使用 SHIFT 键和鼠标或特殊键组合选择多个项。
LBS_HASSTRINGS指定列表框包含由字符串组成的项。 列表框维护字符串的内存和地址,以便应用程序可以使用 LB_GETTEXT 消息检索特定项的文本。 默认情况下,除所有者绘制的列表框之外的所有列表框都具有此样式。 可以创建具有或不带此样式的所有者绘制列表框。对于没有此样式的所有者绘制列表框, LB_GETTEXT 消息检索与项关联的值, (项数据) 。
LBS_MULTICOLUMN指定水平滚动的多列列表框。 列表框自动计算列的宽度,或者应用程序可以使用 LB_SETCOLUMNWIDTH 消息设置宽度。 如果列表框具有 LBS_OWNERDRAWFIXED 样式,则当列表框发送 WM_MEASUREITEM 消息时,应用程序可以设置宽度。具有 LBS_MULTICOLUMN 样式的列表框不能垂直滚动,它忽略它接收的任何 WM_VSCROLL 消息。不能组合 LBS_MULTICOLUMN 和 LBS_OWNERDRAWVARIABLE 样式。 如果同时指定了两者, 则忽略LBS_OWNERDRAWVARIABLE 。
LBS_MULTIPLESEL每次用户单击或双击列表框中的字符串时,都会打开或关闭字符串选择。 用户可以选择任意数量的字符串。
LBS_NODATA指定无数据列表框。 当列表框中的项数超出一千时,请指定此样式。 无数据列表框还必须具有 LBS_OWNERDRAWFIXED 样式,但不得具有 LBS_SORT 或 LBS_HASSTRINGS 样式。无数据列表框类似于所有者描述的列表框,但它不包含项的字符串或位图数据。 用于添加、插入或删除项的命令始终忽略任何指定的项数据;在列表框中查找字符串的请求始终失败。 系统在必须绘制项时将 WM_DRAWITEM 消息发送到所有者窗口。 使用WM_DRAWITEM消息传递的 DRAWITEMSTRUCT 结构的 itemID 成员指定要绘制的项的行号。 无数据列表框不发送 WM_DELETEITEM 消息。
LBS_NOINTEGRALHEIGHT指定列表框的大小正好是应用程序在创建列表框时指定的大小。 通常,系统调整列表框的大小,以便列表框不显示部分项。对于 具有LBS_OWNERDRAWVARIABLE 样式的列表框,始终强制实施 LBS_NOINTEGRALHEIGHT 样式。
LBS_OWNERDRAWFIXED指定列表框的所有者负责绘制其内容,并且列表框中的项目高度相同。 创建列表框时,所有者窗口会收到 WM_MEASUREITEM 消息,当列表框的可视方面发生更改时收到 WM_DRAWITEM 消息。
LBS_SORT按字母顺序对列表框中的字符串进行排序。
LBS_STANDARD按字母顺序对列表框中的字符串进行排序。 每当用户单击列表框项、双击项目或取消所选内容时,父窗口都会收到通知代码。 列表框具有垂直滚动条,其边框位于右侧。 此样式结合了 LBS_NOTIFY、 LBS_SORT、 WS_VSCROLL和 WS_BORDER 样式。
LBS_USETABSTOPS允许列表框在绘制其字符串时识别和展开制表符。 可以使用 LB_SETTABSTOPS 消息指定制表位位置。 默认选项卡位置相隔 32 个对话框模板单位。 对话框模板单元是对话框模板中使用的与设备无关的单位。 若要将度量值从对话框模板单位转换为屏幕单位 (像素) ,请使用 MapDialogRect 函数。
LBS_WANTKEYBOARDINPUT指定每当用户按下键且列表框具有输入焦点时,列表框的所有者将接收 WM_VKEYTOITEM 消息。 这使应用程序能够在键盘输入上执行特殊处理。

控件消息

消息码说明WPARAMLPARAM返回值
LB_ADDSTRING添加字符串到列表项中0LPCTSTRInt
LB_DELETESTRING删除指定字符串项nIndex0Int
LB_GETCOUNT获得列表项的部数00Int
LB_GETCURSEL获得当前选中项的索引00Int
LB_GETITEMDATA获得指定项的附加数据nIndex0DWORD_PTR
LB_GETSEL获得指定项的选中状态nIndex0Int
LB_GETSELCOUNT获得多选项的总数00Int
LB_GETSELITEMS获得选中项的索引数组nMaxArray(数组大小)lpArray(数组)Int
LB_GETTEXT获得指定项的字符串nIndexLPTSTRInt
LB_GETTEXTLEN获得指定项字符串长度nIndex0Int
LB_GETTOPINDEX获得第一个可见项的索引00Int
LB_INSERTSTRING插入字符串项nIndexLPCTSTRInt
LB_RESETCONTENT删除所有的项00Void
LB_SELITEMRANGE范围选择项或取消范围选择BOOL(选择=TRUE,取消=FALSE)DWORD (L=开始选择项的索引,H=结束项的索引)Int
LB_SETCARETINDEX设置指定项获得焦点,并可见nIndexBOOL(FALSE为完全可见,TRUE为部分可见)Int
LB_SETCURSEL设置当前选中的字符串项nIndex0Int
LB_SETITEMDATA设置指定项的附加数据nIndexDWORD_PTRInt
LB_SETSEL设置指定项的选中状态,并获得焦点和可见BOOL 为真突出显示,为FALSE取消突出显示nIndexInt
LB_SETTOPINDEX设置指定项为可见项nIndex0Int

Demo

1. 单击选项弹出消息框显示选择的项
if (LOWORD (wParam) == ID_LIST && HIWORD(wParam) == LBN_SELCHANGE) {
    int iIndex = SendMessage(hListBox, LB_GETCURSEL, 0, 0);
    int iLength = SendMessage(hListBox, LB_GETTEXTLEN, iIndex, 0) + 1;
    TCHAR * pVarName = (TCHAR*)malloc(iLength*sizeof(TCHAR));
    SendMessage(hListBox, LB_GETTEXT, iIndex, (LPARAM)pVarName);
    MessageBox(hWnd, pVarName, TEXT("选择的内容"), MB_OK);
    free(pVarName);
}
2. ListBox重绘

ListBox重绘,实现QQ 消息列表效果

通过指定LBS_OWNERDRAWFIXED样式,可以进行ListBox的重绘。

两个重要消息:WM_DRAWITEMWM_MEASUREITEM

2.1 WM_DRAWITEM 消息

第二个附加参数lParam里包含了控件的相关信息, 其实际类型是DRAWITEMSTRUCT的指针类型

DRAWITEMSTRUCT 原型:

typedef struct tagDRAWITEMSTRUCT {
  UINT      CtlType;
  UINT      CtlID;
  UINT      itemID;
  UINT      itemAction;
  UINT      itemState;
  HWND      hwndItem;
  HDC       hDC;
  RECT      rcItem;
  ULONG_PTR itemData;
} DRAWITEMSTRUCT, *PDRAWITEMSTRUCT, *LPDRAWITEMSTRUCT;
  • CtlType 指定了控件的类型
    在这里插入图片描述

  • CtlID

    组合框、列表框、按钮或静态控件的标识符。 此成员不用于菜单项。

  • itemID

    菜单项的菜单项标识符或列表框或组合框中项的索引。 对于空列表框或组合框,此成员可以是 -1

    这允许应用程序仅在 rcItem 成员指定的坐标处绘制焦点矩形,即使控件中没有项也是如此。 这向用户指示列表框或组合框是否具有焦点。

    itemAction 成员中设置位的方式决定了矩形是否与列表框或组合框具有焦点一样绘制

  • itemAction

    所需的绘图操作。 此成员可以是一个或多个值。
    在这里插入图片描述

  • itemState

    当前绘图操作发生后项的视觉状态。 此成员可以是下表中显示的值的组合。
    在这里插入图片描述

  • hwndItem

    组合框、列表框、按钮和静态控件的控件的句柄。 对于菜单,此成员是包含该项的菜单的句柄。

  • hDC

    设备上下文的句柄;在控件上执行绘图操作时,必须使用此设备上下文。

  • rcItem

    一个矩形,用于定义要绘制的控件的边界。 此矩形位于 hDC 成员指定的设备上下文中。 系统会自动剪辑所有者窗口在组合框、列表框和按钮的设备上下文中绘制的任何内容,但不会剪辑菜单项。 绘制菜单项时,所有者窗口不得在 rcItem 成员定义的矩形边界之外绘制。

  • itemData

    与菜单项关联的应用程序定义值。 对于控件,此参数指定LB_SETITEMDATA或CB_SETITEMDATA消息最后分配给列表框或组合框的值。 如果列表框或组合框具有 LBS_HASSTRINGS或 CBS_HASSTRINGS样式,则此值最初为零。 否则,此值最初是传递给下列消息之一的 lParam 参数中的列表框或组合框的值:

    • CB_ADDSTRING
    • CB_INSERTSTRING
    • LB_ADDSTRING
    • LB_INSERTSTRING

    如果 CtlTypeODT_BUTTONODT_STATIC, 则itemData 为零。

2.2 WM_MEASUREITEM消息

第二个附加参数lParam描述了相关项的绘制信息,其实际类型是MEASUREITEMSTRUCT的指针类型

typedef struct tagMEASUREITEMSTRUCT {
  UINT      CtlType;
  UINT      CtlID;
  UINT      itemID;
  UINT      itemWidth;
  UINT      itemHeight;
  ULONG_PTR itemData;
} MEASUREITEMSTRUCT, *PMEASUREITEMSTRUCT, *LPMEASUREITEMSTRUCT;

大部分字段同DRAWITEMSTRUCT, 两个重要字段itemWidth, itemHeight 指定列表项的宽度和高度

在这里插入图片描述

2.3 重要代码
void SetListBoxItemRect(LPARAM lParam) {
    PMEASUREITEMSTRUCT pmr = (PMEASUREITEMSTRUCT)lParam;
    if (pmr->CtlID == ID_LIST) {
        pmr->itemHeight = 58;
    }
}

void DrawListBoxItem(LPARAM lParam) {
    TCHAR* pVarName;
    PDRAWITEMSTRUCT pdr = (PDRAWITEMSTRUCT)(lParam);
    COLORREF nColor = RGB(66, 66, 66);
    HBRUSH hBursh = NULL;   
    if(pdr->itemState & ODS_SELECTED ) // 选中状态
        hBursh = CreateSolidBrush(RGB(255, 128, 0));
    else
        hBursh = CreateSolidBrush(RGB(255, 255, 255));
    FillRect(pdr->hDC, &pdr->rcItem, hBursh);
    DeleteObject(hBursh);
    int itemLength = SendMessage(hListBox, LB_GETTEXTLEN, pdr->itemID, 0) + 1;
    pVarName = (TCHAR*)malloc(itemLength * sizeof(TCHAR));
    SendMessage(hListBox, LB_GETTEXT, pdr->itemID, (LPARAM)pVarName);

    if (pVarName == NULL) return;
    HBITMAP hBmp = LoadBitmap(hInst, (char*)info_arr[atoi(pVarName)].bitmapId);
    HDC Bhdc = CreateCompatibleDC(pdr->hDC);
    HGDIOBJ oldBMP = SelectObject(Bhdc, hBmp);
    StretchBlt(pdr->hDC, pdr->rcItem.left + 1, pdr->rcItem.top + 1, 56, 56, Bhdc, 0, 0, 100, 100, SRCCOPY);
    HFONT font1 = CreateFont(20,0,0,0,900,NULL,NULL,NULL,GB2312_CHARSET,NULL,NULL,NULL,NULL,"仿宋");
    HFONT font2 = CreateFont(20,0,0,0,800,NULL,NULL,NULL,GB2312_CHARSET,NULL,NULL,NULL,NULL,"方正舒体");
    SetBkMode(pdr->hDC, TRANSPARENT);
    HGDIOBJ oldfont = SelectObject(pdr->hDC, font1);
    nColor = RGB(0, 0, 0);
    SetTextColor(pdr->hDC, nColor);
    TextOut(pdr->hDC, pdr->rcItem.left + 65, pdr->rcItem.top + 5, info_arr[atoi(pVarName)].userName, strlen(info_arr[atoi(pVarName)].userName));
    SelectObject(pdr->hDC, font2);
    nColor = RGB(133, 193, 246);
    SetTextColor(pdr->hDC, nColor);
    TextOut(pdr->hDC, pdr->rcItem.left + 65, pdr->rcItem.top + 30, info_arr[atoi(pVarName)].newData, strlen(info_arr[atoi(pVarName)].newData));
    SelectObject(pdr->hDC, oldfont);
    SelectObject(Bhdc, oldBMP);
    DeleteObject(hBmp);
    DeleteObject(font1);
    DeleteObject(font2);
    DeleteDC(Bhdc);
    free(pVarName);
}
2.4 实现效果

在这里插入图片描述

参考

  1. 基本使用:https://blog.csdn.net/qq_31178679/article/details/125904122

  2. ListBox风格、消息说明:https://www.cnblogs.com/H-R-J/p/11882224.html

  3. ListBox重绘: https://www.freesion.com/article/3893191680/

  4. ListBox简单使用:https://www.codenong.com/cs109127861/

  5. 微软文档:https://learn.microsoft.com/zh-cn/windows/win32/msi/listbox-control

  6. DRAWITEMSTRUCT 结构: https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/ns-winuser-drawitemstruct

项目地址

  • https://github.com/wa-kakalala/QQMsgList

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/404399.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HashMap ConcurrentHashMap介绍

目录 HashMap 数据结构 重要成员变量 Jdk7-扩容死锁分析 单线程扩容 多线程扩容 Jdk8-扩容 ConcurrentHashMap 数据结构 并发安全控制 源码原理分析 重要成员变量 协助扩容helpTransfer 扩容transfer 总结 CopyOnWrite机制 源码原理 HashMap 数据结构 数组…

【题解】百度2020校招Web前端工程师笔试卷(第一批):单选题、多选题

题目来源 若有错误请指正&#xff01; 单选 1 分页存储管理将进程的逻辑地址空间分成若干个页&#xff0c;并为各页加以编号&#xff0c;从0开始&#xff0c;若某一计算机主存按字节编址&#xff0c;逻辑地址和物理地址都是32位&#xff0c;页表项大小为4字节&#xff0c;若…

01.Java的安装

1.JDK&JREJDK : Java SE Development Kit--Java开发工具JRE : Java Runtime Environment--Java运行环境Java编程&#xff0c;需要安装JDK;如果仅仅是运行一款Java程序则只需要运行JREJava的安装包分为两类&#xff1a;一类是JRE--是一个独立的Java运行环境&#xff1b; 一类…

卷积神经网络中的padding理解

前言 在进行卷积神经网络中&#xff0c;经常用到padding&#xff0c;padding在卷积神经网络中起到什么样的作用呢&#xff0c;又是如何发挥作用的呢&#xff1f;本文就此谈下自己看法。 代码中的显示 model.add(Conv2D(filters 32,kernel_size [3,3],strides [1,1],padd…

基于SpringCloud的微服务架构学习笔记(2)注册中心Eureka和负载均衡Ribbon

1. 7 Eureka注册中心 1.7.1 远程调用的问题 地址信息获取&#xff1a;服务消费者如何获取服务提供者的地址信息&#xff08;不能每次都写死&#xff09;&#xff1a; URL&#xff1a;http://localhost:8081/user/"order.getUserId()多选一&#xff1a;如果有多个服务提供…

HBase存储结构、基本架构和shell操作

文章目录一、HBase简介1.1、HBase定义1.2、HBase的存储结构1.3、HBase基本架构二、HBase Shell操作2.1、基本操作2.2、namespace2.3、DDL2.4、DML一、HBase简介 1.1、HBase定义 HBase是一个开源的分布式NoSQL数据库&#xff0c;它是Apache Hadoop项目的一部分&#xff0c;使用…

代码随想录算法训练营 day56 | 动态规划 647. 回文子串 516.最长回文子序列

day56647 回文子串1.确定dp数组&#xff08;dp table&#xff09;以及下标的含义2.确定递推公式3&#xff0c;dp数组如何初始化4.确定遍历顺序5.举例推导dp数组516 最长回文子序列1.确定dp数组&#xff08;dp table&#xff09;以及下标的含义2.确定递推公式3.dp数组如何初始化…

【H2实践】之 SpringBoot 整合

目标 本文紧接上篇【H2实践】之认识 H2&#xff0c;上篇简单介绍了 H2 及其使用&#xff0c;本文继上篇&#xff0c;探索 H2 与 SpringBoot 的整合。 主要实现目标&#xff1a; 1、SpringBoot 连接 H2 内存数据库&#xff0c;并对数据库进行管理。 2、访问 H2 Console 客户端…

Pytest 自动化测试框架

Pytest和Unittest测试框架的区别&#xff1f; 如何区分这两者&#xff0c;很简单unittest作为官方的测试框架&#xff0c;在测试方面更加基础&#xff0c;并且可以再次基础上进行二次开发&#xff0c;同时在用法上格式会更加复杂&#xff1b;而pytest框架作为第三方框架&#x…

52癫痫发作预测的有效双自注意力残差网络

Effective dual self-attentional residual networks for epileptic seizure prediction 摘要 癫痫发作预测作为慢性脑疾病中最具挑战性的数据分析任务之一&#xff0c;引起了众多研究者的广泛关注。癫痫发作预测&#xff0c;可以在许多方面大大提高患者的生活质量&#xff0…

springboot项目配置序列化,反序列化器

介绍本文介绍在项目中时间类型、枚举类型的序列化和反序列化自定义的处理类&#xff0c;也可以使用注解。建议枚举都实现一个统一的接口&#xff0c;方便处理。我这定义了一个Dict接口。枚举类型注解处理这种方式比较灵活&#xff0c;可以让枚举按照自己的方式序列化&#xff0…

三种通用方法——惠普电脑硬盘数据恢复

随着当今数字时代的到来&#xff0c;人们对于计算机硬盘上存储的数据越来越重视。然而&#xff0c;电脑硬盘也时常会发生数据丢失的情况&#xff0c;这时候就需要进行数据恢复。惠普电脑是市面上比较常见的品牌之一&#xff0c;因此本文将从惠普电脑硬盘数据恢复的角度出发&…

【你不知道的事】JavaScript 中用一种更先进的方式进行深拷贝:structuredClone

你是否知道&#xff0c;JavaScript中有一种原生的方法来做对象的深拷贝? 本文我们要介绍的是 structuredClone 函数&#xff0c;它是内置在 JavaScript 运行时中的: const calendarEvent {title: "Builder.io Conf",date: new Date(123),attendees: ["Steve…

EXCEL技能点3-常用技能1

1 引用格式 公式中引用单元格或者区域时,引用的类型可分为以下三种: 绝对引用 相对引用 混合引用 在Excel里&#xff0c;每个单元格都有一个编码&#xff0c;就像人的身份证一样&#xff0c;在Excel里是按照行列进行编码&#xff0c;例如A1就是第一列的第一行。 那么我们想要引…

QEMU启动x86-Linux内核

目录QEMU简介linux启动流程我的环境安装QEMU软件包安装源码安装编译linux内核编译busybox制作initramfs使用QEMU启动linux内核简化命令参考QEMU简介 QEMU&#xff08;quick emulator&#xff09;是一个通用的、开源的硬件模拟器&#xff0c;可以模拟不同硬件架构&#xff08;如…

Docker入门 第四部分

Docker 的优势 Docker 相比于传统虚拟化方式具有更多的优势&#xff1a; Docker 启动快速属于秒级别。虚拟机通常需要几分钟去启动。 Docker 需要的资源更少。Docker 在操作系统级别进行虚拟化&#xff0c;Docker 容器和内核交互&#xff0c;几乎没有性能损耗&#xff0c;性能…

Windows安装Hadoop

当初搭建Hadoop、Hive、HBase、Flink等这些没有截图写文&#xff0c;今为分享特重装。下载Hadoop下载地址&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/apache/hadoop/以管理员身份运行cmd切换到所在目录执行start winrar x -y hadoop-3.3.4.tar.gz&#xff0c;解压。配置…

刚刚和ChatGPT聊了聊隐私计算

开放隐私计算ChatGPT最近太火了&#xff0c;作为一个背后有庞大数据支撑&#xff0c;而且还在不断进化的人工智能&#xff0c;每个人都想和它聊一聊。我们也不例外&#xff0c;于是刚刚和它聊了聊隐私计算那些事儿。先来几个行业问题&#xff0c;毕竟它背后有所有行业新闻、论文…

Python tkinter 如何实现网站下载工具?将所有数据一键获取

前言 铁汁们有没有想过&#xff0c;如何把几个代码的功能结合到一起呢&#xff1f; 有想过的话&#xff0c;有没有实现过呢&#xff1f; 其实很简单的啊&#xff0c;咱就写一个界面就好了&#xff0c;想要哪个代码运行&#xff0c;鼠标轻轻一点就行 开发环境 python 3.8: 解…

【分布式版本控制系统Git】| Git概述、Git安装、Git常用命令

目录 一&#xff1a;概述 1.1. 何为版本控制 1.2. 为什么需要版本控制 1.3. 版本控制工具 1.4. Git 简史 1.5. Git 工作机制 1.6. Git和代码托管中心 二&#xff1a;安装 2.1. Git安装 三&#xff1a;常用命令 3.1 设置用户签名 3.2 初始化本地库 3.3 查看本地库…