打印

delphi 技巧合輯

delphi 技巧合輯

INI文件的操作要点4 J7 ]/ V" P) o3 b
(1)在interface关键字后的uses子句中加入9 a6 [- x2 J* h- u' t- s- }
uses …,inifiles;
) h/ _& ^! ]' v$ Q, F(2)设置变量:var inifile:=TIniFile;
4 p: B- F# N0 i" [" v. d/ K(3)使用前,一定要先做:
9 v$ X! Y" Z3 d. f  s( A& xinifile:=TIniFile.Create(inifilename);* u, ^/ J& o5 Z
我在这里绕了个弯子,写成
9 O/ }8 A! n4 I9 N, O) M+ ~4 j4 N4 rinifile.Create(inifilename);. c' d" T2 h* ]8 u2 X

! {5 z) a4 u; fTShiftState用来检测CTRL,ALT,Shift,以及鼠标按键的状态,
5 i2 C5 Q: ]7 @; q  q/ b常常用在键盘或鼠标的事件处理程序之中。
9 _* u% E9 K  v( m& T5 J4 v
- T; C3 m7 @8 QDCU文件(编译的库单元)的重用
  T6 w: }8 X, w) {( u1 t, y& O(1)在interface里的uses子句中引用。如Windows,Dialogs,. I' H9 B( @- e$ k# K$ ?" V; U
等等,要求被引用的DCU一定要放在Delphi 3\Lib子目录中。
7 `2 s: c& u. }! i, r0 e) h(2)在implementation里的uses子句中引用。如果是自行编写的, D  L. f! ?* {! Y2 r/ ~
DCU文件,应采用这一方式,并将被引用的DCU文件放入当前
' w' |5 y* j' ^4 Q" }# T工程所在的子目录中。
+ P' [' T; s6 c% U6 \executefile函数(在FmxUtils.DCU中定义)不能用在FormCreate/ w& T  |* k1 E/ l& @( T1 Y
事件中。真奇怪……
, W4 f9 ^) i6 g4 l9 Y# A4 R: h% D/ W
- U* n( a0 R- x% D% g内置的版本号控制功能
; d* y9 r- G) w, l( \; W# E在Project Options中的VersionInfo项里,有版本信息的定制,- e! N7 q0 U$ J$ {& j
包括一个有趣的版本号自动增加功能(Auto-increment build; z7 K) \( x' C/ o; ~
number),即每Build一次,版本号中的Build Number加1。选中0 ?( l1 r) R; K6 j
Include version information in project,编译,用资源管/ ?  d6 ~( X+ t8 @
理器里找到生成的.exe文件,点右键,查看“属性”一项,就
  L' N8 [; F( A. X+ j) [" }# X/ P1 U! z, Z会看到在属性中多了一页“版本”,里面就是你刚才输入的各$ x! x+ A6 O% t$ y# T
项内容。
. ^1 Q9 g6 ~, K5 |
: Y8 N  i* l' J& ]( j. `0 Z
. Y3 u$ J; @; I) F2 \7 A( W. Q9 H定制Speedbar
7 V$ Q2 T  F! a* f% [7 Y" b# G右键点击左上角的加速键条(speedbar),选中Properties,
# i, U3 `/ R+ F在列表框中找到你想要加入speedbar的命令按钮,将它拖到
1 c; X: {. b8 H& L" {! t% Xspeedbar上的合适位置即可。如果speedbar上没有多余的空间
. ?( E6 V: d; h' p# n/ d来容纳新的按钮,可把鼠标在speedbar右框处变为双向箭头的; n1 g! U, H- Q7 x1 T- v
形状,向右拖动一段距离,就可腾出空间。如想删除speedbar( R% b6 ^( d$ ~. A* |$ n6 Z
上的某个按钮,可简单地把它拖出speedbar的范围,就能删除。: {6 o2 T& `& ?
2 b6 j# U7 L- E3 Q1 u
0 I6 g7 u. o. W* ?- b
计算出的字段4 L- g: l/ ?7 P; ]4 \
在写一个程序时,我要在DBGrid中显示出一个memo的部分信息,当我把那个
% M3 _# j9 k+ e- c3 c7 ?memo字段放进去后,运行时只能显示出“(memo)”字样。从书上找到计算字
. b" k7 Y5 I6 m- v7 k$ K5 L段的用法后,我在TTable中增加一个计算字段MemoHeader,宽度为40,在此* i: i4 I+ k) U/ l& b
TTable的OnCalcFields事件中输入:
- T. n% e" [" C/ I3 |with MyTable do) N9 f4 y" X$ r" U
FieldByName(‘memoheader’).asstring:=FieldByName(‘memo’).asstring;
3 k  t1 \" H. \9 j在DBGrid中放入MemoHeader,运行,OK!
9 Q# {/ i9 M( \# ~% s# \, u2 i3 t) [# h  x

8 z  D0 b3 |% y; ]! I字段编辑器2 o& B3 m7 d8 D- ?
解决了上面的问题后,我继续学习字段编辑器的作用。原来,DELPHI通过字
* R9 H: H8 s$ r2 N  e段编辑器,近乎完美地实现了数据库的字段级的控制,这包括:2 J0 O! g8 C+ W- e
1)字段在DBGrid中标题、宽度、能否可见;  t+ l: D' e! _* f& P# |* S7 v
2)字段的显示格式和编辑时输入的过滤条件;( p6 v$ @! c; ^3 k
3)字段是否只读;
+ ]/ @4 @$ u( N' p+ h4)字段的类型:数据字段/计算字段/查询字段/内部计算字段;4 ~# l2 n& R8 @* h5 `
5)字段的显示/赋值/修改等事件的定制。) K1 e" G' q8 v+ Q
! R$ \6 o# Y$ M: ]  D. B
0 q3 ^0 d* Y( `: B! P
设计Form时的快捷键5 m4 J7 U  L; N' f. z7 L* z# @
Del 删除所选组件
8 j6 S4 E& M. _# \: X! [, p8 `Esc 选择当前组件的容器(通常是Panel,Group或Form)7 j: x; t( e! n% @
F11 在Form或Unit和对象检查器之间切换* O: M. I7 B& `& F" r, a
F12 在Form和代码编辑器间切换
5 L$ N8 _7 x5 `/ A. R% LCtrl-F12 显示“查看Unit”对话框$ l( }1 c4 C3 f& g5 J
Shift-F12 显示“查看Form”对话框
( G, i' i5 Z5 E& _6 o% MTAB 下一个组件
6 M; e: c: t, u- g+ ^0 NShift-TAB 上一个组件
/ B8 i* q9 q. l8 W% y方向键 选中此方向上最近的组件  I3 [9 z# H5 F( ]' w
Ctrl-方向键 将所选组件移动一个点9 B4 B4 w: A% U. P/ N! e( z
Shift-方向键 将所选组件改变一个点的大小# Y* x" j/ G3 o) _+ \6 O8 e* x
Ctrl-Shift-方向键 将所选组件移动一个格# @3 g, d/ ^- ^, K3 y% d
Shift-click 按住Shift键再用鼠标点击组件,可以选择多个组件。
2 ]. [3 t. a! c; i6 m/ @+ D–= 下面这条是我摸索出来的 =–8 H8 a/ z: K2 y* p/ Y) H' S, C9 ~
Ctrl-drag 按住Ctrl键在一个容器组件(如Panel,QReport,Groupbox等)
$ _! L8 \  j) E2 b4 Z3 V: R里拖动鼠标,可强制选择鼠标拖过的矩形框中的所有属于此容
: E* m7 T9 N' L4 Y! S' D- r器的可视组件但不包括该容器组件。
, ?& I" {: Y5 E/ d3 j8 V0 b
. s/ F( Y. u1 g" x( P$ M: x
5 k5 l: Y& p  d7 j6 Q8 w使用QReport的若干经验
4 C% A3 E0 J( I1)QuickRep1.DataSet:=query1
0 q, n( {+ F5 X; d不然无输出结果
1 ]) d4 Y- D7 n1 A  a2)从qrpt2man.doc中查知,格式化输出结果的方法是:
" Y( k" n* R7 b& F# ?! E& a在QRDBText.Mask中设为.00;0,将使输出带两位小数。
4 x% g0 s2 t5 |& w" H( r3)设置Group时,先加入一个QGroup,再加入一个QRBand,将QGroup的; ~$ e: O" R& J6 G, K
FooterBand设为刚才的QRBand,就可将其联系起来。
9 M- w, A) z- G" N3 Q4 f. S4)在Group中打印的合计数,其ResetAfterPrint设为True,可实现分组合% h5 B) V% `$ z

. v- ~1 t6 p+ b4 y* |. Y% Sformat(‘%*.*f’,[8,2,123.456]); //等价于format(‘%*8.2f’,[123.456])
5 K0 d# w. C$ ~& g9 ?format(‘%d %d %0:d %d’[10,20]);
- g" Z/ z1 y* Q* ]/ ^, V, S% e6 \
& I6 R5 i% t5 r' d4 P) q. _4 _( f% w3 F% Y* r8 |9 N) U
! z+ R& h$ e. X2 u1 p
播放一个wav文件: m2 v& A) r. N8 R# U
use mmsystem;
) {: t$ q( m  e& qSndPlaySound(‘hello.wav’,SND_FILENAME or SND_SYNC)
0 T" o. a2 Y% h+ f: h" ?, [5 U' y% O* z- B, T0 t
使你的form适应不同的显示分辨率
. b1 @( t9 ]; G( L假设你在800*600的分辨率下设计的form,第一步:
- k, M& h& X/ n8 W7 r% A- `: @2 U7 yinplementation
& @2 g) y/ m* D8 n$ t( Hconst! D! a3 v; l" S; l) u, o! y, [
ScreenWidth: LongInt = 800; {I designed my form in 800×600 mode.}
2 f5 x$ M* E1 Q* TScreenHeight: LongInt = 600;
; R7 |1 `5 ~. G. }' \& a. S: |0 A: z! l; }; t
{$R *.DFM}" X% u5 g. y! m- i5 j& a

1 ?; S5 f: N; I, qprocedure TForm1.FormCreate(Sender: TObject);: P& \; ~4 @6 S: @( t2 `# D
begin+ e$ m; R( u& d, Q8 W) ~3 a( I
scaled := true;
6 m5 {. Y( I" g0 u% p* oif (screen.width <> ScreenWidth) then
5 x- J% O' U8 V% n7 g  jbegin3 t; U5 l& N* |( r! U' n) F
height := longint(height) * longint(screen.height) div ScreenHeight;
6 k, f7 w* t5 J0 a& e+ ^9 v4 Vwidth := longint(width) * longint(screen.width) div ScreenWidth;
. j1 E% Z3 T$ O/ h$ G4 E/ f/ AscaleBy(screen.width, ScreenWidth);
3 }" Q3 K# W$ d$ Rend;3 |: m* K$ a' W1 i6 _( b4 }& K9 V
end;
8 K/ E' L# K+ c' x/ p
$ z" R: Y9 {- i; Z  s下一步,要让每个子控制的字体改变到合适的大小:
2 ]2 J, \5 C! w) M  e& ntype% r8 k3 d/ Z4 D( i2 h1 @" |
TFooClass = class(TControl); { needed to get at protected }: p- V6 v9 L" Z; o2 ?/ b( b
{ font property }* ^; }  I2 B6 y2 c" q6 o

# p6 g4 y1 R  y- [' q" ~/ Yvar
) }; \' \/ n7 _, Si: integer;# o: H4 M' C& R6 V; Y" b  M
begin
, G) k! F( s7 ^1 ]" Ofor i := ControlCount – 1 downto 0 do) B; r# c) h/ ?" e; k& n- m
TFooClass(Controls).Font.Size :=& p1 l% _" ~" L' ^! Q) e# k0 @1 q
(NewFormWidth div OldFormWidth) *, N: p) b5 x3 c- ]5 U5 m+ s
TFooClass(Controls).Font.Size;
/ ?& g1 h, q5 @3 a' w' U7 Wend;7 L) G% d, F" }2 @+ E) \

# p: U9 A" b3 `用raise引发一个错误处理例程
4 W8 W: E0 {2 X示例:先给出下面的定义) j& k+ z( u! d' m& N
type EPasswordInvalid=class(Exception);2 b1 ]! x1 [; E- |* m
这样你就可以随时引发一个”password invalid”的例外:+ l; i$ @( y$ u3 k) e
if Password<>CorrectPassword then. o1 O# V7 _& I6 _3 G: |
raise EPasswordInvalid.Create(‘Increect Password entered’);( A6 S. s& S8 c* s$ ~
运行后,出现信息框
: L0 W% l; E! N# G  c0 x- QProject Project1.exe raise exception class EPasswordInvalid
' u/ L& g6 V) d" q& f& l% n  Fwith message ‘Incorrect Password entered’. Process stopped.# K4 v9 M' {4 T( K8 i' q
Use step or run to continue.
+ a" n% J% A' o4 o% A1 y( V7 U$ d再按Run按钮,出现一个信息框:# J3 ?& N6 J3 C/ K# {
Incorrect Password entered.! J! {8 {$ A& F* G% }! O( F

- z8 l& R* x, `% J; ^3 i
$ _! _: f# ]2 _9 k1 w1 Y从DEMO例程中学到的若干小技巧+ _; S5 ?6 g. d. m( s# V; Y
在demo\internet\http\webbrows\main.pas中,
+ S/ k* A4 i3 }; S  ?1 Xprocedure TForm1.DocumentSourceClick(Sender:Tobject);
" Q1 t( \, h) g' H( ~begin
2 k) P/ S! r4 ^- H5 j- _* hwith DocSourceForm do& m3 q) B2 P- k" O
begin* ^0 K" R0 t' Q" Q+ I) a
show; // 显示HTML源码的FORM/ U2 c0 L' Q% h7 ^2 R
Memo1.lines.clear; // 清空memo1中内容
2 a2 `2 G, [' ]. Y  d( L7 rMemo1.lines.add(HTML1.SourceText); // 植入源码
% N8 |- I  T2 h5 ZMemo1.SelStart:=0 // ***
& n9 E/ H# X7 sSendMessage(Memo1.Handle, // Memo1的窗口句柄4 `, Y$ J9 S/ e, Z: r  B  V7 |/ M) b
EM_ScrollCaret //将Edit Control中的caret光标滚动到视野中
2 Q# Q6 I9 ^! j& U; ?% D2 U0,0 //这两个参数暂不使用
9 J0 x6 `; _/ F5 i( J; b# L5 Qend;8 ]& v  G* S2 ^3 k7 C8 P8 V# @
end;$ t6 z- M8 c1 f! P, H- X
(此SendMessage系一WinAPI调用,给一个或一组窗口发送消息,直到
7 N1 }1 U. s  ^相应窗口处理此消息后才有返回值。相似的另一函数为PostMessage,
5 Q& h& T( _4 J) }: }9 x它将消息放入消息队列中后立即返回。)& G) T" d& ]* g6 Y. p! o6 v
*** 清空当前选择并将光标移动到指定字符(0代表第一个字符)。如同时
6 w/ \, W; x- ^, \设memo1.sellength为一非0值,可选择一段文本。
5 j9 P4 V$ P" G9 ]% L& J! I: r9 O$ i# k+ w
; S) v% t5 z& R4 Z+ r
奇怪的I/O error — 我在开发过程中发现下面这两条语句
/ m! p; J5 t. f1 L$ ?9 xassignfile(fDesc,CDDatadir+describefile);4 U6 n2 E' {- O/ ]1 v
reset(fDesc);
; `4 |0 ^- B: }) y2 C0 t: ~每当我第一次运行到这里时,总会出现 I/O Error 183 的错误.
6 n" I( ?2 Z  g, u6 s% U* T  B最后我想这也有可能是没有清除 ioresult 的原因.在两句之间加入  z6 L9 m& L3 G! a4 y! ~
if ioresult<>0
$ J2 O0 N9 ^( Y* G" k& E* Cthen; : d- ?' N7 P6 w/ l! B8 r' w/ ~
oooook! 可以了.
4 Q' \- e% |+ {& p% o8 E2 {9 j, h9 D6 r( p$ k, m( N6 n

7 \  O8 z* f0 I值得注意的I/O error
1 v$ f3 N+ N" e% w6 SAssignFile(F, fname);3 W; e1 y3 D! O% }+ e
Rewrite(F);
. t* A% p( O& q  M4 q8 @当文件 F 经 Reset(F)打开的情况下, Rewrite(F)会引发一个异常: I/O error 323 M+ @3 M& i5 Z, z
反之,经 Rewrite(F)打开, Reset(F)也会引发同一个异常./ W' P5 `2 N8 p; j+ ], w
Reset(F)两次,closefile(F),再Rewrite(F),或反之,也会引发同样异常.
9 ~$ ]. v4 ~0 ]6 g: C* A. J) U9 v7 t

& d4 V0 q& p& A% O) ?6 r: l% Z0 q: F- [: V
string和pchar的相互转换:
  N' }$ k% E8 [9 ?4 istring –> pchar: pchar(s3 P  x; c# ]6 I: V: B
tr:string);2 I, \" N% ]* l" m! c2 M
pchar –> string: strpas(p:pchar);$ a! t, ?$ S1 V
" S' I1 ?0 d( ?+ I$ O
0 s# d( Q% W( |: ]% u

$ G+ U9 o# @; j  _在Delphi代码中定义数据库
9 b# Z4 q9 o% ?& G- i: O" p+ ~% fprocedure tform1.create_tbl;
! W- [* G( P1 V- cvar tbl:ttable;, h( B+ Q7 j8 q. Y3 C: r/ S1 K
begin
3 N7 e+ R' _! ktbl:=ttable.create(self); // 如没有声明中的”tform1.”,Delphi不认这个self& ]" R' f* f' J( m0 `- ~( ]
with tbl do% E" I! K" K# f2 u2 c/ x
begin+ g9 @' }2 O' m; D
datebasename:=;dbdemos’;
; W6 Y" N! I% Otablename:=’my_tbl’;
1 R& _/ I5 x& }with fielddefs do* i1 j+ s/ W; ^2 \5 k
begin' g0 v+ z+ i3 T. \
clear;& h; b8 n+ C! w7 ~4 s
add(‘No’,ftInteger,0,false);
+ J% U9 {* r/ \0 gadd(‘Name’,ftString,0,false);
$ k: A& ^3 y% \9 p' R) z# ]) B- [. R1 v2 |( }/ A* I! M( |
end;
$ |1 p9 g3 e5 k2 _1 Twith indexdefs do
" L# R! a7 k' R- h' r' zbegin
: _2 W, M. n- q. `% |; P7 rclear;
' ?# j9 r6 m& p' g( a2 Dadd(‘primary’,'no’,[ixPrimary,ixUnique]);
# g4 V+ i' t0 R+ E- @8 l
  q( a& L+ a6 ^3 Eend;
+ C+ ?' |' J6 i. B* h8 j# oCreateTable;
" b8 z) Z. X4 n2 Aend;( F' ^5 R  ^" w: M
end;, @6 J: X* k3 T. d  o9 G- ~5 r, z
  U8 T  n  s! y- N8 N& B- s1 k

: ~+ C1 Z5 M- J7 k; ]' B' Kstring、TStrings、pchar的相互转换(这里是我的个人经验)
: ?/ p6 H5 z" R4 d  W7 v/ `* a假设有如下定义:
7 a+ [8 X) `( c4 K* gvar: O- G( S" W3 e
p:pchar;
0 n! b4 m3 l( X; ms:string;
/ I3 e* _: @) H% B) k0 ess:tstrings;( g2 Z5 ^' p" O$ g
begin
0 l) u' e7 s- L" Iss:=tstringlist.create; // 开始时一定不要忘记创建ss
( T- [4 X& i$ f. ~# bss.text:=s; // string –> tstrings
4 C1 g0 ]; k/ x( z6 @" Q" Z0 @s:=ss.text; // tstrings –> string
' {! R. T" o- xp:=pchar(s); // string –> pchar8 {- V/ G8 J# J. C
s:=p; // pchar –> string2 ]9 l6 H; P3 b6 |4 G) Q
showmessage(s); // 合法语句2 B3 \$ [9 l& e3 O
showmessage(p); // 合法语句' e$ P" Z8 [# _8 q+ ]3 \
… …' [6 m" K/ A+ l* C7 d6 o+ y
ss.free; // 最后还要记着释放ss占用的资源
3 v# \( \, h% O% z, Hend;* h9 T/ H" B  |5 L4 J

8 Z) v$ K/ v+ D: ]" m9 V) n
: x: ?& T' S+ y2 O6 l. K0 H: P1 N& ~% t, l7 J  P( y5 P6 D
在设计Menu时,常用的ShortCut可从下拉菜单中选取。但我发现可选的ShortCut有些不在列表中,如ESC,Ctrl-Shift-A等。我试着在ShortCut项的右边输入:ESC,竟然成功了。再试Ctrl-Shift-A,这回Delphi自动把它变为Shift-Ctrl-A

TOP

發新話題