韩冰 发表于 2005-1-26 12:28

在C++Builder中实现ListView的列标头点击排序功能

<P>  </P>
<P>  </P>
<P>天津大学电子与信息工程学院 </P>
<P>宋天宁 </P>
<P>---- 列表框控件在应用程序中的使用率很高,在Windows中经常见到, </P>
<P>它有四种常见的式样,分别具有显示大图标,小目标,含有图标的多列列表,含 </P>
<P>有列标头的列表。我们也经常见到一些扩展功能,例如我们在资源管理器中的文 </P>
<P>件列表框中,在选用详细资料察看时,用鼠标单击列标头,如大小,则所列文件 </P>
<P>按大小排序;单机日期,则按文件日期进行排序.这一功能增强了应用程序的可用 </P>
<P>性,使操作更直观、方便。笔者在以Borland C++Builder 3.0(以下简称BCB)作 </P>
<P>为开发平台实现这一功能时发现,仅通过设定列表框控件的属性值的方法,只能 </P>
<P>根据项目的首列加以排序,不能根据子项目(SubItems)排序。因此,我们需要编 </P>
<P>写自己的代码以完成这一功能。 </P>
<P>  </P>
<P>---- 以下描述如何在BCB开发平台上为列表框添加列标头点击排序功能,当我们 </P>
<P>点击的次数为奇数时,所列内容以降序排列;当我们点击的次数为偶数时,所列 </P>
<P>内容以升序排列。 </P>
<P>  </P>
<P>---- 首先将一个列表框控件安放在Form上,并将其名称设为ListView1。然后在 </P>
<P>其中添加若干项目作为试验对象。方法为:用鼠标右键单击控件,在弹出的对话 </P>
<P>框中选择Columns Editor用来添加列和子列;再选Items Editor用来添加项目( </P>
<P>包含子列和主列上的内容)。 </P>
<P>  </P>
<P>---- 为了显示出子项目内容,需要在Object Inspector中修改ListView属性值 </P>
<P>,将ViewStyle设置为vsReport。另外,还必须将SortType设置为None,以使我 </P>
<P>们的排序程序起作用。这样,程序的外观已经符合需要,下面应该增加排序功能 </P>
<P>的代码了。为此需要添加类的方法到源代码中。添加位置为: </P>
<P>  </P>
<P>  </P>
<P>void __fastcall TForm1::ListView1ColumnClick </P>
<P>(TObject *Sender, </P>
<P>TListColumn *Column) </P>
<P>  </P>
<P>---- 在该方法的传递参数中,指向TListColumn类型的指针Column中含有用户所 </P>
<P>点击的列的信息。 </P>
<P>---- 下面先定义变量: </P>
<P>  </P>
<P>int i,m,n,j; </P>
<P>static bool od=true; </P>
<P>od=!od; </P>
<P>  </P>
<P>---- od代表用户点击的次数,奇数时为true,偶数时为false。注意此处od的存 </P>
<P>储类型设定为static,可以保证其数值的连续性。用n记录用户点击的列号,m记录 </P>
<P>列表框中的总项目数。 </P>
<P>n=Column- &gt;Index; </P>
<P>m=ListView1- &gt;Items- &gt;Count; </P>
<P>  </P>
<P>---- 在列表框中临时添加一个项目作为排序中交换用的临时空间。 </P>
<P>ListView1- &gt;Items- &gt;Add(); </P>
<P>  </P>
<P>---- 当用户点击第一列列标头时,排序按ListView1- &gt;Items- &gt;Item- </P>
<P>&gt;Caption进行,与其它列不同,所以要单独进行排序。 </P>
<P>if (n==0) </P>
<P>{ </P>
<P>for(i=0;i&lt; m-1;i++) </P>
<P>for(j=i+1;j&lt; m;j++) </P>
<P>if(od) </P>
<P>{ </P>
<P>if(ListView1- &gt;Items- &gt;Item- &gt;Caption &gt; </P>
<P>ListView1- &gt;Items- &gt;Item- &gt;Caption) </P>
<P>{ </P>
<P>ListView1- &gt;Items- &gt;Item= </P>
<P>ListView1- &gt;Items- &gt;Item; </P>
<P>ListView1- &gt;Items- &gt;Item= </P>
<P>ListView1- &gt;Items- &gt;Item; </P>
<P>ListView1- &gt;Items- &gt;Item= </P>
<P>ListView1- &gt;Items- &gt;Item; </P>
<P>} </P>
<P>} </P>
<P>else </P>
<P>{ </P>
<P>if(ListView1- &gt;Items- &gt;Item- &gt;Caption&lt; </P>
<P>ListView1- &gt;Items- &gt;Item- &gt;Caption) </P>
<P>{ </P>
<P>ListView1- &gt;Items- &gt;Item= </P>
<P>ListView1- &gt;Items- &gt;Item; </P>
<P>ListView1- &gt;Items- &gt;Item= </P>
<P>ListView1- &gt;Items- &gt;Item; </P>
<P>ListView1- &gt;Items- &gt;Item= </P>
<P>ListView1- &gt;Items- &gt;Item; </P>
<P>} </P>
<P>} </P>
<P>ListView1- &gt;Items- &gt;Delete(m); </P>
<P>return; </P>
<P>} </P>
<P>  </P>
<P>---- 点击其它列时,需要将所点击的列内容从ListView1- &gt;Items- </P>
<P>&gt;Item- &gt; SubItems- &gt;Text中抽出,并参照其进行排序。子项目在存储中,形 </P>
<P>式为_子项目1\r\n子项目2\r\n子项目3\r\n...子项目N\r\n_。为抽取其中某一 </P>
<P>子项目,需编写如下函数,并将其放于void __fastcall TForm1:: </P>
<P>ListView1ColumnClick前面即可。 </P>
<P>#include &lt; vcl/dstring.h &gt; </P>
<P>AnsiString __stdcall sg(AnsiString str,int n) </P>
<P>{ </P>
<P>int l,i; </P>
<P>AnsiString qq(str); </P>
<P>l=qq.Length(); </P>
<P>AnsiString p(str); </P>
<P>char a[]="\r\n"; </P>
<P>int j=0,k=0; </P>
<P>for(j=1;j&lt; l;j++) </P>
<P>{ </P>
<P>i=1; </P>
<P>while(qq!=a &amp;&amp; qq!=a) </P>
<P>{ </P>
<P>p=qq; </P>
<P>j++; </P>
<P>} </P>
<P>k++; </P>
<P>if((k-1)==n) </P>
<P>break; </P>
<P>} </P>
<P>p=NULL; </P>
<P>return (p); </P>
<P>} </P>
<P>  </P>
<P>---- 有了此函数以后,只需将上面的ListView1- &gt;Items- &gt;Item- </P>
<P>&gt;Caption更换为sg(ListView1- &gt;Items- &gt;Item- &gt;SubItems- &gt;Text,n-1)即 </P>
<P>可完成对此项目的点击排序功能。 </P>
<P>for(i=0;i&lt; m-1;i++) </P>
<P>for(j=i+1;j&lt; m;j++) </P>
<P>if(od) </P>
<P>{ </P>
<P>if(sg(ListView1- &gt;Items- &gt; </P>
<P>Item- &gt;SubItems- &gt;Text,n-1) &gt; </P>
<P>sg(ListView1- &gt;Items- &gt; </P>
<P>Item- &gt;SubItems- &gt;Text,n-1)) </P>

<P>// ...以下从略 </P>
<P>  </P>
<P>最后,删除临时的交换项目。 </P>
<P>ListView1- &gt;Items- &gt;Delete(m); </P>
<P>  </P>
<P>---- 编译运行程序后,即会看到我们预期的结果。另外,本程序是按照字符串方 </P>
<P>式进行排序的,如果需要按照数字或其它方式排序,只需进行相应的类型转换即可 </P>
<P>  </P>
页: [1]
查看完整版本: 在C++Builder中实现ListView的列标头点击排序功能