数学建模社区-数学中国

标题: 在C++Builder中实现ListView的列标头点击排序功能 [打印本页]

作者: 韩冰    时间: 2005-1-26 12:28
标题: 在C++Builder中实现ListView的列标头点击排序功能
<>  </P>& H% O& ?6 t3 A; f+ I' m! ?" N0 k
<>  </P>9 `3 R8 s/ v, c: B# c
<>天津大学电子与信息工程学院 </P>
2 G& b, P8 s- o( H- S" ~7 n<>宋天宁 </P>- x; O. X& [3 Q; r8 v; G+ i7 [
<>---- 列表框控件在应用程序中的使用率很高,在Windows中经常见到, </P>
. `4 ?$ L7 l% `9 E6 V) z: G<>它有四种常见的式样,分别具有显示大图标,小目标,含有图标的多列列表,含 </P>
: C: t# O. W0 {& e<>有列标头的列表。我们也经常见到一些扩展功能,例如我们在资源管理器中的文 </P>
1 t) q" n6 F& ^: R$ e5 B6 Z<>件列表框中,在选用详细资料察看时,用鼠标单击列标头,如大小,则所列文件 </P>/ s& e0 P  R$ `; l0 g/ R
<>按大小排序;单机日期,则按文件日期进行排序.这一功能增强了应用程序的可用 </P>9 V/ L. ~! t, g
<>性,使操作更直观、方便。笔者在以Borland C++Builder 3.0(以下简称BCB)作 </P>; {; F7 ^2 V8 v7 l4 y# `
<>为开发平台实现这一功能时发现,仅通过设定列表框控件的属性值的方法,只能 </P># K# g, I' Z! Q; q6 j' F
<>根据项目的首列加以排序,不能根据子项目(SubItems)排序。因此,我们需要编 </P>3 F- @1 ?/ I& N+ z' k: f
<>写自己的代码以完成这一功能。 </P>
9 t7 T4 t" I8 I  j) |( X<>  </P>
- S; h/ F4 @4 a' c5 ^& ^2 P<>---- 以下描述如何在BCB开发平台上为列表框添加列标头点击排序功能,当我们 </P>
8 @& V9 u2 a  u/ d<>点击的次数为奇数时,所列内容以降序排列;当我们点击的次数为偶数时,所列 </P>& |( M7 i; z9 _7 e# C
<>内容以升序排列。 </P>
1 ?6 g# ]: }( D8 g8 i( u" m# F; C, K<>  </P>
* z) N4 a3 G3 U/ l6 a4 ?0 y<>---- 首先将一个列表框控件安放在Form上,并将其名称设为ListView1。然后在 </P>5 s# ]* j# P' U0 {
<>其中添加若干项目作为试验对象。方法为:用鼠标右键单击控件,在弹出的对话 </P>
  Q8 T- A, w3 l: b+ {<>框中选择Columns Editor用来添加列和子列;再选Items Editor用来添加项目( </P>9 C( [' P) _4 h) g' I- ]+ z- M
<>包含子列和主列上的内容)。 </P>* u6 D: ^! Z8 T% \: E4 ?9 A8 o
<>  </P>1 Z2 p8 ]$ c; E- r6 T- @7 @+ j- d
<>---- 为了显示出子项目内容,需要在Object Inspector中修改ListView属性值 </P>
% t7 a9 h3 h# b1 {<>,将ViewStyle设置为vsReport。另外,还必须将SortType设置为None,以使我 </P>
8 D( J% R+ Z* j' S<>们的排序程序起作用。这样,程序的外观已经符合需要,下面应该增加排序功能 </P>
. ~: k; w+ l1 V* d- _; e1 @<>的代码了。为此需要添加类的方法到源代码中。添加位置为: </P>) f7 o  J0 d8 o0 \8 _* K
<>  </P>7 A5 `) I$ p! u; y
<>  </P>
0 Y) g3 k$ F$ S0 q! S9 z: z<>void __fastcall TForm1:istView1ColumnClick </P>4 x6 |2 v1 C: b- C
<P>(TObject *Sender, </P>7 n; r; `8 L+ d# R
<P>TListColumn *Column) </P>+ Q: _  P9 h! i' c2 k
<P>  </P>
, M. Y+ u  G4 X. S<P>---- 在该方法的传递参数中,指向TListColumn类型的指针Column中含有用户所 </P>8 \% O7 n" L, \; w
<P>点击的列的信息。 </P>1 s. q, U1 V: {) L0 t
<P>---- 下面先定义变量: </P>/ ~3 b8 f9 Y% m. A& f
<P>  </P>
; b; D, {8 }# d/ ~* P<P>int i,m,n,j; </P>
9 P* M5 e% b" |) ~, s2 ]  y- p<P>static bool od=true; </P>9 g4 J+ T' j2 ?/ t  m5 A0 Z
<P>od=!od; </P>
! F0 `% r; Q6 P; I3 w<P>  </P>
) X6 u8 E8 K! h<P>---- od代表用户点击的次数,奇数时为true,偶数时为false。注意此处od的存 </P>
  S# _9 u& _# z& f0 E* L<P>储类型设定为static,可以保证其数值的连续性。用n记录用户点击的列号,m记录 </P>
$ s/ x$ I  F/ [0 t* ]* x2 G4 J' M<P>列表框中的总项目数。 </P>
- p/ b; k' y% t8 n6 [6 [' F4 K1 Q  M<P>n=Column- &gt;Index; </P>: l* G3 F) n% }9 l
<P>m=ListView1- &gt;Items- &gt;Count; </P>
: A& n+ R) A2 f( p! u/ P<P>  </P>* B) {1 e) ^2 l9 F" D
<P>---- 在列表框中临时添加一个项目作为排序中交换用的临时空间。 </P>5 \9 C  A+ f: l: f
<P>ListView1- &gt;Items- &gt;Add(); </P>( a: H1 }" d/ @! v# K
<P>  </P>/ A4 m4 }* i9 e) `* ^( G; J6 S& J1 r
<P>---- 当用户点击第一列列标头时,排序按ListView1- &gt;Items- &gt;Item- </P>
# U; v( h6 X  k  B<P>&gt;Caption进行,与其它列不同,所以要单独进行排序。 </P>/ I) b( {+ b4 S  z
<P>if (n==0) </P>8 E. k6 [3 I+ _5 y5 c: m' F: _2 U
<P>{ </P>* {9 B6 r$ P* v
<P>for(i=0;i&lt; m-1;i++) </P>2 [" ]. l! A) F( L$ o5 P
<P>for(j=i+1;j&lt; m;j++) </P>; D5 |; ~$ u' b& L# h+ R
<P>if(od) </P>
, Q% L! }' ~. e4 T7 g5 V<P>{ </P>" t, f: K; R4 s0 w3 R+ x, L% x
<P>if(ListView1- &gt;Items- &gt;Item- &gt;Caption &gt; </P>
  P6 m# u, `- M7 P4 X<P>ListView1- &gt;Items- &gt;Item[j]- &gt;Caption) </P>
6 k* `+ v6 O" d8 z( U7 [% n3 [<P>{ </P>
% A' U' ]& c( A9 l) x<P>ListView1- &gt;Items- &gt;Item[m]= </P>* v5 I+ B! T& W) J' b7 ~# ^4 M
<P>ListView1- &gt;Items- &gt;Item; </P>4 e5 V- u" p5 N
<P>ListView1- &gt;Items- &gt;Item= </P>6 _* W$ K% ?, M* A
<P>ListView1- &gt;Items- &gt;Item[j]; </P>) \- }6 T: K9 h  [
<P>ListView1- &gt;Items- &gt;Item[j]= </P>
  `+ K9 J. i, E& W& n# S2 |( Z<P>ListView1- &gt;Items- &gt;Item[m]; </P>$ l9 T) B4 P9 S' `) E. H* S
<P>} </P>
$ R$ b; ~& I& u# N<P>} </P>
) X6 F4 B2 K4 V. u<P>else </P>
  j: T3 n8 \# u<P>{ </P>
9 f( U" a; k! n<P>if(ListView1- &gt;Items- &gt;Item- &gt;Caption&lt; </P>
( v; G7 f  E% b. k+ r  M7 w4 g<P>ListView1- &gt;Items- &gt;Item[j]- &gt;Caption) </P>$ _  @: E# B+ ?, G$ i3 ?
<P>{ </P>
  i7 C2 [8 H7 ~& }7 f) K: P; A<P>ListView1- &gt;Items- &gt;Item[m]= </P>4 W  r2 x! s; p0 [& K6 w
<P>ListView1- &gt;Items- &gt;Item; </P>
: {) ?. D; ]# g8 C<P>ListView1- &gt;Items- &gt;Item= </P>; L8 h( S2 L2 g3 {" H
<P>ListView1- &gt;Items- &gt;Item[j]; </P>" L7 f) ~  L, t( B
<P>ListView1- &gt;Items- &gt;Item[j]= </P>. s/ y4 d. {# d1 a- N' O1 _$ f9 Z
<P>ListView1- &gt;Items- &gt;Item[m]; </P>3 s0 |. L9 F) F1 ]* b' c
<P>} </P>0 i7 x+ v6 X$ C4 S% W. E4 N1 c
<P>} </P>
2 u/ e8 X5 ]7 o6 @8 w* B<P>ListView1- &gt;Items- &gt;Delete(m); </P>
4 Q  N' t) m# s; w" j2 J5 z: n<P>return; </P>! _2 P1 T- a' z% _# R
<P>} </P>
* e, u+ j' a' c, P' m<P>  </P>6 z6 ]% k$ b' Y/ |. x
<P>---- 点击其它列时,需要将所点击的列内容从ListView1- &gt;Items- </P>
- O3 k3 |/ b; P2 k8 d/ w& N<P>&gt;Item- &gt; SubItems- &gt;Text中抽出,并参照其进行排序。子项目在存储中,形 </P>* V& c! u! [9 X* v2 I
<P>式为_子项目1\r\n子项目2\r\n子项目3\r\n...子项目N\r\n_。为抽取其中某一 </P>
' h8 ~, F: V, `" s" D<P>子项目,需编写如下函数,并将其放于void __fastcall TForm1:: </P>
- M" q( b7 ^! J: s<P>ListView1ColumnClick前面即可。 </P>
+ z3 ~: {, [8 |5 _2 p# W+ C8 k<P>#include &lt; vcl/dstring.h &gt; </P>
0 i) W% i7 V, M9 A( G<P>AnsiString __stdcall sg(AnsiString str,int n) </P>
' @* G% R7 W3 b3 r- y( [$ G2 z: s<P>{ </P>
# s" W" t! o6 h<P>int l,i; </P>
( V( z  c3 k0 U# s& r<P>AnsiString qq(str); </P>+ Y1 Q0 g2 |+ m4 H& |* Q, T3 o. x
<P>l=qq.Length(); </P>
* s. `" }( j- r6 B! L: r* _<P>AnsiString p(str); </P>
! c2 W' G8 e3 y3 D0 |<P>char a[]="\r\n"; </P>
* R  z  I) o* W  V4 W<P>int j=0,k=0; </P>
3 P- ^8 a+ @6 q4 J" C! o<P>for(j=1;j&lt; l;j++) </P>$ j# i% }  R& e1 a. A
<P>{ </P>6 ^3 k0 ^' f/ C2 f! N+ I& R
<P>i=1; </P>$ V, g" L# i* D- G
<P>while(qq[j]!=a[0] &amp;&amp; qq[j+1]!=a[1]) </P>) `3 p& P/ W8 g% I. m
<P>{ </P>9 t/ d6 k9 f' Q' z  N0 _
<P>p[i++]=qq[j]; </P>
  @, ?5 N# c5 M; ^+ K<P>j++; </P>
" U( d+ T( y3 [5 v) x<P>} </P>
6 y9 }0 x8 \1 D! \* U' @6 Y<P>k++; </P>/ r- q! ?4 z3 @/ |
<P>if((k-1)==n) </P>
  V( t8 u) m4 w0 _<P>break; </P>0 H( r8 [; U, l: t, K
<P>} </P>
( h) V" R5 v/ [) }7 d* V# Y+ f<P>p=NULL; </P>
. v$ d+ F( j# h$ v/ f( m; R9 y6 f' o<P>return (p); </P>
3 Z% x3 ?$ j) j5 [. @<P>} </P>
7 n# {5 y+ h) z& b; P- S, y<P>  </P>
. A2 i: m" a( z! [5 [; O<P>---- 有了此函数以后,只需将上面的ListView1- &gt;Items- &gt;Item- </P># S" v# W1 x1 K& N" z- D" {3 i
<P>&gt;Caption更换为sg(ListView1- &gt;Items- &gt;Item- &gt;SubItems- &gt;Text,n-1)即 </P>7 |( y0 r0 ^" p$ u/ t, _
<P>可完成对此项目的点击排序功能。 </P>
3 y0 M+ ]$ k/ d8 i/ ~6 Y( L<P>for(i=0;i&lt; m-1;i++) </P>' U7 p" o0 J9 k" ?# q! \% A
<P>for(j=i+1;j&lt; m;j++) </P>9 p/ J0 x/ f! f  Q
<P>if(od) </P>6 Z1 k6 F$ ~! V7 y" c6 X) b! m( @) A
<P>{ </P>
. w6 }' L$ Y, h! c1 ^& Q4 e<P>if(sg(ListView1- &gt;Items- &gt; </P>7 ~- m. J9 b, h, a) ?7 w/ z* d% P$ o
<P>Item- &gt;SubItems- &gt;Text,n-1) &gt; </P>
4 U" }! a3 n$ J# S- `  q9 g<P>sg(ListView1- &gt;Items- &gt; </P>
+ H- I' X7 ~" o$ C<P>Item[j]- &gt;SubItems- &gt;Text,n-1)) </P>: r4 s+ h  \$ U' P

2 T( M4 i# ~! W  m* j<P>// ...以下从略 </P>8 F! |6 G$ P0 ]# ~( J
<P>  </P>$ }6 }3 Y$ Z0 Q. K
<P>最后,删除临时的交换项目。 </P>
5 `+ z: n9 H# O: W4 ~<P>ListView1- &gt;Items- &gt;Delete(m); </P>: i4 v0 N0 m3 u! O
<P>  </P>
* `# n9 w- T3 s7 o- M<P>---- 编译运行程序后,即会看到我们预期的结果。另外,本程序是按照字符串方 </P>
8 y$ f1 |! r: t4 H+ @% v0 v<P>式进行排序的,如果需要按照数字或其它方式排序,只需进行相应的类型转换即可 </P>
1 N! ^" T6 {# X8 g& e<P>  </P>




欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5