数学建模社区-数学中国

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

作者: 韩冰    时间: 2005-1-26 12:28
标题: 在C++Builder中实现ListView的列标头点击排序功能
<>  </P>
5 ~( J2 v0 m" @7 M+ w0 v8 P<>  </P>2 y$ n6 h. M" |3 e' ?* `
<>天津大学电子与信息工程学院 </P>) y* F/ A) a* U0 C/ n! K; n
<>宋天宁 </P>
% A+ i. U  C# S% r: x+ ]<>---- 列表框控件在应用程序中的使用率很高,在Windows中经常见到, </P>
7 T% p3 s6 }  E2 u<>它有四种常见的式样,分别具有显示大图标,小目标,含有图标的多列列表,含 </P>
% h% W8 t1 N6 _' ?<>有列标头的列表。我们也经常见到一些扩展功能,例如我们在资源管理器中的文 </P>
6 S/ W. ]" K# |1 q$ [0 i3 w! [<>件列表框中,在选用详细资料察看时,用鼠标单击列标头,如大小,则所列文件 </P>: m% N; _: h" s
<>按大小排序;单机日期,则按文件日期进行排序.这一功能增强了应用程序的可用 </P>3 Z  p4 j$ W% f
<>性,使操作更直观、方便。笔者在以Borland C++Builder 3.0(以下简称BCB)作 </P>
3 B; I* c% U# z0 R/ C7 h; n<>为开发平台实现这一功能时发现,仅通过设定列表框控件的属性值的方法,只能 </P>
3 [2 G3 i5 |! a) E1 Y<>根据项目的首列加以排序,不能根据子项目(SubItems)排序。因此,我们需要编 </P>' j/ a: ~& |) u; v& ]9 ~
<>写自己的代码以完成这一功能。 </P>( K+ t  J* N/ m2 F( K3 {# ]
<>  </P>- I5 D1 ?+ [0 f6 [- ], j$ d& d
<>---- 以下描述如何在BCB开发平台上为列表框添加列标头点击排序功能,当我们 </P>
& X/ Z4 W: \* A# ^6 L<>点击的次数为奇数时,所列内容以降序排列;当我们点击的次数为偶数时,所列 </P>
8 }+ K  N! x0 k2 Y! x<>内容以升序排列。 </P>; v/ [$ o( P" Z. i! K! _8 ^% q
<>  </P>: c. h7 ]3 ^! U1 q" P* O: C
<>---- 首先将一个列表框控件安放在Form上,并将其名称设为ListView1。然后在 </P>
  m, s% C( A3 l6 I0 K1 |- @<>其中添加若干项目作为试验对象。方法为:用鼠标右键单击控件,在弹出的对话 </P>  f5 [9 W. a9 q) B" K/ j
<>框中选择Columns Editor用来添加列和子列;再选Items Editor用来添加项目( </P>
( }/ [  }( _5 p: S% B  ]<>包含子列和主列上的内容)。 </P>
  R  v, K5 a! P% |  u<>  </P>
! Q, ^3 g8 c* x, U6 E) F<>---- 为了显示出子项目内容,需要在Object Inspector中修改ListView属性值 </P>5 Y% w2 j- @$ V3 N/ I/ y2 b9 z
<>,将ViewStyle设置为vsReport。另外,还必须将SortType设置为None,以使我 </P>
  c+ k( _2 [2 |# |% W, \; E<>们的排序程序起作用。这样,程序的外观已经符合需要,下面应该增加排序功能 </P>
9 H% G& x8 z: x* I/ @$ w<>的代码了。为此需要添加类的方法到源代码中。添加位置为: </P>
: S! |5 O; l4 _! w<>  </P>
5 g! D* ~! [$ P/ Y8 t<>  </P>/ h' M4 g3 P. S% p' b
<>void __fastcall TForm1:istView1ColumnClick </P>
( ^7 g# ]$ V" I+ `2 D<P>(TObject *Sender, </P>
7 `# K9 k3 b2 F/ j8 X+ M<P>TListColumn *Column) </P>( \  F1 i. X! J1 D# V
<P>  </P>* j5 R6 k& U) D0 o  p# {
<P>---- 在该方法的传递参数中,指向TListColumn类型的指针Column中含有用户所 </P>7 W' H) n( `( P6 L6 o5 M9 t0 S
<P>点击的列的信息。 </P>8 l) d- {2 r7 d. O) d
<P>---- 下面先定义变量: </P>
& A$ X. P: P6 m4 B<P>  </P>: I9 M" a0 ~6 g6 J' D4 p) G1 _
<P>int i,m,n,j; </P>, ~# N1 @7 R' M, {$ \4 z3 W
<P>static bool od=true; </P>5 e4 @- H$ E$ g( a6 t3 U
<P>od=!od; </P>
& P0 S4 {8 u+ R( T& l6 B3 j<P>  </P>$ L, Z2 D( {* m6 q$ \  }  c/ d
<P>---- od代表用户点击的次数,奇数时为true,偶数时为false。注意此处od的存 </P>/ w- V: h0 U' f$ r9 m$ m3 D
<P>储类型设定为static,可以保证其数值的连续性。用n记录用户点击的列号,m记录 </P>& L$ {2 c1 O9 c6 E! c: ?
<P>列表框中的总项目数。 </P>- m4 Z1 s+ h* B$ x  ]) x
<P>n=Column- &gt;Index; </P>2 U3 t: R8 H3 m3 O
<P>m=ListView1- &gt;Items- &gt;Count; </P>
8 v2 N& j8 i; t2 J+ [. h<P>  </P>. Y5 d1 j- k! V+ c+ @
<P>---- 在列表框中临时添加一个项目作为排序中交换用的临时空间。 </P>
: _. |+ x0 \  P& k+ X" V1 {7 ?) W1 \<P>ListView1- &gt;Items- &gt;Add(); </P>! ^( p/ f5 x3 U. Q
<P>  </P>  n+ L4 x/ a# }3 Y- O2 [
<P>---- 当用户点击第一列列标头时,排序按ListView1- &gt;Items- &gt;Item- </P>: p( ~* `3 S: K/ L; z
<P>&gt;Caption进行,与其它列不同,所以要单独进行排序。 </P>
1 C9 e* g, r" x! N# A$ {<P>if (n==0) </P>
8 ~! p% o0 L( m9 `' i5 ^( b& M' Y<P>{ </P>
' w4 O: ~* M. I  b7 T2 j<P>for(i=0;i&lt; m-1;i++) </P>2 p1 E* F7 G) ^  H- G9 p
<P>for(j=i+1;j&lt; m;j++) </P>& S9 q- I$ b/ q
<P>if(od) </P>. F! E  P1 B5 Z- Q" v
<P>{ </P>
8 l, D! |1 A4 q% G  k0 T<P>if(ListView1- &gt;Items- &gt;Item- &gt;Caption &gt; </P>
$ ?* z5 Z$ }* t5 r. d1 @3 A7 P<P>ListView1- &gt;Items- &gt;Item[j]- &gt;Caption) </P>
% V) [6 t; g. L5 k<P>{ </P>* @% M! j; _; d1 H+ s8 D# H, Y5 X
<P>ListView1- &gt;Items- &gt;Item[m]= </P>
, |$ K- I. C& D! R* w' U<P>ListView1- &gt;Items- &gt;Item; </P>
- G# H0 d0 h8 D<P>ListView1- &gt;Items- &gt;Item= </P>
& I- a4 i/ x7 d% W) B) w0 ^<P>ListView1- &gt;Items- &gt;Item[j]; </P>  a+ I8 _  O; t/ ^1 K
<P>ListView1- &gt;Items- &gt;Item[j]= </P>. O2 a7 V" P" w) J  [+ F& O5 u
<P>ListView1- &gt;Items- &gt;Item[m]; </P>; e3 K! [; G  h  G4 e
<P>} </P>
5 E6 Z7 w7 B+ h0 g  @. y<P>} </P>* i5 ~6 x) E- ]' N0 g& d
<P>else </P>6 @/ ]1 G2 ^  Z8 Z
<P>{ </P>
" ~; n$ F6 f  Q9 ?7 e# w<P>if(ListView1- &gt;Items- &gt;Item- &gt;Caption&lt; </P>, D! H  G( n2 I
<P>ListView1- &gt;Items- &gt;Item[j]- &gt;Caption) </P>: I* F2 r) |% I; Q3 u, g
<P>{ </P>/ u0 r/ v3 ?* [
<P>ListView1- &gt;Items- &gt;Item[m]= </P>
) n5 q. P5 T+ ]: g' a% a3 t0 m2 J$ d<P>ListView1- &gt;Items- &gt;Item; </P>! D. s, ]2 \" x+ N  X7 |: N! |
<P>ListView1- &gt;Items- &gt;Item= </P>, f8 k7 h9 O( U" m( i4 L( S  L
<P>ListView1- &gt;Items- &gt;Item[j]; </P>. t( b: n8 k4 a# `
<P>ListView1- &gt;Items- &gt;Item[j]= </P>1 A! F# l0 u$ @9 E0 l$ _1 M
<P>ListView1- &gt;Items- &gt;Item[m]; </P>8 a$ V2 b# s2 p3 z( v- Z8 K, [
<P>} </P>
+ N; [7 l! T/ e. y  H" ^<P>} </P>
5 b! S  G) j% o8 G  y# t% e1 b% X, N2 F<P>ListView1- &gt;Items- &gt;Delete(m); </P>/ ?( J( f) f% J9 ~7 R
<P>return; </P>
9 _: R3 ]' v4 @! o" K<P>} </P>
6 d* S( r4 p7 o/ f4 j: h- o9 r<P>  </P>: z$ A% n7 O/ L% q5 a
<P>---- 点击其它列时,需要将所点击的列内容从ListView1- &gt;Items- </P>$ p6 J$ D( c( _& m% L! A- n  X9 v
<P>&gt;Item- &gt; SubItems- &gt;Text中抽出,并参照其进行排序。子项目在存储中,形 </P>( T6 {: ~. g3 t- o5 A( C. i
<P>式为_子项目1\r\n子项目2\r\n子项目3\r\n...子项目N\r\n_。为抽取其中某一 </P>
& T; g: K1 U: o- B+ S0 v<P>子项目,需编写如下函数,并将其放于void __fastcall TForm1:: </P>
( w8 X9 y9 Y* e* X<P>ListView1ColumnClick前面即可。 </P># S, N) k  e) j) h( V4 V; t
<P>#include &lt; vcl/dstring.h &gt; </P>0 |" i" q8 g. }
<P>AnsiString __stdcall sg(AnsiString str,int n) </P>
0 T6 y# V* K- `5 K; D<P>{ </P>
8 k. {6 P/ L* A6 u& X; l5 m<P>int l,i; </P>
5 |* n, Y- b5 K/ |<P>AnsiString qq(str); </P>1 H* D  d: ?' E# O- [% ^
<P>l=qq.Length(); </P>
4 y' }7 M# v5 R& K4 q( v9 o2 _  k<P>AnsiString p(str); </P>2 z' r8 W$ l( T( q* P
<P>char a[]="\r\n"; </P>2 f# b- ^8 f9 V' v
<P>int j=0,k=0; </P>& {$ y# C* B9 {0 V/ M
<P>for(j=1;j&lt; l;j++) </P>( E) i. s' C( p# O3 K7 Y- r
<P>{ </P>9 F0 I3 b! C6 |0 y
<P>i=1; </P>
) C1 S! L8 I' t7 e( |  v<P>while(qq[j]!=a[0] &amp;&amp; qq[j+1]!=a[1]) </P># _1 r: w6 b) Z2 d# q
<P>{ </P>
$ \3 X  A  j1 @% n3 I4 [<P>p[i++]=qq[j]; </P>7 h3 \/ @# L5 i! Q: p6 E
<P>j++; </P>! n. k5 ?4 ]3 e' o3 k; [& P# E
<P>} </P>1 ~/ M+ B! X8 ]6 G6 L
<P>k++; </P>" C! i; I  P6 N* Z
<P>if((k-1)==n) </P>
3 |1 w) V; g0 f9 t+ W/ ]<P>break; </P>
7 `  i, M, q1 J: o) B<P>} </P>
6 h, c. i7 E2 T% L<P>p=NULL; </P>
; k( r7 [) z, Y7 Q! Q  `; S<P>return (p); </P>' @: o4 f% o5 g, u4 O+ Y. Q
<P>} </P>6 G; d/ ?' l' N: a/ M8 a
<P>  </P>  n/ M# K% F7 k. T% D9 R
<P>---- 有了此函数以后,只需将上面的ListView1- &gt;Items- &gt;Item- </P>- S! u. C1 s) b, |
<P>&gt;Caption更换为sg(ListView1- &gt;Items- &gt;Item- &gt;SubItems- &gt;Text,n-1)即 </P>
7 G. O, a: {6 ?( o4 U* U<P>可完成对此项目的点击排序功能。 </P>
- e; ]+ `+ v0 ?<P>for(i=0;i&lt; m-1;i++) </P>
! l5 I- @) u2 P7 i4 m<P>for(j=i+1;j&lt; m;j++) </P>! [$ O2 F# P* C6 v* M( e& B
<P>if(od) </P>
" a) l. L3 p9 a" ^& C3 b, y<P>{ </P>
( g1 u* r6 T: R& A( v1 O. u<P>if(sg(ListView1- &gt;Items- &gt; </P>7 ]' G2 I. J# i; }9 S
<P>Item- &gt;SubItems- &gt;Text,n-1) &gt; </P>
% s7 H) I; F$ ]* h) _<P>sg(ListView1- &gt;Items- &gt; </P>
# n; ~2 j% J# d  }( L1 ~8 ?<P>Item[j]- &gt;SubItems- &gt;Text,n-1)) </P>
0 u; V  o! O6 p# s- H
5 Z; A, y: j, @! q$ E( D* `<P>// ...以下从略 </P>
3 k5 I& S9 @$ I4 U2 {1 L<P>  </P>' M  _2 S& F! A- a2 j
<P>最后,删除临时的交换项目。 </P>
3 B1 }9 Z3 q, g9 v/ ~<P>ListView1- &gt;Items- &gt;Delete(m); </P>
* ~' H6 k! V/ l7 g" B8 }; X+ ~8 U<P>  </P>* u6 A! P" D, m' G* A" C) R  `  I, ]2 v
<P>---- 编译运行程序后,即会看到我们预期的结果。另外,本程序是按照字符串方 </P>
2 G7 v! u6 c4 w/ Y7 i<P>式进行排序的,如果需要按照数字或其它方式排序,只需进行相应的类型转换即可 </P>
( O9 s% h/ {" I/ U! [; h! X<P>  </P>




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