数学建模社区-数学中国

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

作者: 韩冰    时间: 2005-1-26 12:28
标题: 在C++Builder中实现ListView的列标头点击排序功能
<>  </P>: L# V1 Z1 O( |7 A7 ^3 m) N
<>  </P>" p: W7 T! S9 r7 Y2 Z1 }) v1 q
<>天津大学电子与信息工程学院 </P>
9 N- M+ Y' B1 H& G  |; y<>宋天宁 </P># }) b2 U0 i& b) c9 p, W/ R2 U
<>---- 列表框控件在应用程序中的使用率很高,在Windows中经常见到, </P>
: i/ @3 P2 L5 V<>它有四种常见的式样,分别具有显示大图标,小目标,含有图标的多列列表,含 </P>
1 {3 E( V2 i# F6 f! {$ ?+ {<>有列标头的列表。我们也经常见到一些扩展功能,例如我们在资源管理器中的文 </P>
( q  v7 ^) J5 V0 e# f) ^<>件列表框中,在选用详细资料察看时,用鼠标单击列标头,如大小,则所列文件 </P>6 U1 m9 @( q4 ~) h7 a, A: v
<>按大小排序;单机日期,则按文件日期进行排序.这一功能增强了应用程序的可用 </P>
; w; H+ r/ o: \! r& Y( J& P, t/ U. l- x<>性,使操作更直观、方便。笔者在以Borland C++Builder 3.0(以下简称BCB)作 </P>8 L" j2 p! B- u0 @# I+ ^6 T
<>为开发平台实现这一功能时发现,仅通过设定列表框控件的属性值的方法,只能 </P>$ f, Y2 N7 p3 O6 ]0 q, E' D: P
<>根据项目的首列加以排序,不能根据子项目(SubItems)排序。因此,我们需要编 </P>
3 B" u! E. I; `( k2 B& k3 ^6 K: w<>写自己的代码以完成这一功能。 </P>
6 }) ^2 m& R. W5 ~0 k& @( ^<>  </P>
5 J' u$ S3 z; @4 k<>---- 以下描述如何在BCB开发平台上为列表框添加列标头点击排序功能,当我们 </P>% e* G7 M' v5 r4 v5 S
<>点击的次数为奇数时,所列内容以降序排列;当我们点击的次数为偶数时,所列 </P>
# @0 e9 c! w1 b' Q6 O6 k. |4 {<>内容以升序排列。 </P>6 g: Y5 J# E: Q
<>  </P>/ V- p! w% Z' ~, Y0 p: G1 q- O
<>---- 首先将一个列表框控件安放在Form上,并将其名称设为ListView1。然后在 </P>
4 v# k8 b3 q! h- b1 i<>其中添加若干项目作为试验对象。方法为:用鼠标右键单击控件,在弹出的对话 </P>
. Q7 m# z1 [8 ~( _* M& C<>框中选择Columns Editor用来添加列和子列;再选Items Editor用来添加项目( </P>) p1 Q) s8 k8 L
<>包含子列和主列上的内容)。 </P>. g5 c) c- O, f8 D# T& K, g
<>  </P>  K7 N. r( x  ]2 D/ b% T
<>---- 为了显示出子项目内容,需要在Object Inspector中修改ListView属性值 </P>
9 @$ j, w% O4 B% J0 L+ r1 g<>,将ViewStyle设置为vsReport。另外,还必须将SortType设置为None,以使我 </P>
2 t! F0 D4 g9 K, t, g<>们的排序程序起作用。这样,程序的外观已经符合需要,下面应该增加排序功能 </P>
9 m2 |' i4 `3 L+ i2 k+ ?<>的代码了。为此需要添加类的方法到源代码中。添加位置为: </P>
6 R+ N* h5 c& ~+ M: j/ r. M0 H<>  </P>7 N; e% m; t2 ?2 X/ Z+ P" d# S7 g
<>  </P>
  ]. n7 P) g8 ^2 Q' L& o0 b6 m<>void __fastcall TForm1:istView1ColumnClick </P>
  L4 i1 e: G' N8 n1 [% m<P>(TObject *Sender, </P>3 A: M1 @( L8 r# E. {  e+ Q
