为CListBox加上智能水平滚动条

MFC实现智能水平滚动条,重写滚动条方法 第一步、首先创建添加一个新类 这里以我的项目为例: 右键点击=》类向导 添加一个新类:CDJListBox,基类为:CListBox 接下来VS就会自动帮你生成2个文件:DJListBox.h 和 DJListBox.cpp 我们在DJListBox.h头文件里面添加: 注意看图添加位置 int AddString( LPCTSTR lpszItem ); int m_nMaxWidth; ... 阅读详情
在MFC中,用列表框(CListBox)来显示多个字符串是一种很方便的方法。但缺省的列表框水平滚动条不够智能——这里智能的含义是:在应该出现的时候出现,不应该出现的时候消失,而且应能自动调节自己的大小。本文通过实例说明了存在的问题和解决办法。

一、问题演示

首先用Visual Studio应用向导创建工程CustomCListBox。这是一个基于对话框的应用,向导提供的所有可选参数均采用其缺省值。

在资源编辑器中将对主话框字体设为宋体12,插入一个CListBox控制,设其ID为IDC_LLISTTEST,大小为125 X 84。 请确认列表框的垂直滚动条、水平滚动条有效,取消其排序风格。

启动Class Wizard,选择Member Variables选项卡,为列表框加入对应的成员变量m_lListTest,在Category中选择Control。

接下来在Workspace窗格中选择ClassView,扩展CCustomCListBoxDlg类并双击OnInitDialog(),在编辑窗格中找到注释行“TODO: Add extra initialization here”,在该行下面加入以下内容:

m_lListTest.AddString(_T("One"));
m_lListTest.AddString(_T("Two"));
m_lListTest.AddString(_T("Three"));
m_lListTest.AddString(_T("Four"));
m_lListTest.AddString(_T("Five"));
m_lListTest.AddString(_T("Six"));
m_lListTest.AddString(_T("北国风光,千里冰封,万里雪飘。"));
m_lListTest.AddString(_T("Eight"));
m_lListTest.AddString(_T("Nine"));
m_lListTest.AddString(_T("Ten"));

编译并运行这个工程,可以发现列表框能够正确显示全部内容。

如果在上述m_lListText.AddString(_T"Ten"))后面加入一行:

m_lListTest.AddString(_T("Eleven"));

重新编译并运行该工程,可以发现出现了一个垂直滚动条。垂直滚动条的出现使得列表框水平方向有效显示宽度变小,第七行的内容被切割而不能完整显示。但此时水平滚动条并没有自动出现,第七行被切割部分就无法看到了。

如果我们删除最后加入的语句,把第七行汉字加长到超出列表框显示宽度为止,也可以发现水平滚动条不会自动出现。被切割部分仍旧无法看到。

由此可知,CListBox的水平滚动条并不象垂直滚动条那样“聪明”:垂直滚动条总是能够在需要它的时候自动出现,并能够自动调节自身大小,而水平滚动条不能。

二、解决问题

为提高代码的可重用性,可以创建CListBox的派生类,在派生类中实现“智能”水平滚动条。需要考虑的主要问题包括:跟踪最大字符串宽度(应能适应不同场合下的字体变化),必要时计算垂直滚动条宽度,自动显示和调节水平滚动条的大小。

选菜单 Insert/New Class,设新创建类的名字为CDJListBox,其基类为CListBox,其它选项采用缺省值。单击OK,Visual Studio自动生成DJListBox.cpp和DJListBox.h两个文件。

接下来将主对话框的列表框改为CDJListBox类型,即在CLassView扩展CCustomListBoxDlg类并双击m_lListTest成员,在编辑窗格,修改

CListBox m_lListTest;

为:

CDJListBox m_lListTest;

然后,在类声明代码之前,插入

#include "DJListBox.h"

此时如果重新编译并运行,是无法看到任何实质性的改变的,因为我们并没有修改CDJListBox。所有对于CDJListBox的调用都直接传递给基类CListBox了。

跟踪字符串最大宽度可以通过覆盖CListBox::AddString()实现。打开DJListBox.h,紧接类的析构函数加入如下声明:

int AddString( LPCTSTR lpszItem );

并在实现文件DJListBox.cpp加入该函数框架:

int CDJListBox::AddString(LPCTSTR lpszItem)
{
//此处加入字符串宽度跟踪、水平滚动条显示等代码
}

