数学建模社区-数学中国

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

作者: 韩冰    时间: 2005-1-26 12:28
标题: 在C++Builder中实现ListView的列标头点击排序功能
<>  </P>$ r4 Z  e5 e* M% ^, f4 K6 _
<>  </P>. j- X* Y$ V, _, |/ ^) f; y( h
<>天津大学电子与信息工程学院 </P>" A. @) U) H& J! Q5 a
<>宋天宁 </P>
* ]* u7 O0 N* u2 h: r; l<>---- 列表框控件在应用程序中的使用率很高,在Windows中经常见到, </P>5 h3 q' ]- M" L  w  _
<>它有四种常见的式样,分别具有显示大图标,小目标,含有图标的多列列表,含 </P>
0 A  A* s9 m9 k. S<>有列标头的列表。我们也经常见到一些扩展功能,例如我们在资源管理器中的文 </P>! g) z' M. L8 M- s: D: I
<>件列表框中,在选用详细资料察看时,用鼠标单击列标头,如大小,则所列文件 </P>9 ]: N4 e3 j  d( C& s
<>按大小排序;单机日期,则按文件日期进行排序.这一功能增强了应用程序的可用 </P>$ O3 \& e4 a+ F4 |( b
<>性,使操作更直观、方便。笔者在以Borland C++Builder 3.0(以下简称BCB)作 </P>
! u- ^0 I* A+ |$ u9 ?% u' A" O<>为开发平台实现这一功能时发现,仅通过设定列表框控件的属性值的方法,只能 </P>
; f' _, |& ^0 \& U' R7 y<>根据项目的首列加以排序,不能根据子项目(SubItems)排序。因此,我们需要编 </P>
. i9 v& G7 R1 v  F- P+ P- T. `<>写自己的代码以完成这一功能。 </P>( e4 m% w2 W! G1 K
<>  </P>/ t  D. U0 ^+ W+ H  l, m, j8 N
<>---- 以下描述如何在BCB开发平台上为列表框添加列标头点击排序功能,当我们 </P>& a! p/ [' c$ d9 {. x
<>点击的次数为奇数时,所列内容以降序排列;当我们点击的次数为偶数时,所列 </P># t: z; P+ ~- w
<>内容以升序排列。 </P>
& c* H2 B: f3 |- N: @, L0 b<>  </P>
# h# h8 y! o# n0 C<>---- 首先将一个列表框控件安放在Form上,并将其名称设为ListView1。然后在 </P>
$ ^/ l3 n4 P! k7 R% U1 e7 ^. ^<>其中添加若干项目作为试验对象。方法为:用鼠标右键单击控件,在弹出的对话 </P>. M7 w! U2 D2 d
<>框中选择Columns Editor用来添加列和子列;再选Items Editor用来添加项目( </P>7 Y6 M/ J' f' K  ^& b# T4 ^
<>包含子列和主列上的内容)。 </P>5 l" V1 d; s5 u( X, t: z
<>  </P>1 m% u7 M, k  a1 `
<>---- 为了显示出子项目内容,需要在Object Inspector中修改ListView属性值 </P>
6 r7 D# a6 b8 Z6 l  m<>,将ViewStyle设置为vsReport。另外,还必须将SortType设置为None,以使我 </P>
7 p; K; w0 T# A2 y. h0 c<>们的排序程序起作用。这样,程序的外观已经符合需要,下面应该增加排序功能 </P>
0 V3 E* @8 t6 v! S<>的代码了。为此需要添加类的方法到源代码中。添加位置为: </P>0 r8 t/ ~* T$ c% U. V( A; L( K; ?4 f2 y
<>  </P>! f2 H7 o' f& O/ B# z" B9 B  M
<>  </P>) a- D) J, o* G8 O' x% `
<>void __fastcall TForm1:istView1ColumnClick </P>$ W- U, n( I( |; [' l) v
<P>(TObject *Sender, </P>9 ^8 x: Q* o+ J2 K* l
<P>TListColumn *Column) </P>; p) i7 a& V+ c2 k6 b$ ?
<P>  </P>- Z* g; P" y/ ~0 F1 j% d& v
<P>---- 在该方法的传递参数中,指向TListColumn类型的指针Column中含有用户所 </P>
$ |/ p/ t, p7 {" {<P>点击的列的信息。 </P>1 M: }1 \1 L7 L3 ]7 J
<P>---- 下面先定义变量: </P>
) p9 d9 s* F8 @4 E3 ]6 D/ U2 n5 h<P>  </P>. W, G4 F5 L& {# C- a* [
<P>int i,m,n,j; </P>
4 l6 f* z7 U: y/ |& L<P>static bool od=true; </P>; \2 W8 D' c3 D* x6 t/ V
<P>od=!od; </P>
# }- X' k0 X0 S# O4 j<P>  </P>2 E/ h- b/ k. F0 U# [# r
<P>---- od代表用户点击的次数,奇数时为true,偶数时为false。注意此处od的存 </P>- Q& ^) T2 R5 V) g' `9 v
<P>储类型设定为static,可以保证其数值的连续性。用n记录用户点击的列号,m记录 </P>
) ~8 f2 P9 J5 k) C& E<P>列表框中的总项目数。 </P># e+ h0 F+ q9 M% U6 d- c6 T! F' G; C
<P>n=Column- &gt;Index; </P>
9 A" r  }$ O& X$ w* B, |" S( t( Q4 o<P>m=ListView1- &gt;Items- &gt;Count; </P>
2 l$ L/ r/ P" l/ p<P>  </P>
0 y; b. H6 V# j0 i0 I5 I<P>---- 在列表框中临时添加一个项目作为排序中交换用的临时空间。 </P>' P* a7 Y6 N% ~$ M1 F, L% r8 W5 p
<P>ListView1- &gt;Items- &gt;Add(); </P>
% {8 ~4 R7 U; u<P>  </P>
3 Z+ ]' O  k1 ^4 S' f. m$ F* S<P>---- 当用户点击第一列列标头时,排序按ListView1- &gt;Items- &gt;Item- </P>
9 n7 v: Y! p- I2 K' g<P>&gt;Caption进行,与其它列不同,所以要单独进行排序。 </P>" p1 e5 w  P" ~* B1 V# h
<P>if (n==0) </P>% {3 s) |& ~3 F/ S) |5 u
<P>{ </P>6 Q6 ?2 W% t6 g6 o! V# u: E
<P>for(i=0;i&lt; m-1;i++) </P>& P! c' E8 T3 s9 x' I* S
<P>for(j=i+1;j&lt; m;j++) </P>% }8 B$ M" ~# G0 o) ]% D
<P>if(od) </P>! Y4 d! V" w: Z, J- |  z
<P>{ </P>( X* X  `7 R8 s! r0 T
<P>if(ListView1- &gt;Items- &gt;Item- &gt;Caption &gt; </P>: s; C+ Q  H2 W! a
<P>ListView1- &gt;Items- &gt;Item[j]- &gt;Caption) </P>
& C3 R3 i9 |+ T  ^  c6 v<P>{ </P>: p; N0 t3 n) B9 B+ E! I1 J7 W2 B
<P>ListView1- &gt;Items- &gt;Item[m]= </P>4 s6 j  z6 L3 V" ]" ^
<P>ListView1- &gt;Items- &gt;Item; </P>
' ]; A6 G' G" j  ~: O- f<P>ListView1- &gt;Items- &gt;Item= </P>
8 h" {1 A% }0 m: c<P>ListView1- &gt;Items- &gt;Item[j]; </P>
9 I. q- U( j8 e" k  ]+ o& M) c<P>ListView1- &gt;Items- &gt;Item[j]= </P>: l- G+ P, }2 r7 q- c% ~$ Y& ]
<P>ListView1- &gt;Items- &gt;Item[m]; </P>: F1 x+ E& @" P  O' o
<P>} </P>
" ]4 Z3 o5 X0 P. X$ P1 x( h0 N% J8 M<P>} </P>, V. k' p8 p8 H8 ]" I1 Y. |
<P>else </P>  |$ e' M3 Y' t. ^; {7 o1 S
<P>{ </P>
8 [* p* `% u' V0 ~9 s<P>if(ListView1- &gt;Items- &gt;Item- &gt;Caption&lt; </P>. Z% u1 `; n" g/ Z/ Q8 ]0 }! z; I
<P>ListView1- &gt;Items- &gt;Item[j]- &gt;Caption) </P>$ D* j9 [& ?# _1 Z; X1 l7 M! O
<P>{ </P>
5 X7 @! H5 s1 _9 a, i+ t/ u7 y<P>ListView1- &gt;Items- &gt;Item[m]= </P>
: _3 ]* G, g  _/ x- \<P>ListView1- &gt;Items- &gt;Item; </P>
& ~/ H/ t; g! ~6 w<P>ListView1- &gt;Items- &gt;Item= </P>4 w" U$ \9 {5 q; {- e/ R% {
<P>ListView1- &gt;Items- &gt;Item[j]; </P>
: d0 B8 p: T, L" q: H& F" e7 u( B<P>ListView1- &gt;Items- &gt;Item[j]= </P>
5 o3 n( u% P2 h: C, d3 t<P>ListView1- &gt;Items- &gt;Item[m]; </P>
- c4 L' A1 F4 h& P5 l- b" N4 x$ e<P>} </P>
; g: I% s: U2 u<P>} </P># @8 |5 T, U; K8 h8 B) U
<P>ListView1- &gt;Items- &gt;Delete(m); </P>7 h. W" O+ ^& S& R( c5 ~$ ]- w
<P>return; </P>: T/ ?, ~: Y1 m& _
<P>} </P>2 k" {, M5 g" K) u5 X
<P>  </P>
$ K, O2 N4 @, H<P>---- 点击其它列时,需要将所点击的列内容从ListView1- &gt;Items- </P>
4 @) o# r! c" }" `<P>&gt;Item- &gt; SubItems- &gt;Text中抽出,并参照其进行排序。子项目在存储中,形 </P>( z4 P  Q# F' Q) v" q5 b
<P>式为_子项目1\r\n子项目2\r\n子项目3\r\n...子项目N\r\n_。为抽取其中某一 </P>3 Y3 p' f7 T' c
<P>子项目,需编写如下函数,并将其放于void __fastcall TForm1:: </P>
: m) [& v8 M. h0 J4 y2 Q" g. }+ d<P>ListView1ColumnClick前面即可。 </P>
9 Y0 q' L: q' F<P>#include &lt; vcl/dstring.h &gt; </P>
9 k/ E; S7 |6 Z3 l1 ?. `<P>AnsiString __stdcall sg(AnsiString str,int n) </P>
9 `9 h' O4 a" `2 d% Q8 _<P>{ </P>
" H/ S9 P, ?4 y) l1 D' ?! |<P>int l,i; </P>/ O: r) t5 W9 U* _  w3 t
<P>AnsiString qq(str); </P>5 U/ |. x6 u9 _& e! B
<P>l=qq.Length(); </P>- u, t. O- K2 R9 W# c
<P>AnsiString p(str); </P>
: l- A3 `: q" f7 Q" l: R$ O<P>char a[]="\r\n"; </P>- @7 Q( _, d; `" z1 ~8 F
<P>int j=0,k=0; </P>
9 R* X2 a, z' V- l3 m! P8 Y<P>for(j=1;j&lt; l;j++) </P>
  V% ?  N3 ~1 k8 z  r' v0 c( M<P>{ </P>% t% z: `9 C4 q9 @3 c; X9 ~0 b
<P>i=1; </P>
% b  ]3 y9 {9 G. ^' |<P>while(qq[j]!=a[0] &amp;&amp; qq[j+1]!=a[1]) </P>% N) y; P0 y8 ^& |" W. L
<P>{ </P>
2 V3 Q" T5 C5 s0 v/ P<P>p[i++]=qq[j]; </P>
3 [0 ^: v# a7 B/ y) o' u. ^1 c! ]<P>j++; </P>& O% v; q1 g; F; Q( i. o/ }
<P>} </P>* E+ D, e: ^7 A( L. x4 @
<P>k++; </P>8 }5 r9 V# ]* ?+ o: @
<P>if((k-1)==n) </P>
/ E- r8 ~! h+ H6 t% K5 {  _, A/ {<P>break; </P>4 F- y2 J9 y$ X0 A$ w9 O7 J2 B# H" F
<P>} </P>
5 b. v9 V$ ^  i- Q4 [7 Z" L<P>p=NULL; </P>
) f( Z7 q- D3 U3 c4 _) A<P>return (p); </P>
3 I$ X. P# E* R# ~! u! l1 ~<P>} </P>
( f4 J+ T, D" U* a+ @0 p9 `<P>  </P>" H6 x, H9 w8 e0 f- l
<P>---- 有了此函数以后,只需将上面的ListView1- &gt;Items- &gt;Item- </P>
# a8 m; L# z6 h; G; k$ `3 b3 Z<P>&gt;Caption更换为sg(ListView1- &gt;Items- &gt;Item- &gt;SubItems- &gt;Text,n-1)即 </P>4 R& ]6 I4 ~* [% k' I; }
<P>可完成对此项目的点击排序功能。 </P>
8 F8 p; ^& J* x$ Q( ^' ~$ E<P>for(i=0;i&lt; m-1;i++) </P>& `5 [8 m" ^$ @2 K4 k0 Y! a
<P>for(j=i+1;j&lt; m;j++) </P>. p& X( O* y9 A
<P>if(od) </P>! }0 e/ ]/ t: c. T6 A( P, ?6 `8 a
<P>{ </P>
! l; u$ d& i& y' N8 T6 n' O5 ?<P>if(sg(ListView1- &gt;Items- &gt; </P>
3 m. {2 o: |; ?; C& n. M) r<P>Item- &gt;SubItems- &gt;Text,n-1) &gt; </P>
, g8 ?  k' U) o5 N& b4 @<P>sg(ListView1- &gt;Items- &gt; </P>. K8 p2 f6 l6 D* h4 j
<P>Item[j]- &gt;SubItems- &gt;Text,n-1)) </P>
$ B' g2 Q' `. w/ k5 \  \, i' P2 H5 d4 [7 }
<P>// ...以下从略 </P>
& c/ i# g& W4 v9 E<P>  </P>: {2 ?, s1 @! b- C- E6 K, F3 i
<P>最后,删除临时的交换项目。 </P>4 y( w8 Q( ], [' z
<P>ListView1- &gt;Items- &gt;Delete(m); </P>! U; T! i0 y. m2 l3 f3 `" m" r
<P>  </P>$ ^- ~) a7 g+ n( Q
<P>---- 编译运行程序后,即会看到我们预期的结果。另外,本程序是按照字符串方 </P>
2 F7 T2 [+ ^" s<P>式进行排序的,如果需要按照数字或其它方式排序,只需进行相应的类型转换即可 </P>: D: f2 x; }; C5 K! ~9 R5 c0 W
<P>  </P>




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