<P>TListColumn *Column) </P>
6 t  k# E+ S6 o% [# c& g<P>  </P>
: \( e$ R8 y1 p; P4 B<P>---- 在该方法的传递参数中,指向TListColumn类型的指针Column中含有用户所 </P>& O6 T$ A4 ^1 J0 e$ x
<P>点击的列的信息。 </P>
. {) S7 V6 {, M. M8 F' y<P>---- 下面先定义变量: </P>
* ^1 y4 u' p2 S& q  c<P>  </P>  m) }- U+ Y9 G) G
<P>int i,m,n,j; </P>$ T5 X1 W# z& |9 }& Y8 O
<P>static bool od=true; </P>7 Q" e/ c" X( G9 G
<P>od=!od; </P>
9 }! Q; O  }( F, ]* X% H<P>  </P>! [7 d% @+ \" o  [2 x
<P>---- od代表用户点击的次数,奇数时为true,偶数时为false。注意此处od的存 </P>5 w9 }$ c4 K/ R
<P>储类型设定为static,可以保证其数值的连续性。用n记录用户点击的列号,m记录 </P>
$ Z- W3 k- a# _. X  i* F9 s$ U0 a8 U! t, D<P>列表框中的总项目数。 </P>6 _# p, r. s: E9 ?: n6 r0 I
<P>n=Column- &gt;Index; </P>
7 c: T( U" n) s3 G0 z) p<P>m=ListView1- &gt;Items- &gt;Count; </P>- A! z# H7 |/ y
<P>  </P>
% V( U$ A6 l2 r2 j2 h<P>---- 在列表框中临时添加一个项目作为排序中交换用的临时空间。 </P>+ s! b2 X# S4 U, [1 e5 H9 e' |8 `2 L
<P>ListView1- &gt;Items- &gt;Add(); </P>
5 _  J7 L+ m1 _) W4 I3 e<P>  </P>, I7 ]% W  `, G1 e4 F9 m# ]
<P>---- 当用户点击第一列列标头时,排序按ListView1- &gt;Items- &gt;Item- </P>! S' s: V! l; y) m! u, R
<P>&gt;Caption进行,与其它列不同,所以要单独进行排序。 </P>
* H  o3 W5 W! z( E  f<P>if (n==0) </P>
* u  ^1 P9 G/ d* A4 c0 ~! c% p<P>{ </P>% _! L1 H& }, x) E4 f: c9 p
<P>for(i=0;i&lt; m-1;i++) </P>. ^4 ]; T: x; F1 p0 ?/ R6 `  l( M
<P>for(j=i+1;j&lt; m;j++) </P>1 g+ H# e) Z& X, ]5 K* d) a
<P>if(od) </P>' t4 n% X  _! I+ L7 h- d4 e
<P>{ </P>, H, J2 \- \5 N3 C# d
<P>if(ListView1- &gt;Items- &gt;Item- &gt;Caption &gt; </P>
& L3 N( C8 V+ x8 l+ h<P>ListView1- &gt;Items- &gt;Item[j]- &gt;Caption) </P>2 m6 z) o' W+ e5 O; b2 ?
<P>{ </P>9 i$ P0 b/ P2 Q9 g
<P>ListView1- &gt;Items- &gt;Item[m]= </P>
6 q9 V$ G. z1 _) X) G1 l<P>ListView1- &gt;Items- &gt;Item; </P>
; v$ B- U' l* N: m; M& ]3 Z<P>ListView1- &gt;Items- &gt;Item= </P>
! V$ [) W# p4 C& l<P>ListView1- &gt;Items- &gt;Item[j]; </P>" X# ]. B5 i5 m+ h
<P>ListView1- &gt;Items- &gt;Item[j]= </P>, `3 g: R2 g1 Z3 t
<P>ListView1- &gt;Items- &gt;Item[m]; </P>: d, Q6 y& ^1 ?) F% X% v2 J. z
<P>} </P>
) Y( \$ y1 Q1 \$ c<P>} </P>' Q! r( r0 ~- l4 t
<P>else </P>, b) l* _7 q- g
<P>{ </P>3 C% O( o& R+ k! u3 _  `
<P>if(ListView1- &gt;Items- &gt;Item- &gt;Caption&lt; </P>
# p' d+ t' v( o: G3 F& w<P>ListView1- &gt;Items- &gt;Item[j]- &gt;Caption) </P>  L! m) t& u$ |+ u# Z9 b" r" f' s
<P>{ </P>) k& f9 s% k0 e& W4 c' k
<P>ListView1- &gt;Items- &gt;Item[m]= </P>9 ]% l% S# c0 M; J% R) c5 Z
<P>ListView1- &gt;Items- &gt;Item; </P>
! Z0 z# h) }' }3 @3 k% G5 }<P>ListView1- &gt;Items- &gt;Item= </P>
( [5 m6 O$ R7 @. R6 v  O<P>ListView1- &gt;Items- &gt;Item[j]; </P>
" [% g! r$ \3 O  X! I" U<P>ListView1- &gt;Items- &gt;Item[j]= </P>  t1 ?, {$ q7 O  o9 J
<P>ListView1- &gt;Items- &gt;Item[m]; </P>- V5 F: N+ w8 g2 o+ D! d' {0 A+ Q
<P>} </P>
; Q" ^3 E, u5 l* |  A9 P<P>} </P>
/ q% F# @" s8 Q. \<P>ListView1- &gt;Items- &gt;Delete(m); </P>
/ e  ]% Z' H5 g# d, R* i/ p<P>return; </P>
9 f2 I  l/ `/ ?6 P) T<P>} </P>
  m( g. i4 {6 V) E3 @; Z<P>  </P>
) |& x+ m5 I+ u8 f" a4 J<P>---- 点击其它列时,需要将所点击的列内容从ListView1- &gt;Items- </P>' ]+ m* ?' @! {7 A7 E: `" M
<P>&gt;Item- &gt; SubItems- &gt;Text中抽出,并参照其进行排序。子项目在存储中,形 </P>4 E, D$ \8 t4 ?1 o! @
<P>式为_子项目1\r\n子项目2\r\n子项目3\r\n...子项目N\r\n_。为抽取其中某一 </P>
$ k% ?' g7 e6 H9 _2 o<P>子项目,需编写如下函数,并将其放于void __fastcall TForm1:: </P>
/ Q2 e) U. m" c! E: ~<P>ListView1ColumnClick前面即可。 </P>) f3 k# J. H6 V9 h
<P>#include &lt; vcl/dstring.h &gt; </P>
, Z- q% F9 S" C* b9 D7 Z. E" P<P>AnsiString __stdcall sg(AnsiString str,int n) </P>/ E1 U) u3 o- g( A: p% n5 y! m5 T
<P>{ </P>
! F, v; P' `) S5 ^8 h<P>int l,i; </P>: C4 t. d$ ^/ L& E( \* g0 @; q
<P>AnsiString qq(str); </P>
5 O4 P( ~# z& B! h; I- i4 ]8 D# D4 n<P>l=qq.Length(); </P>6 m- G5 ^9 E- M, n0 d( O5 J" x* e
<P>AnsiString p(str); </P># w+ ~/ w+ m$ o- ?! l3 _9 \
<P>char a[]="\r\n"; </P>1 x: S2 |/ U2 F" u7 j2 i9 W7 o
<P>int j=0,k=0; </P>
( n5 R: K; Z+ B<P>for(j=1;j&lt; l;j++) </P>1 j( {4 ^) Z5 J6 @0 x; d
<P>{ </P>
- m  g/ M- {+ q5 v<P>i=1; </P>
0 d  n( Q4 V9 ]+ C<P>while(qq[j]!=a[0] &amp;&amp; qq[j+1]!=a[1]) </P>( s% n+ s3 e  K, `! `
<P>{ </P>
+ G! V" c+ O/ a  C9 R! ~<P>p[i++]=qq[j]; </P>. }% t+ S0 |6 K  B" X
<P>j++; </P>
0 b& q* R% h* ^6 }( Z" X  H! ~+ |8 v<P>} </P>
  j4 n; d8 R) @0 p- f<P>k++; </P>
7 S1 f, a) N8 `! l: S! S+ O<P>if((k-1)==n) </P>+ ~# W: k% e8 b4 [. T& O9 ]
<P>break; </P>
5 n% ?2 ?$ }* }+ ]<P>} </P>
% g8 ?2 l. g& n0 U  I4 X& [<P>p=NULL; </P>
; d( V( S, z8 `0 ^' M+ c<P>return (p); </P>
! D9 E- B% b' L9 R* Y<P>} </P>
; i! y* Z& l' e<P>  </P>/ @$ j2 r. n* h0 {, d
<P>---- 有了此函数以后,只需将上面的ListView1- &gt;Items- &gt;Item- </P>
$ p& P. p- ~: c1 f<P>&gt;Caption更换为sg(ListView1- &gt;Items- &gt;Item- &gt;SubItems- &gt;Text,n-1)即 </P>4 f. e# A4 e  C- M/ C
<P>可完成对此项目的点击排序功能。 </P>
8 ^' M  M) s) U1 @) w<P>for(i=0;i&lt; m-1;i++) </P>
- B) I' [6 T2 O3 [<P>for(j=i+1;j&lt; m;j++) </P># i& D+ `7 v1 _/ U5 p- X
<P>if(od) </P>
7 k- T# \) y' o9 R  a/ |<P>{ </P>
& H. J/ s6 e. x1 z9 I<P>if(sg(ListView1- &gt;Items- &gt; </P>8 }9 A( N. O# T4 d  l
<P>Item- &gt;SubItems- &gt;Text,n-1) &gt; </P>
4 H, k" y: F) {, w6 m<P>sg(ListView1- &gt;Items- &gt; </P>
$ K3 `7 u' E0 Y) R- V6 r<P>Item[j]- &gt;SubItems- &gt;Text,n-1)) </P>" }& T4 R: Z, y2 r) s7 g

! Q" U0 t: D& T8 n. A<P>// ...以下从略 </P>
$ ]- \$ Z# a0 L<P>  </P>7 j* r3 p5 W5 Q$ y5 K
<P>最后,删除临时的交换项目。 </P>' M. F3 o6 ]# ]9 u& B/ f
<P>ListView1- &gt;Items- &gt;Delete(m); </P>3 N7 J; _6 M% B* p" K
<P>  </P>2 R# Y% F+ F) j! n% i# z. Y
<P>---- 编译运行程序后,即会看到我们预期的结果。另外,本程序是按照字符串方 </P>. g# M7 q5 \$ ]5 ^" Y3 d5 G- d
<P>式进行排序的,如果需要按照数字或其它方式排序,只需进行相应的类型转换即可 </P>
9 X  W5 ~' }' [) _<P>  </P>




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