字符串宽度跟踪可以用整形成员变量m_nMaxWidth实现。在DjListBox.h的protected声明区内,加入以下一行:

int m_nMaxWidth;

在DJListBox.cpp文件,找到CDJListBox的建构函数,为这个最大宽度作初始化:

m_nMaxWidth = 0;

现在可以改动新加入的AddString()了。先应该调用基类AddString(),并用nRet记录其返回值:

int nRet = CListBox::AddString(lpszItem);

接下来调用GetScrollInfo()以获得垂直滚动条的相关信息。这些信息是通过一个SCROLLINFO结构传递的,下面是对该结构初始化并调用GetScrollInfo()的代码:

SCROLLINFO scrollInfo;
memset(&scrollInfo, 0, sizeof(SCROLLINFO));
scrollInfo.cbSize = sizeof(SCROLLINFO);
scrollInfo.fMask = SIF_ALL;
GetScrollInfo(SB_VERT, &scrollInfo, SIF_ALL);

在调试器内观察SCROLLINFO,可以发现要获得nMax和nPage的正确数值,列表框至少应含有一个字符串。SCROLLINFO的成员nPage保存了列表框“每页”能够显示的项目数,nMax是列表框内项目总数。当nMax大于或等于nPage,就出现了垂直滚动条。我们需要知道垂直滚动条的宽度以正确计算列表框的有效显示宽度。这里使用一个初始值为0的整数nScrollWidth表示,并在垂直滚动条显示时将它赋值:

int nScrollWidth = 0;
if(GetCount() > 1 && ((int)scrollInfo.nMax
> = (int)scrollInfo.nPage))
{
nScrollWidth = GetSystemMetrics(SM_CXVSCROLL);
}

接下来声明一个SIZE变量sSize,并实例化对话框的CClientDC:

SIZE sSize;
CClientDC myDC(this);

对话框所采用的字体,有可能是缺省字体,也有可能是有目的的选择。在对话框编辑器中右击对话框,并选择Properties可以查看当前值。虽然MyDC是从列表框取得的,但列表框字体信息并未包含在MyDC中。也就是说,对话框创建时所用字体并没有“选入”CClientDC。要从GetTextExtentPoint32()获得真正的字符串大小,应该先调用GetFont()获得列表框的字体信息,然后将此字体选入MyDC,代码为:

CFont* pListBoxFont = GetFont();
if(pListBoxFont != NULL)
{
CFont* pOldFont =
myDC.SelectObject(pListBoxFont);

现在可以调用GetTextExtendPoint32()函数来获得字符串的宽度了。字符串的宽度由sSize结构的cx成员返回,将该值和已有最大宽度相比较:

GetTextExtentPoint32(myDC.m_hDC,
lpszItem, strlen(lpszItem), &sSize);
m_nMaxWidth = max(m_nMaxWidth, (int)sSize.cx);

剩下的重要工作之一,就是设置水平滚动条的大小了。这可以通过调用SetHorizontalExtent()完成。如果传递给它的整形参数比列表框本身宽度小,则水平滚动条被隐藏。

这里有一个容易被忽略的地方。如果仔细观察CListBox,可以发现文本左边有一栏小小的空白,它的大小为3 。这部分宽度应该加到文本宽度上。如果希望在文本右边也同样空出一栏,则可以在文本宽度上再加3。

SetHorizontalExtent(m_nMaxWidth + 3);

在结束之前,我们需要为MyDC选入原有字体。原有字体保存在pOldFont中:

myDC.SelectObject(pOldFont); }

return nRet;

编译并执行新的代码,可以看到水平滚动条终于能够自动显示了。

三、其它问题

在实际应用中,凡是改变列表框内容的函数都可能影响水平滚动条的显示要求,因而也必须加以定制。但其基本过程——计算文本宽度并按指定大小显示滚动条等,和上述讨论过程是相似的。

CListBox类能够改变列表内容的方法除AddString()外,还有DeleteString(),InsertString(),ResetContent()。其中InsertString()用于在指定位置插入字符串,在本文讨论的主题内它和AddString()是一样的。

DeleteString()删除一个字符串,在派生类中其参考代码如下:

