`
ldb19890624
  • 浏览: 243826 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

在下拉列表框中显示树状结构

 
阅读更多

作者:星轨(oRbIt)
E_Mail :inte2000@163.com
转载请注明原作者,否则请勿转载

在下拉列表框中显示树状结构 下拉列表框(或称组合列表框)是在Windows系统下开发软件最常用的控件之一,该控件适用性强且使用简单,因而深受开发人员喜爱。一个典型的用户界面就是使用下拉列表框(或称组合列表框)显示数据库中相关表名或某个表中的某个字段的全部数据,用户通过鼠标选择某一项后进行相关操作。在这种情况下使用下拉列表框对数据选择可以简化操作,用户也比较喜欢这种方式,但是简单的下拉列表框无法表达数据之间的相互关系,比如两个数据项之间的父子关系或包容关系等。开发人员通常希望能在简化用户操作的同时向用户提供这些信息以方便用户决定下一步操作。针对这种情况我们使用MFC开发了一个支持显示树状结构的CComboBox派生类CWzComboBox,并且该派生类已经成功应用到我们的软件中,现在我们将代码公开,希望对广大开发人员有所帮助,也希望大家共同完善它。(演示程序运行示例如图1所示)

图1 演示程序运行实例

首先我们对CwzComboBox类的自定义函数和相关的数据结构做简要的说明。要使列表框能够显示树状结构,首先应该设计一个数据结构用于记录列表中各个项之间的关系。我们定义了一个结构用于存储节点之间的关系,不妨将之称为信息数据结构,如下所示:

typedef struct tagITEMDATA
{
WORD wParantOriginIdx;
WORD wOriginIdx;
BYTE cType;
BYTE cLevel;
}ITEMDATA,*LPITEMDATA;

结构成员wParantOriginIdx和wOriginIdx分别用以存储该项的父项和该项本身在列表中的原始索引位置,因为添加或删除列表项时会导致列表项之间的顺序改变,也就是索引位置会改变,所以只能通过各项的原始索引位置确定它们之间的关系。成员cType用于存储节点对应的图标在图标列表(ImageList)中的索引位置,成员cLevel用于存储该项的级别,处于根结点的项cLevel是0,子项的cLevel都比父项的大,该成员主要用在显示列表项时确定项的水平起始位置,从而使各项看起来呈树状结构。

下面就详细说明一下类CWzComboBox的设计。基类CComboBox的原来的公有方法 AddString()和InsertString()不支持附加信息不能再使用,DeleteString()无法正确的释放附加信息所占用的内存所以也不能使用,为了防止开发人员误用他们引起代码崩溃,我们重载了这三个函数:

virtual int AddString(LPCTSTR lpszString) { return -1; }
virtual int InsertString(int nIndex, LPCTSTR lpszString) { return -1; }
virtual int DeleteString(int nIndex) { return -1; }

仅仅返回-1表示函数执行失败。手工加入AddCTString()和DeleteCTString()两个函数用于列表项的添加和删除。AddCTString()向第一个参数wParentIdx指定的项添加一个子项,函数运行时首先判断wParentIdx是否是nRootIndex(定义常量nRootIndex等于(WORD)-1),如果是nRootIndex就将该项设为根项,即令cLevel为0。

WORD CWzComboBox::AddCTString(WORD wParentIdx,BYTE cType,LPCTSTR lpszString)
{
int idx = -1;
if(wParentIdx == nRootIndex)//添加根项
{
idx = CComboBox::AddString(lpszString);//调用基类的函数添加该项到列表中
LPITEMDATA pData = new ITEMDATA;//建立相应的项信息结构
ASSERT(pData != NULL); pData->cLevel = 0;//根为0级
pData->cType = cType;
pData->wOriginIdx = (WORD)idx;//该项当前的索引位置
pData->wParantOriginIdx = wParentIdx;//父项的索引位置,就是nRootIndex
SetItemData(idx,(DWORD)pData);
}
else//不是添加根项
{
int ParentCurrentIdx = CurrentIdxFromOriginIdx((int)wParentIdx);//根据父项的原始索引 位置找到父项当前的索引位置
LPITEMDATA pParentData = (LPITEMDATA)GetItemData(ParentCurrentIdx);//读出项信息结构
int count = GetChildCount(pParentData->wOriginIdx);//得到父项的子项个数
int pos = wParentIdx + count + 1;//子项增加一个
idx = CComboBox::InsertString(pos,lpszString);
LPITEMDATA pData = new ITEMDATA;//建立子项的信息结构
ASSERT(pData != NULL);
pData->cLevel = pParentData->cLevel + 1;//比父项的级数大1
pData->cType = cType;
pData->wOriginIdx = (WORD)idx;
pData->wParantOriginIdx = pParentData->wOriginIdx;
SetItemData(idx,(DWORD)pData);
}
return (WORD)idx;//返回索引位置
}

删除某项时首先遍历整个列表,删除所有子项,释放为子项信息结构分配的内存,最后删除该项并释放该项信息结构占用的内存。根据树状结构的特性,某项的所有子项的索引位置都在该项和该项的下一个兄弟项之间,所以删除函数的任务就是删除该项后所有级数比该项高的项,直到遇到第一个级数与该项相同或更小的项。外层的while循环用来删除子项,直到标志bFind是FALSE才退出,内层的for循环从当前项的索引位置开始到列表的结尾搜索当前项的子项,只要找到就将bFind赋值为TRUE并删除该项,然后跳出for循环,继续外层的while循环。

int CWzComboBox::DeleteCTString(int index)//参数为当前项索引位置
{
LPITEMDATA pdata = (LPITEMDATA)GetItemData(index);
BOOL bFind = TRUE; //删除该项的所有子项,包括子项的子项
while(bFind)
{
bFind = FALSE;//只要找到子项就设为TRUE,结束或遇到一个级数相同的项就保持FALSE,结束标 志
int count = GetCount();//得到总的项数
for(int i = index + 1; i < count; i++)//子项的索引位置总在该项之后
{
LPITEMDATA p = (LPITEMDATA)GetItemData(i);
if(p->cLevel > pdata->cLevel)//子项的Level比父项的Level大
{
bFind = TRUE;//找到一个子项,可能还有
CComboBox::DeleteString(i);
break;//删除一个就跳出循环
}
}
}
//现在删除当前项
CComboBox::DeleteString(index);
return GetCount();
}

在删除函数中用到了GetChildCount()和CurrentIdxFromOriginIdx()两个函数,这两个函数被声明为保护成员,不允许直接访问。GetChildCount()返回指定索引位置的项的所有子项,包括子项的子项,实现的方法很简单,就是利用前面提到的树状结构的特性,统计该项后所有级数比该项高的项的个数,直到遇到第一个级数与该项相同或更小的项。CurrentIdxFromOriginIdx()函数根据某项的原始索引位置查找并返回其当前位置索引位置,实现的方法也很简单,就是遍历整个列表,比较每一项的原始索引位置,找到相同的就返回其在列表中的当前索引位置。 以上是对CwzComboBox类的自定义函数和相关的数据结构的说明,现在要解释一下与MFC有关的函数。首先就自绘控件做简要的说明,事实上所有的控件都是“自绘”的,Windows系统的窗口在需要重画窗口内的控件时会向该控件发送WM_DRAWITEM消息,该消息有两个参数,第一个参数是控件的ID,第二个参数是一个指向DRAWITEMSTRUCT结构的指针,DRAWITEMSTRUCT结构含有控件绘制自己所需的显示设备上下文、位置、控件的状态和其他属性,控件就利用这些参数绘制自己。MFC对控件进行了封装,将WM_DRAWITEM消息其映射为虚函数DrawItem,从而简化了编程的复杂性。所以,要实现列表框显示自定义的树状结构只需重载DrawItem函数就可以了。当系统需要绘制列表框时就会多次调用DrawItem来画列表框的每一项。CwzComboBox类重载的DrawItem仅仅就是根据各项的信息结构在相应的位置画出该项,所以不需做太多说明。另一个需要重载的函数是DeleteItem,这也是基类的虚函数,重载此函数的目的是为了使系统删除列表项的同时能释放为该项信息结构分配的存储空间。我们自定义删除函数并没有直接释放信息结构占用的存储空间而是调用了基类的DeleteString函数,由DeleteString函数触发DeleteItem,这样做就简化了开发人员对列表项的维护工作。当下拉列表框被打开时会触发CBN_DROPDOWN事件,CwzComboBox类响应这个事件,计算使列表框中所有项能够完全显示所需的最小宽度值,并根据这个最小宽度值重设列表框的宽度,从而使其看起来有视觉效果好一些。

CwzComboBox类的的使用非常简单,看一下例子代码就知道了。此代码最早是发布在www.codeproject.com网站,所以项目的资源都英文的,注释也是英文的。www.vchelp.net网站也有转载,另外还可以使用以下URL:http://www.winmsg.com/download/cwzcombox.zip下载代码和演示程序。

分享到:
评论

相关推荐

    wpf 下拉列表树状结构显示

    在.NET的C# WPF(Windows Presentation Foundation)框架中,创建一个下拉列表显示树状结构的控件是一项常见的需求,特别是在设计用户界面时需要层级数据的交互。这个标题所指的“wpf 下拉列表树状结构显示”就是...

    树形下拉列表框

    树形下拉列表框是一种交互式的用户界面组件,它结合了传统的下拉列表与树状结构的优点,使得用户在选择时能以层级的方式查看和选择数据。这种组件常见于需要展示具有层次关系的数据集合,例如组织结构、地区分类或者...

    树状结构下拉选

    在描述中提到的"在项目中用到非常不错的树状结构下拉选",可能是指这个组件在实际应用中表现出良好的用户体验,如快速响应、易用性和清晰的视觉反馈。它可能是用于导航、分类选择、多级权限设置或者组织结构展示等...

    实现多选和搜索过滤功能的jQuery下拉列表框插件

    在网页开发中,传统的HTML下拉列表框(`&lt;select&gt;`元素)往往不能满足复杂交互的需求,比如多选和搜索过滤功能。为了解决这个问题,开发者通常会借助于jQuery这样的JavaScript库来增强下拉列表的功能。本文将详细介绍...

    jquery ui 树状下拉选择框

    Comboxtree 是一个结合了下拉框和树形结构的组件,允许用户在下拉列表中看到数据的层级结构,并进行选择。 ##### 4.2 使用方法 1. **引入必要文件**: - 引入 jQuery 和 jQuery EasyUI 的 CSS 及 JS 文件。 - ...

    wpf_combobox_tree下拉树形控件

    在Silverlight中,我们可能有一个树形下拉控件,它可能利用了DataTemplate和VisualTree来呈现树状结构。要将其转换为WPF,我们需要遵循以下步骤: 1. **控件模板**:在WPF中,我们可以使用ControlTemplate来定义...

    目录树下拉列表(TreeComboBox c#)

    在C#编程环境中,`TreeComboBox`控件是一种结合了树形结构和组合框功能的控件,它允许用户在下拉列表中选择一个或多个项,这些项以树状结构呈现。`TreeComboBox`提供了丰富的交互性,使得在用户界面中展示层次数据变...

    树形Combobox

    在描述中提到的"实现了树形Combobox组件ComboTreeCtrl",意味着开发者已经编写了代码来扩展MFC的基础控件,使其具备树状结构的功能。通常,这涉及到重写或扩展MFC的CComboBox类,添加对树结构的支持,包括添加、删除...

    从datawindow的下拉列表中弹出treeview选择框

    本文将详述如何在PowerBuilder环境下,利用DataWindow控件的特性,创建一个从下拉列表中弹出TreeView选择框的功能,这属于界面相关的类技术。 首先,DataWindow是PowerBuilder中的核心组件之一,它用于显示和操作...

    Ext下拉列表树

    Ext下拉列表树是一种在ExtJS框架中实现的组件,它结合了下拉列表和树形结构的功能,为用户提供了一种交互式的、层次化的选择项。这种组件在数据管理、菜单选择、分类筛选等场景中非常常见,尤其适用于需要展现多级...

    能显示树状目录的组合框

    在IT界,尤其是在软件开发中,"能显示树状目录的组合框"是一种常见的用户界面元素,它结合了传统组合框(ComboBox)的功能与树状目录的结构,为用户提供了一种更加直观、高效的导航方式。这种组件常用于文件管理器、...

    C#树形下拉列表控件

    树形下拉列表控件(TreeView with Dropdown)是Windows Forms或WPF应用中的一种交互式UI元素,它结合了传统的下拉列表和树视图的功能,允许用户在层次结构中选择数据。这种控件在需要展示具有分类关系的数据时特别...

    .Net 级联案例,树形控件,下拉列表。

    在.NET框架中,级联(Cascading)是一种常见的数据绑定技术,用于创建相互关联的控件,如树形控件和下拉列表。这种技术能够帮助用户在多个选择之间建立逻辑关系,使得一个控件的选择会影响另一个控件的显示内容。在...

    显示树状目录的组合框

    在Windows编程中,"显示树状目录的组合框"是一个常见的需求,特别是在开发具有文件系统浏览功能的应用程序时。这个标题暗示我们正在讨论一个自定义的控件,它结合了组合框(ComboBox)和树视图(TreeView)的功能。...

    WPF 下拉框树状通用控件

    在Windows Presentation Foundation(WPF)框架中,下拉框树状控件是一种常见的UI元素,它结合了下拉框和树视图的功能,允许用户在有限的空间内展示层级结构的数据。这种控件在多种场景下都非常有用,比如在选择组织...

    ComboxTree(C#下拉框是树形结构)

    "ComboxTree"控件通常是在C#环境下开发的,它允许在下拉列表中展示树形结构数据,这样用户就可以通过展开节点来查看和选择深层次的选项。这种控件在数据层级关系复杂时特别有用,比如组织架构、地区分类或产品类别等...

    下拉树形列表

    在IT界,尤其是在前端开发领域,下拉树形列表是一种常见的交互元素,它结合了下拉菜单和树状结构的特点,使得用户可以在一个简洁的界面中进行多级选择。本篇将深入探讨“下拉树形列表”的相关知识点,以及如何在实际...

    jQuery实现的点击选择框出现树形下拉列表特效源码(插件可修改).zip

    在HTML中,通常使用`&lt;select&gt;`元素创建下拉列表,但该元素无法直接呈现树状结构。利用jQuery,开发者可以创建一个自定义的UI组件,当用户点击一个普通的文本输入框或选择框时,显示一个包含树形结构的下拉列表。这个...

Global site tag (gtag.js) - Google Analytics