打印

delphi 技巧合輯

delphi 技巧合輯

INI文件的操作要点
: Z: c* z4 Q8 }, g# m$ Y(1)在interface关键字后的uses子句中加入
$ T/ z) [% s" R' _4 Z" Cuses …,inifiles;
5 `- |) S0 @: ?+ {(2)设置变量:var inifile:=TIniFile;
! x& G; _. Z0 Y6 k(3)使用前,一定要先做:( n! M" R9 ^! a/ r3 h4 i% ]' O. n
inifile:=TIniFile.Create(inifilename);
; L0 X; O8 y9 O我在这里绕了个弯子,写成
+ v, p+ g# F# Q" Y5 X+ `+ Finifile.Create(inifilename);5 z  ]9 h  m8 \, S
! N, h0 ?. F7 r5 M) O- S
TShiftState用来检测CTRL,ALT,Shift,以及鼠标按键的状态,' M3 W! J9 L% p$ P& ~. \+ j8 [$ w
常常用在键盘或鼠标的事件处理程序之中。# w3 L( p; h+ d  D  l6 R( {9 l
8 d+ `/ W6 A7 \5 ^
DCU文件(编译的库单元)的重用/ b7 t3 v; c: Z  c' g9 W+ M
(1)在interface里的uses子句中引用。如Windows,Dialogs,
3 Y- I! G( I8 W  k8 q等等,要求被引用的DCU一定要放在Delphi 3\Lib子目录中。& v7 c) o0 a9 Z( u* |1 ]" F; Z
(2)在implementation里的uses子句中引用。如果是自行编写的; i2 M* w6 _1 X8 ^- u
DCU文件,应采用这一方式,并将被引用的DCU文件放入当前9 [  r' ]6 i# T% q( w
工程所在的子目录中。+ c8 V8 G2 H5 P! Z7 p. Q1 J
executefile函数(在FmxUtils.DCU中定义)不能用在FormCreate' }5 Z' r4 `/ ]+ ~0 i* T4 W
事件中。真奇怪……
# y7 n+ m- Y' B6 n8 E. V! }! S* b- F0 p6 ]; ]$ @$ B8 M
内置的版本号控制功能0 D7 a1 L- T- N; u, S# R
在Project Options中的VersionInfo项里,有版本信息的定制,
3 P  X6 \  S* a4 p3 ?: `) x" x包括一个有趣的版本号自动增加功能(Auto-increment build+ \! f7 u: E- g" q& X. I* a7 I
number),即每Build一次,版本号中的Build Number加1。选中
3 F# F( B. O3 J8 D/ gInclude version information in project,编译,用资源管
% m% u3 g1 j: ^1 k理器里找到生成的.exe文件,点右键,查看“属性”一项,就
2 p9 L  i" \9 d7 A; @4 V/ q7 D会看到在属性中多了一页“版本”,里面就是你刚才输入的各
" J6 E8 C( `( \" P% W$ @2 S) C+ D项内容。
' I5 `7 m" r  N) C' N( {' d" [8 _' ?! Q1 l! j/ B

, B$ o2 {: ?! \$ v- C& G" `6 @' D定制Speedbar
1 U8 t9 `" r3 f# i右键点击左上角的加速键条(speedbar),选中Properties,
  j- c- n; L& R2 L! g* r在列表框中找到你想要加入speedbar的命令按钮,将它拖到/ \/ Y4 w7 {9 q1 \
speedbar上的合适位置即可。如果speedbar上没有多余的空间
$ p/ m" C4 b/ o6 b+ ]9 n) E来容纳新的按钮,可把鼠标在speedbar右框处变为双向箭头的
" Z* D. A3 i8 h: D形状,向右拖动一段距离,就可腾出空间。如想删除speedbar* h3 G3 @( ?: e5 @- J+ X
上的某个按钮,可简单地把它拖出speedbar的范围,就能删除。3 f( `6 [. o. E: x" t

) F) T" h( c2 v6 u. M
4 f. g8 u$ m+ A4 p8 a7 u计算出的字段0 F" \4 B' e6 X& p4 h; ^  e1 P6 e
在写一个程序时,我要在DBGrid中显示出一个memo的部分信息,当我把那个
' ~/ _- ?3 x5 d: G0 T; ?6 Nmemo字段放进去后,运行时只能显示出“(memo)”字样。从书上找到计算字
: ^7 M. h4 w* ]段的用法后,我在TTable中增加一个计算字段MemoHeader,宽度为40,在此
: \8 S) J! `) ~$ f  a) bTTable的OnCalcFields事件中输入:& Z7 T+ Z- S$ s$ F  _* z! t! K& a
with MyTable do3 T. K, J7 s) V1 |2 O7 R
FieldByName(‘memoheader’).asstring:=FieldByName(‘memo’).asstring;
. \1 C% ?; [7 y9 X. G, z: m在DBGrid中放入MemoHeader,运行,OK!  t5 s+ s- z2 W/ y+ `

0 c4 p  P/ ?0 u9 y# s5 L0 K! G
4 v* l1 ~( r% A# U& N5 g字段编辑器! w4 D4 p* |' k. s
解决了上面的问题后,我继续学习字段编辑器的作用。原来,DELPHI通过字% X6 f4 B3 _+ i! F6 C" b( P
段编辑器,近乎完美地实现了数据库的字段级的控制,这包括:
1 i5 @; [. }4 G+ {) F, M' a1)字段在DBGrid中标题、宽度、能否可见;1 z+ M1 N0 Y2 B; `2 [
2)字段的显示格式和编辑时输入的过滤条件;
7 |; B7 m( V+ G' M+ W9 I3)字段是否只读;
3 \! s9 K% K" M2 C0 \: m* g4)字段的类型:数据字段/计算字段/查询字段/内部计算字段;6 S5 `' Y+ Y+ b. v6 S
5)字段的显示/赋值/修改等事件的定制。; N) Q- I- u5 w% A8 {. I
  C2 X  j0 K5 t$ \

5 Z+ ~6 s' M7 Z( t$ i) t6 B/ A设计Form时的快捷键: l  o7 V2 x, \2 Q* p: o
Del 删除所选组件
$ \1 \) L2 i4 W! F) U9 U7 e; QEsc 选择当前组件的容器(通常是Panel,Group或Form)
6 F9 Y' i- g% S5 ^1 ~) z1 ~; T  c8 QF11 在Form或Unit和对象检查器之间切换
! Y0 f, ?6 J5 w7 ~+ A" cF12 在Form和代码编辑器间切换: h& ]% d& L6 j7 d( `
Ctrl-F12 显示“查看Unit”对话框# p0 c# u2 k5 N) }$ N
Shift-F12 显示“查看Form”对话框9 }3 G% l: |" q( O0 A" O
TAB 下一个组件. |( v7 s( M% n, p6 _1 F" D
Shift-TAB 上一个组件+ C- U5 H5 p# Z$ V3 k
方向键 选中此方向上最近的组件1 Z& X2 P: d# K) d1 z5 t1 N1 a
Ctrl-方向键 将所选组件移动一个点
& f) g) G' ?# }' F- {" KShift-方向键 将所选组件改变一个点的大小/ }0 f2 t- g% `$ N( o9 h
Ctrl-Shift-方向键 将所选组件移动一个格
3 j3 X) o6 q: M: nShift-click 按住Shift键再用鼠标点击组件,可以选择多个组件。
: l* b# m* H% h# X/ k% Z–= 下面这条是我摸索出来的 =–" \5 @( z3 v0 U
Ctrl-drag 按住Ctrl键在一个容器组件(如Panel,QReport,Groupbox等)
6 Z9 C) O% p  p3 w里拖动鼠标,可强制选择鼠标拖过的矩形框中的所有属于此容
! g3 G6 X" L4 N9 d  {器的可视组件但不包括该容器组件。: q0 T( B  H7 _1 o- ?/ |1 h  G