int CDJListBox::DeleteString(UINT nIndex)
{
RECT lRect;
GetWindowRect(&lRect);

int nRet = CListBox::DeleteString(nIndex);

int nBoxWidth = lRect.right - lRect.left;
m_nMaxWidth = nBoxWidth;

SIZE sSize;
CClientDC myDC(this);

int i;
char szEntry[257];

for (i = 0; i nBoxWidth) // 显示水平滚动条
{
ShowScrollBar(SB_HORZ, TRUE);
SetHorizontalExtent(m_nMaxWidth);
}
else
{
ShowScrollBar(SB_HORZ, FALSE);
}
return nRet;
}

ResetContent()用于清除列表框的全部内容。在派生类中其参考代码如下:

void CDJListBox::ResetContent()
{
CListBox::ResetContent();

m_nMaxWidth = 0;
SetHorizontalExtent(0);
}
【VS开发】CListBox智能滚动设置 添加数据以后,再在下面加句, int nCount = m_myListBox.GetCount(); if (nCount > 0) m_myListBox.SetCurSel(nCount - 1);其实是在output页卡中实现自动滚动显示最新添加的info,因为 COutputList m_wndOutputInfo; m_wndOutput.m_wndOutputInfo 阅读详情

相关推荐

为ListBox添加水平滚动条

在MFC中,为ListBox创建水平滚动条,使其在应该出现的时候出现,不应该出现的时候消失,而且应能自动调节自己的大小。

CListBox支持水平滚动条

class CListBoxEx : public CListBox{// Attributespublic: int  m_nMaxWidth;// Operationspublic: int  AddString(LPCTSTR lpszItem); int  DeleteString(int nIndex); int  InsertString(int nIndex,LPCTSTR lpsz

shg104的专栏 2212

MFC自动水平滚动条CListBox

CHorzListBox类继承自CListBox, 可以根据内容自动显示调整水平滚动条

为CListBox加上智能水平滚动条(转)

作者:俞良军提交者:eastvc 发布日期:2004-1-2 20:05:51原文出处:http://www.ccw.com.cn在MFC中,用列表框(CListBox)来显示多个字符串是一种很方便的方法。但缺省的列表框水平滚动条不够智能——这里智能的含义是:在应该出现的时候出现,不应该出现的时候消失,而且应能自动调节自己的大小。本文通过实例说明了存在的问题和解决办法。 一、问题演示 首先

zzh5756712的专栏 841

Listbox设置水平滚动条范围

ListBox设置水平滚动条,包含2个接口: 1.根据字符内容自动设置水平滚动条的长度, 2.手动设置水平滚动条的字符串长度。封装好了接口,可直接调用。

Telegram 担保交易系统搭建指南:安全可靠的交易流程实现

本文介绍了基于Telegram Bot API搭建担保交易系统的完整方案。该系统通过第三方资金托管机制解决买卖双方信任问题,支持"付款后发货"和"收货后放款"的交易流程。文章详细阐述了系统架构设计,包括Telegram Bot交互层、后端业务逻辑层、数据库层和支付接口层。核心实现步骤涵盖:1)订单创建模块处理交易信息;2)支付处理模块集成Stripe Escrow实现资金托管;3)确认收货模块完成资金划转。系统采用PostgreSQL存储交易数据,并通过FastAPI

jingpide9527的博客 1952

CListBox加上水平智能滚动条

