数学建模社区-数学中国
标题:
在C++Builder中实现ListView的列标头点击排序功能
[打印本页]
作者:
韩冰
时间:
2005-1-26 12:28
标题:
在C++Builder中实现ListView的列标头点击排序功能
<
> </P>
) m) R- ?2 d R" X7 [! R o1 \
<
> </P>
) z2 F1 T; o$ V2 {$ y
<
>天津大学电子与信息工程学院 </P>
: H+ D! J, H! p- ~0 Z" O
<
>宋天宁 </P>
, c! B/ S6 u7 V6 O4 v5 {! `
<
>---- 列表框控件在应用程序中的使用率很高,在Windows中经常见到, </P>
) o( z5 @$ D% t. {- G
<
>它有四种常见的式样,分别具有显示大图标,小目标,含有图标的多列列表,含 </P>
+ M# F9 Q9 f) k R- x
<
>有列标头的列表。我们也经常见到一些扩展功能,例如我们在资源管理器中的文 </P>
) h) X- z+ i$ ]# ^ A; A0 R, d3 M
<
>件列表框中,在选用详细资料察看时,用鼠标单击列标头,如大小,则所列文件 </P>
k0 k6 |2 M9 |2 L" Y* e* ^1 [3 X; t
<
>按大小排序;单机日期,则按文件日期进行排序.这一功能增强了应用程序的可用 </P>
- ~1 Q8 K6 ?" R! w& i
<
>性,使操作更直观、方便。笔者在以Borland C++Builder 3.0(以下简称BCB)作 </P>
1 p$ S" L3 z" L8 g. j5 Y
<
>为开发平台实现这一功能时发现,仅通过设定列表框控件的属性值的方法,只能 </P>
7 B2 c; }0 c( W: e5 @- F: |8 N
<
>根据项目的首列加以排序,不能根据子项目(SubItems)排序。因此,我们需要编 </P>
5 {2 O$ {. D8 \/ W6 y# G9 E
<
>写自己的代码以完成这一功能。 </P>
' O0 L! w. O( W3 `% L" [. U
<
> </P>
! ^ a$ K4 L7 ?, P( t1 Q+ H+ m
<
>---- 以下描述如何在BCB开发平台上为列表框添加列标头点击排序功能,当我们 </P>
5 l8 n! h" p9 I, Y
<
>点击的次数为奇数时,所列内容以降序排列;当我们点击的次数为偶数时,所列 </P>
' H1 F& a) n! k
<
>内容以升序排列。 </P>
+ b0 X" ?* |# m$ ^3 t; G3 ~8 ~
<
> </P>
4 g% N% k2 h: Y* g2 r' M% ^
<
>---- 首先将一个列表框控件安放在Form上,并将其名称设为ListView1。然后在 </P>
1 @- j* `+ }2 M
<
>其中添加若干项目作为试验对象。方法为:用鼠标右键单击控件,在弹出的对话 </P>
( b: w8 g$ j$ x
<
>框中选择Columns Editor用来添加列和子列;再选Items Editor用来添加项目( </P>
9 g8 M9 j% b; x2 p' }6 v8 O5 n$ k
<
>包含子列和主列上的内容)。 </P>
8 X+ {$ u/ }& ]3 X
<
> </P>
`9 \8 V& p7 }$ f) i
<
>---- 为了显示出子项目内容,需要在Object Inspector中修改ListView属性值 </P>
3 D% _! L7 m) I9 m' }
<
>,将ViewStyle设置为vsReport。另外,还必须将SortType设置为None,以使我 </P>
6 |1 I8 J- C+ j1 g" `
<
>们的排序程序起作用。这样,程序的外观已经符合需要,下面应该增加排序功能 </P>
3 M" @ ^3 S2 W6 f9 W& M
<
>的代码了。为此需要添加类的方法到源代码中。添加位置为: </P>
! l2 b( D$ U1 a: C% G2 A
<
> </P>
6 o. E6 `6 C' V+ V9 W/ q
<
> </P>
% P& O+ P" Z9 [& t, L' i
<
>void __fastcall TForm1:
istView1ColumnClick </P>
6 B- k; ?* T) [, C* @
<P>(TObject *Sender, </P>
1 K9 x4 `8 u$ d1 u% `3 C
<P>TListColumn *Column) </P>
. m, n7 ^5 H1 M
<P> </P>
6 u- f4 _# L2 ]$ G$ y% p$ Y- |
<P>---- 在该方法的传递参数中,指向TListColumn类型的指针Column中含有用户所 </P>
5 @: m0 v# C; ?8 e* r" _' I
<P>点击的列的信息。 </P>
0 }' y8 x9 P+ ^4 n: h
<P>---- 下面先定义变量: </P>
6 A, m$ r, V( r7 `
<P> </P>
% c( }# ?! ^: H* r; }
<P>int i,m,n,j; </P>
/ A8 d1 Q$ V) c: y5 H! w
<P>static bool od=true; </P>
, R8 ^& c) l1 J% C0 S
<P>od=!od; </P>
9 U# T# w/ X$ }3 j
<P> </P>
, ~+ t* o. I3 r$ ~+ i1 T
<P>---- od代表用户点击的次数,奇数时为true,偶数时为false。注意此处od的存 </P>
" z! D4 i! f+ a1 _6 C9 S9 f
<P>储类型设定为static,可以保证其数值的连续性。用n记录用户点击的列号,m记录 </P>
0 w, R5 f5 c$ p9 _* H/ L5 q
<P>列表框中的总项目数。 </P>
% ]4 d+ ]+ G6 [4 l& P
<P>n=Column- >Index; </P>
( s( |9 Y$ U! s
<P>m=ListView1- >Items- >Count; </P>
! B5 k( ^7 ^' N+ i
<P> </P>
) G/ ^; I7 D! L0 X! z
<P>---- 在列表框中临时添加一个项目作为排序中交换用的临时空间。 </P>
. |* h5 z! s; E+ _5 Q. N
<P>ListView1- >Items- >Add(); </P>
0 Y0 L& _, N% b5 w1 K8 b4 W
<P> </P>
6 r+ {% V; r1 s3 E: S7 c6 G
<P>---- 当用户点击第一列列标头时,排序按ListView1- >Items- >Item
- </P>
% J( @/ h% w) c6 s. R/ h
<P>>Caption进行,与其它列不同,所以要单独进行排序。 </P>
+ s( H$ ^& k4 B6 n# ?
<P>if (n==0) </P>
% c: F5 A$ ~+ j) q* ?
<P>{ </P>
; y2 N. `; V/ P& Q
<P>for(i=0;i< m-1;i++) </P>
/ \7 Y# o4 ~/ }
<P>for(j=i+1;j< m;j++) </P>
3 N' Y1 ~/ J: v/ P6 T9 l
<P>if(od) </P>
+ s4 i0 N1 M/ N5 K. G* [( E( | d& q2 ]
<P>{ </P>
( I+ P! D( H( y3 U6 m
<P>if(ListView1- >Items- >Item
- >Caption > </P>
/ D& D+ Y# V6 Z; e
<P>ListView1- >Items- >Item[j]- >Caption) </P>
W7 T; M; t' X& m0 d& C0 d8 k$ o
<P>{ </P>
3 a1 c6 |; y* ^ i9 x$ a5 m
<P>ListView1- >Items- >Item[m]= </P>
& [1 ?* E1 |9 o- ]5 J: z
<P>ListView1- >Items- >Item
; </P>
; i4 H4 D T T+ v7 s
<P>ListView1- >Items- >Item
= </P>
$ d n( Q# C( ~; Z5 g% J
<P>ListView1- >Items- >Item[j]; </P>
2 o' Z0 o6 [. e$ Z7 u0 N
<P>ListView1- >Items- >Item[j]= </P>
- X8 J0 V" ?3 p/ ?' S
<P>ListView1- >Items- >Item[m]; </P>
$ [( a: g- q- `
<P>} </P>
3 Y5 U" h6 H* Q3 I8 G/ R
<P>} </P>
) Z; r: t" Q7 F( M' k# p& l
<P>else </P>
( m! N3 M6 z j. F% w! H5 x
<P>{ </P>
0 m1 f- S' `! z; p6 b" ^; X+ B6 r
<P>if(ListView1- >Items- >Item
- >Caption< </P>
8 |+ V3 H' b: Z; u+ ?
<P>ListView1- >Items- >Item[j]- >Caption) </P>
/ |/ B) \1 r( ~- M; D( f/ v
<P>{ </P>
: F+ t/ {; v; h" f/ Q; A
<P>ListView1- >Items- >Item[m]= </P>
/ e; ~$ |4 P' Z. i# p
<P>ListView1- >Items- >Item
; </P>
4 }5 ^( k3 x8 l+ \9 D' U
<P>ListView1- >Items- >Item
= </P>
" [5 Q( _% g- o( c; `/ n7 ?
<P>ListView1- >Items- >Item[j]; </P>
" F2 _7 p/ u$ i" S, B; m. G1 f' ^* a
<P>ListView1- >Items- >Item[j]= </P>
6 c! b; S% x5 o: _. j
<P>ListView1- >Items- >Item[m]; </P>
& t" F" o9 z7 E
<P>} </P>
3 l$ ?- f% U- j# S
<P>} </P>
- G7 q7 @& I* J. D+ ^
<P>ListView1- >Items- >Delete(m); </P>
V0 L& A: \) j( }9 \
<P>return; </P>
' l& o, s) O. V4 o
<P>} </P>
2 w/ L, P) }# y! O3 i; u
<P> </P>
: v7 W: X5 _% T* N8 T& r( z, P1 c M9 P
<P>---- 点击其它列时,需要将所点击的列内容从ListView1- >Items- </P>
/ t% }5 d3 |( o% z' ^( b
<P>>Item
- > SubItems- >Text中抽出,并参照其进行排序。子项目在存储中,形 </P>
( u9 y- h( |9 ~% B8 Z! x" k
<P>式为_子项目1\r\n子项目2\r\n子项目3\r\n...子项目N\r\n_。为抽取其中某一 </P>
- \5 G) ?6 u% i! B( T" R$ Y
<P>子项目,需编写如下函数,并将其放于void __fastcall TForm1:: </P>
. B6 n) \7 a8 f, s, V( \. S
<P>ListView1ColumnClick前面即可。 </P>
- F# C5 Z8 A0 o$ K! `
<P>#include < vcl/dstring.h > </P>
% `8 Q- r& y4 \, n g( q% w
<P>AnsiString __stdcall sg(AnsiString str,int n) </P>
1 B. F r3 I6 D1 f6 u
<P>{ </P>
% X4 P% q' j- |5 ~" g+ ^2 k, g9 A
<P>int l,i; </P>
& ~2 x5 V9 R C. l- a
<P>AnsiString qq(str); </P>
* |- b- q$ a6 F. p, h2 L9 L1 A# e
<P>l=qq.Length(); </P>
0 r0 A8 K% L! V0 b- w, }" I
<P>AnsiString p(str); </P>
7 W% x" {) q( r) B# G8 P& K; X
<P>char a[]="\r\n"; </P>
9 ~* M0 @& g) ]$ m; w! L ^
<P>int j=0,k=0; </P>
+ x" e4 L$ j1 y7 x
<P>for(j=1;j< l;j++) </P>
, g1 x) W, s( V2 s/ O( u, `4 }9 _
<P>{ </P>
9 _4 Y& c) N3 E$ [, w' p
<P>i=1; </P>
9 e0 [! R) Y" f9 ]5 l( X7 l
<P>while(qq[j]!=a[0] && qq[j+1]!=a[1]) </P>
. a5 s1 F' j2 G- v
<P>{ </P>
! p8 [* O s" U7 i
<P>p[i++]=qq[j]; </P>
2 g' h' u/ ?2 f# D, S9 O0 o
<P>j++; </P>
! m+ Q4 k3 ^& B* t* k+ g
<P>} </P>
0 C* a7 k* K2 e& a* z" Y+ {. I
<P>k++; </P>
& G# N4 X! n! k. B/ ` |0 B
<P>if((k-1)==n) </P>
2 o) F2 ^& X" \. L6 U$ X9 k& c
<P>break; </P>
3 j4 j4 s3 T) ^
<P>} </P>
+ G9 ]& @$ n1 N5 a) H
<P>p
=NULL; </P>
' K J0 T6 J# w
<P>return (p); </P>
' Q5 E, U8 V5 B6 ~7 m3 V
<P>} </P>
4 T9 O6 d4 }4 t" w0 t- l
<P> </P>
1 v+ W% p3 |. B# M, ?3 P' \; u
<P>---- 有了此函数以后,只需将上面的ListView1- >Items- >Item
- </P>
& A& J9 r2 {* D( ]" G
<P>>Caption更换为sg(ListView1- >Items- >Item
- >SubItems- >Text,n-1)即 </P>
- k/ ~/ B% ?$ }
<P>可完成对此项目的点击排序功能。 </P>
/ ]% J7 l, ?, u4 I* Z. i& ]
<P>for(i=0;i< m-1;i++) </P>
- R0 G1 o$ [* g
<P>for(j=i+1;j< m;j++) </P>
% v7 O4 b9 x! g) K1 j
<P>if(od) </P>
" ~; O" g$ q4 s1 p# r: K
<P>{ </P>
& a: O, R6 c2 S
<P>if(sg(ListView1- >Items- > </P>
4 Z3 h- n* y1 |) l5 c- j$ A5 e
<P>Item
- >SubItems- >Text,n-1) > </P>
" `1 @, Q% D9 ]; t
<P>sg(ListView1- >Items- > </P>
6 J M! P* g# ^% H S) {: T
<P>Item[j]- >SubItems- >Text,n-1)) </P>
3 T1 Q1 T% o6 ]! k
3 y5 }$ ?& T( T$ i
<P>// ...以下从略 </P>
, r4 _8 E. `: i& m1 w# Q: U
<P> </P>
) n4 f4 |: j5 X2 M6 H% L# R
<P>最后,删除临时的交换项目。 </P>
X' B* P& M0 V8 F$ }8 N" H3 N1 i
<P>ListView1- >Items- >Delete(m); </P>
4 W/ t3 O- U' e4 X7 ?
<P> </P>
0 n) t' s& D! O5 v- w
<P>---- 编译运行程序后,即会看到我们预期的结果。另外,本程序是按照字符串方 </P>
# X; D$ ?" b1 k. E# r0 Y1 d/ t
<P>式进行排序的,如果需要按照数字或其它方式排序,只需进行相应的类型转换即可 </P>
7 ?" X0 V2 s: S+ O3 S( U6 X$ d
<P> </P>
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5