% L3 D. ^6 u9 M7 |' ~" A
6 x( U% N( c4 ~# w/ q+ h' I5 b6 ?. R使用QReport的若干经验
8 q. f# _# X2 P8 N& S! t: u1)QuickRep1.DataSet:=query1
- C! U. ?2 A4 C+ W1 d不然无输出结果  v( ]7 e, C% M
2)从qrpt2man.doc中查知,格式化输出结果的方法是:0 t6 ~2 C6 F$ w5 {9 i- L( i0 y
在QRDBText.Mask中设为.00;0,将使输出带两位小数。
% u) A& s  |# x$ `/ ~3)设置Group时,先加入一个QGroup,再加入一个QRBand,将QGroup的$ c) f5 m6 |& e
FooterBand设为刚才的QRBand,就可将其联系起来。
4 J  N' h: Z& }* B4)在Group中打印的合计数,其ResetAfterPrint设为True,可实现分组合
% j8 O! a$ v: S, L9 S% }& @. {* l% d4 h# ^3 V) q4 `
format(‘%*.*f’,[8,2,123.456]); //等价于format(‘%*8.2f’,[123.456])
, \: v2 y5 H! P+ X, a* ^format(‘%d %d %0:d %d’[10,20]);7 J9 S% P4 F% U* O+ z* p' u
8 o% p; {4 u( r+ {- Z

! {2 z/ L7 O0 ~; u- `. m+ S% E& K- q4 b$ ~
播放一个wav文件. i8 D% Z! }+ i. Q# n, N: z
use mmsystem;
1 B+ h: B. ~5 o' [' S- ?2 tSndPlaySound(‘hello.wav’,SND_FILENAME or SND_SYNC)) n4 ^3 P7 K( y) t$ X( q- m
+ L9 b9 o5 o  v, k$ V
使你的form适应不同的显示分辨率
$ o6 g3 v! [! r! A" ^/ @9 S- c假设你在800*600的分辨率下设计的form,第一步:) k- p0 A$ L" n6 l; Q( c
inplementation
7 S4 }# T: F: n. ?. f* lconst
8 q  V; M7 ?4 {ScreenWidth: LongInt = 800; {I designed my form in 800×600 mode.}' `- G' Y$ ^$ w  T! n: C% ^& v
ScreenHeight: LongInt = 600;+ R- q5 C  K4 l7 u* m' p1 R8 O! Q

# z4 D' M7 H3 a+ G6 E- \% r{$R *.DFM}7 S3 S+ a8 Y/ ~5 v) g

5 E: t4 ^* n" B0 f" d% r; r. Zprocedure TForm1.FormCreate(Sender: TObject);
! e& b& @# p3 E3 vbegin
1 g$ W: i3 ]3 `scaled := true;
5 y% ^3 m: m; m. u- `7 Wif (screen.width <> ScreenWidth) then7 k8 i$ Z0 B( ?) c* A
begin
, ?  J3 Z1 g1 B5 l( o# {height := longint(height) * longint(screen.height) div ScreenHeight;
- {* j8 n8 C- S& J8 D" j9 U/ fwidth := longint(width) * longint(screen.width) div ScreenWidth;# z3 ]- Z/ h0 R4 s& w3 U" r
scaleBy(screen.width, ScreenWidth);8 c7 D8 C- ?# }7 t. @9 ]6 K
end;
' Y# F! i, E( F3 bend;. s. w, c% m9 m7 M1 B8 i
( I8 z5 I; e- v7 u8 F+ n
下一步,要让每个子控制的字体改变到合适的大小:! E5 P; S0 J0 v& ~( M6 Y, h# B; j
type* D) w9 Y+ [5 N0 M' C8 \& _
TFooClass = class(TControl); { needed to get at protected }; I' w8 M0 C" g' ]+ _/ \& ~
{ font property }
; L' ~5 }7 J0 t
* c! h# n& f8 ]$ O3 ~var
% V# O7 o% {( m) `; `5 [i: integer;9 O# r# I, q& u  R5 r( N' l
begin
; S+ B/ a1 _3 vfor i := ControlCount – 1 downto 0 do
, G, t2 G& A7 [" b, ^/ o- j# PTFooClass(Controls).Font.Size :=; r( f7 m" ^7 q5 J2 Y6 e5 W
(NewFormWidth div OldFormWidth) *
" N" [3 i7 A3 T: \0 oTFooClass(Controls).Font.Size;( k' h# y2 s5 f* q
end;9 a/ T/ ~' l7 x& k3 ?- N9 u

  ?" W7 C; P! M% x, b/ L4 q$ P5 k用raise引发一个错误处理例程5 g' F/ e. T" i9 e' C4 L$ ?
示例:先给出下面的定义
/ R7 }( T! q" e# l: z# A" R" k& Ptype EPasswordInvalid=class(Exception);
& W5 R- [4 `6 B( p8 J1 v6 ~这样你就可以随时引发一个”password invalid”的例外:
# o! H& d% H: m3 i+ Z6 b- D7 Y% [if Password<>CorrectPassword then
( |! g9 @; f* G) g9 d% }" ^& _raise EPasswordInvalid.Create(‘Increect Password entered’);; @: [! d4 T- V
运行后,出现信息框
' l5 U, r7 E3 r$ M6 TProject Project1.exe raise exception class EPasswordInvalid& _4 n, J% Z, T' D) W- y) K) g
with message ‘Incorrect Password entered’. Process stopped.
# _% o" W" m( P5 pUse step or run to continue.+ Y4 C1 E; I- z8 v5 p. }
再按Run按钮,出现一个信息框:3 R3 ^% f, a' [
Incorrect Password entered.- E: p- O) L. ^  r% ]
7 C+ y! i* i  g  i8 X
5 I. X6 X9 J6 s3 \0 X9 I6 I
从DEMO例程中学到的若干小技巧
) O5 J4 \: a/ ?# ~; ^在demo\internet\http\webbrows\main.pas中,
6 [- U" R7 B7 G* j" N: D' ]; gprocedure TForm1.DocumentSourceClick(Sender:Tobject);
7 \2 q; `0 H! c5 F4 Bbegin8 \  [, O! b. J! _3 o
with DocSourceForm do
0 {6 g5 r; M4 q3 D" vbegin
+ z- V' s. y5 E: g3 Q  kshow; // 显示HTML源码的FORM
- t/ T1 t, p, W, f( D3 kMemo1.lines.clear; // 清空memo1中内容
4 W! U6 T2 e* d9 x; k) o" lMemo1.lines.add(HTML1.SourceText); // 植入源码% e: F$ l- h0 E
Memo1.SelStart:=0 // ***
8 I, z& M9 x( wSendMessage(Memo1.Handle, // Memo1的窗口句柄
4 J, S$ \; \/ `3 Q5 Y$ P& h' yEM_ScrollCaret //将Edit Control中的caret光标滚动到视野中, g: k$ m# H6 u$ ^  A
0,0 //这两个参数暂不使用/ X6 U1 X  c  v$ }+ W: m
end;
) ?5 G3 _/ S0 l$ Mend;
( [$ W) S& J2 ^(此SendMessage系一WinAPI调用,给一个或一组窗口发送消息,直到* T+ W; O/ g! s, F! {  W9 O
相应窗口处理此消息后才有返回值。相似的另一函数为PostMessage,
3 O0 M$ g1 D# H4 p+ }它将消息放入消息队列中后立即返回。)
9 ]( D0 K% `+ x- F+ ?. O*** 清空当前选择并将光标移动到指定字符(0代表第一个字符)。如同时& Q3 N2 z: G6 x0 [( C) C9 j* f  X
设memo1.sellength为一非0值,可选择一段文本。- `, P3 M$ E# M" K) k* c. A! ~
. \# n+ R% F6 ]5 C
* P. S) ]* Z: i4 R: w5 W( U, }3 x" r
奇怪的I/O error — 我在开发过程中发现下面这两条语句/ P* N! V/ K$ }0 q" b$ b% J" W* k
assignfile(fDesc,CDDatadir+describefile);
) {% `3 g: e2 P$ e% T) }# P5 e4 \6 dreset(fDesc); $ D' M  Z! l( v  I" D& j, w
每当我第一次运行到这里时,总会出现 I/O Error 183 的错误.
0 l3 f% F" u' C8 [% R% X最后我想这也有可能是没有清除 ioresult 的原因.在两句之间加入: l! o2 {( x3 d9 }- M. i0 Z
if ioresult<>0
8 S" Y$ F0 }) h+ rthen;
2 {$ j/ I* c3 K. `& W% Z0 L' l1 s9 \oooook! 可以了.4 ?4 Z! a# p5 J$ x& _: Z9 _! q

3 }! r  \* l. O; {* P3 h% d" H0 i' b. L
值得注意的I/O error8 {$ K0 Q7 h  d
AssignFile(F, fname);
0 |6 P0 n2 ^% a) HRewrite(F);7 l! k0 Z9 }8 h5 R9 L* F
当文件 F 经 Reset(F)打开的情况下, Rewrite(F)会引发一个异常: I/O error 32
7 y2 B' a1 ?) g反之,经 Rewrite(F)打开, Reset(F)也会引发同一个异常.  i" m9 ?3 a" Y& F
Reset(F)两次,closefile(F),再Rewrite(F),或反之,也会引发同样异常.. {6 ^& z5 O2 X7 L  ]2 j& q; K, K! c

- v7 e+ b3 \& |5 R6 j
1 s/ _. C; Q: D1 m9 w9 j4 Y. C( [, s; E1 B( i) d- Y7 H, m% s
string和pchar的相互转换:% ~0 A$ m- N/ u4 E: {! S2 _, D5 Y- P1 u$ L
string –> pchar: pchar(s. \; n) k' J. U5 `3 D4 F
tr:string);
$ L4 L+ H  b9 ?0 _pchar –> string: strpas(p:pchar);
9 A3 a. Z; X' V; i2 G( a, `! Q& ^0 I* w' ]: Q3 d* z: t" Z
+ B) H) V: p4 y
) ^3 q# t. R  e" ~
在Delphi代码中定义数据库/ n4 z) ?4 Z3 p4 n+ n  H' H
procedure tform1.create_tbl;
* T% m/ P! W9 X* N2 dvar tbl:ttable;7 s+ c, a4 }0 H: P0 D( r% L7 N
begin+ J2 b3 j+ Z9 U" M5 {
tbl:=ttable.create(self); // 如没有声明中的”tform1.”,Delphi不认这个self
$ w: D0 [0 v7 C% h0 O7 cwith tbl do
9 v/ k* |* K) K5 qbegin
. M1 m4 B5 S; g0 odatebasename:=;dbdemos’;
  ]$ _  f/ ?( H; {& f( R" m( Atablename:=’my_tbl’;
+ [( k7 Z7 Y0 i% U% Rwith fielddefs do* P1 g$ E! R& ^% L' N/ o
begin
, l$ }+ S: ~4 [: z$ bclear;8 N# y1 k8 t% k5 R* |. q9 t
add(‘No’,ftInteger,0,false);/ X+ K* J6 o# O& j$ @; S
add(‘Name’,ftString,0,false);5 G3 ^' H4 y% @: E) q

7 e' x$ b* m9 R* d! a- Wend;$ V9 K. i4 i9 T
with indexdefs do* J: e3 I8 p0 _2 |. X7 Y; y7 P! W' ?
begin
( h) S' u+ X6 L3 v1 [% S% T/ ]clear;
& T/ s/ C, ^( {1 ?" }add(‘primary’,'no’,[ixPrimary,ixUnique]);
, k+ u4 [8 x4 N) V, G" @! y* O3 W" ^4 s/ \2 W; S
end;
# r2 u- {4 ]* zCreateTable;
) {9 R1 I; ]7 w! V$ Tend;: k5 J3 H+ z" M7 q- u& f
end;% G4 |# ^/ _: K1 `8 @9 O0 x

  ~6 ?2 t" K3 w
+ ]' b- `9 m  ^4 O7 j9 y7 N0 Tstring、TStrings、pchar的相互转换(这里是我的个人经验)
, s5 H: L' Z0 `4 r" ^' r2 ~假设有如下定义:/ c2 M$ Z" v& K1 W/ O
var6 ]4 r- i/ x2 N! ?3 a
p:pchar;- e8 O  L. ~* Y% E
s:string;1 X; }( E4 G1 F8 x' N( j7 G* Q
ss:tstrings;
4 U% N3 F* _2 @' Z0 E3 N; ?" K8 W2 E. pbegin8 i$ p; \: B7 {: V& U( X0 M
ss:=tstringlist.create; // 开始时一定不要忘记创建ss: V3 [3 N. W7 d- ?, D
ss.text:=s; // string –> tstrings
( b( w1 H; L# O. h1 {3 [) G7 ds:=ss.text; // tstrings –> string
6 @9 a; o8 l& P, N6 [p:=pchar(s); // string –> pchar3 d0 Y. C4 a% B8 t: c3 b( _) }
s:=p; // pchar –> string
  y# x) r6 |, S% o/ zshowmessage(s); // 合法语句! @6 ~; z" x3 Q& I
showmessage(p); // 合法语句
/ \' P* m2 T1 O" C& `! Q" a… …
. _; k# [% E: `6 {ss.free; // 最后还要记着释放ss占用的资源
. Y. \+ w" |! B/ m  y9 `end;
+ X# H; a$ j8 C# @% ~" }4 @0 C+ q* M0 m

9 f  _9 ?' i" G0 n3 K0 ]; c1 D
* n8 i  ~! U/ z/ f' S0 J0 M; Z在设计Menu时,常用的ShortCut可从下拉菜单中选取。但我发现可选的ShortCut有些不在列表中,如ESC,Ctrl-Shift-A等。我试着在ShortCut项的右边输入:ESC,竟然成功了。再试Ctrl-Shift-A,这回Delphi自动把它变为Shift-Ctrl-A

TOP

發新話題