CListBox m_strList;CString str;CSize   sz;int     dx=0;CDC*    pDC = m_strList.GetDC();for (int ii=0;ii {    m_strList.GetText( ii, str );    sz = pDC->GetTextExtent(str);if (sz.cx > dx)    dx = s

wyingquan的专栏 1818

Python实战:5分钟搞定N-CMAPSS航空发动机数据集解析(附完整代码)

本文提供了一份针对N-CMAPSS航空发动机数据集的快速解析实战指南。通过Python的h5py和Pandas库,详细演示了如何高效读取HDF5格式文件、理解数据结构、提取关键特征(如传感器数据与剩余使用寿命RUL),并整合为可用于预测性维护分析的DataFrame,帮助研究者和工程师快速上手这一重要的工业时序数据集。

weixin_29083373的博客 279

VC++------------为CListBox加上智能水平滚动条

为CListBox加上智能水平滚动条  ----   为提高代码的可重用性,可以创建CListBox的派生类,在派生类中实现  “智能”水平滚动条。需要考虑的主要问题包括:跟踪最大字符串宽度(应能适  应不同场合下的字体变化),必要时计算垂直滚动条宽度,自动显示和调节水平  滚动条的大小。    ----   选菜单   Insert/New   Class,设新创建类的名字为C

奔跑的蜗牛 3105

用STC8单片机解码EV1527遥控信号:从波形分析到C代码实现(附完整库)

本文详细介绍了如何使用STC8单片机解码EV1527遥控信号,从波形分析到C代码实现的完整过程。内容包括EV1527协议解析、硬件搭建、信号捕获技巧、解码算法实现及优化策略,并附有完整库代码,帮助开发者快速实现智能家居设备的无线控制。

weixin_34093995的博客 295

数据资产目录(SailCatalog)和数据地图(SailMap)

笔者接下来准备开发大数据平台(XSailboat)中的数据资产目录(SailCatalog)和数据地图(SailMap)相关的功能,本文用以记录笔者关于此部分功能的概念梳理和主体功能设计。

OkGogooXSailboat的博客 2327

在vs2005中为listbox加上水平滚动条

【转】VC ListBox添加水平滚动条 2011-05-23 18:09 转载自 feng411215 在MFC中,用列表框(CListBox)来显示多个字符串是一种很方便的方法。 但缺省的列表框水平滚动条不够智能——这里智能的含义是:在应该出现的时候 出现,不应该出现的时候消失,而且应能自动调节自己的大小。本文通过实例 说明了存在的问题和解决办法。

yangdelong0000的专栏 1544

Java开发的企业排班系统

Java开发的企业排班系统,用了springboot框架,人脸识别是采用百度接口的方式实现

自学网站s.jf3q.com,菜鸟的成长之路 6013

可定制字体样式与智能滚动条的MFC CListBox类

可定制字体样式与智能滚动条的MFC CListBox类 去发现同类优质开源项目:https://gitcode.com/ 简介 本资源文件提供了一个功能强大的MFC CListBox派生类,允许用户为列表框中的每一行设置不同的字体样式、大小、颜色以及行间距。此外,该类还具备智能显示和隐藏水平滚动条的功能,使得列表框的显示更加灵活和美观。 功能特点 多样的字体设置:支持为列表框中的每一行设置不同的...

gitblog_09818的博客 568

中文文本纠错实战:pycorrector与kenlm的安装与高效使用指南

本文提供了一份详细的中文文本纠错实战指南,重点介绍了pycorrector与kenlm的安装与高效使用方法。内容涵盖从编译环境准备、依赖安装到核心参数调优、批量处理及领域自适应等全流程,旨在帮助开发者快速部署并优化纠错系统,提升中文文本处理的质量与效率。

weixin_29055699的博客 411

cs231n作业 assignment 1 q1 q2 q3

请先看课程作业地址。有两种做作业的方法,一种是在google Colab上做 (需魔法),另一种就是下载到本地,但是我懒得在本地配置环境,太麻烦了,还得修改一些基础代码,我就直接在google colab上做了google colab 配置环境只需要跟着教程走就好了最后还有一题解答题懒得做的,这个题目做的没啥意思。让我们用简单写法来实现softmax的loss函数与梯度计算。

Leezed525的博客 9277

为CListBox垂直滚动条,自动滚动,文字显示不全问题!

这个题目,其实和我用的项目没什么关系,不过顶一下吧,我主要是用的垂直滚动条。就是滚动条是根据信息自动滚动了,但是文字会显示不全所以还是使用SetCurSel这个接口来直接实现了,毕竟现在要求还不是很严,如果需要的话,可能后期还要改。 int nCount = m_pListBox->GetCount(); if(nCount > 1) { m_pListBox->SetCurSel(nCo

思想的可见性 4183

SAP_SD模块销售利润中心替代简介

SAP SD模块跨公司销售利润中心替代简介 在SAP SD模块中,系统自动生成的财务凭证需要正确反映利润中心归属。当默认利润中心取值不符合业务逻辑时(如跨公司销售、多组织共用工厂等情况),需配置利润中心替代功能。该功能通过事务码0KEM定义替代规则,可根据物料、客户等条件自动替换利润中心字段。系统配置包括创建替代规则、定义先决条件、设置用户出口程序等步骤。对于复杂业务场景,还可通过用户出口或BADI增强实现。利润中心替代能确保销售收入与成本正确核算,避免利润分配错误,满足企业多维度利润分析需求。

我小时候很黑的博客 436
上一篇: 再谈用MFC实现文件拖放到编辑框
下一篇: 带颜色文字的列表框
普通网友
博客等级 码龄22年 1万+粉丝 3156原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值