打印

delphi 技巧合輯

delphi 技巧合輯

INI文件的操作要点
9 y, ^# H' y( ]6 m' l(1)在interface关键字后的uses子句中加入
4 w" u* F4 n9 X! ]) y' ouses …,inifiles;
$ s% Y" g5 `! e: v* @(2)设置变量:var inifile:=TIniFile;
; [: u1 q; T+ `(3)使用前,一定要先做:) e# o/ E2 x, o; R7 ^
inifile:=TIniFile.Create(inifilename);
$ u, _! [$ H( _: J9 K2 f% D0 e我在这里绕了个弯子,写成- S% e" X) |/ s, o
inifile.Create(inifilename);; b  S% j6 C5 w

6 Y% _4 A/ f( V6 s, VTShiftState用来检测CTRL,ALT,Shift,以及鼠标按键的状态,8 L; j* {1 w  a: D
常常用在键盘或鼠标的事件处理程序之中。  [/ S$ }5 d+ l9 d3 r9 R2 \

# s" F) ~" a3 a, R( ^' MDCU文件(编译的库单元)的重用
/ O9 T% V" r- o# B7 q! |  L(1)在interface里的uses子句中引用。如Windows,Dialogs,
# r4 N1 X+ r0 d, {等等,要求被引用的DCU一定要放在Delphi 3\Lib子目录中。
( Q6 ?) H' I) E+ S9 F& m& F6 b(2)在implementation里的uses子句中引用。如果是自行编写的
' y) f1 w4 g% b) gDCU文件,应采用这一方式,并将被引用的DCU文件放入当前
" z, m; P7 v" N/ j工程所在的子目录中。/ e1 M3 m9 w$ J
executefile函数(在FmxUtils.DCU中定义)不能用在FormCreate5 Y' T2 }1 w$ g- m% A8 F
事件中。真奇怪……  m# L& Y% k/ @* e- K- h
) _0 r# `0 s( _, k) M5 s6 _: z7 E
内置的版本号控制功能
, \. I! n0 k; G在Project Options中的VersionInfo项里,有版本信息的定制,7 N8 B1 T! V7 o* F' O8 n- n
包括一个有趣的版本号自动增加功能(Auto-increment build+ U" U  ]' G2 ]3 \. _
number),即每Build一次,版本号中的Build Number加1。选中
) R* g+ w& R1 Q, w2 ^: O/ ?Include version information in project,编译,用资源管& d, [- c7 u4 J1 i: a; x) {7 Z
理器里找到生成的.exe文件,点右键,查看“属性”一项,就
: c& e; ^, g. M; Y. H' r3 B7 u会看到在属性中多了一页“版本”,里面就是你刚才输入的各! v  Q0 B0 H1 M& M
项内容。7 {1 q, ]) [& U/ ~, ?
- q' B  }9 r5 B2 ~8 {2 B3 E
( ]; c3 S/ m0 ~$ x! L( _
定制Speedbar2 r4 p5 n* w1 g$ e5 Q) m: Z
右键点击左上角的加速键条(speedbar),选中Properties,2 t0 y% }7 ~  D& k
在列表框中找到你想要加入speedbar的命令按钮,将它拖到+ U# e# U! V* {. M
speedbar上的合适位置即可。如果speedbar上没有多余的空间( `8 f; p5 `7 I4 G  q% h
来容纳新的按钮,可把鼠标在speedbar右框处变为双向箭头的# ?- N  z( b& V7 f, e0 z$ ?9 m) I
形状,向右拖动一段距离,就可腾出空间。如想删除speedbar% P1 S, h' V& {8 H7 y
上的某个按钮,可简单地把它拖出speedbar的范围,就能删除。, Z4 Z" ^7 y( G( R2 Y3 k. s: Y, A

7 H* @. I& A# i" i3 E8 S% u
3 {3 i1 e# d! Z1 G计算出的字段3 x+ o5 f" A* X; x
在写一个程序时,我要在DBGrid中显示出一个memo的部分信息,当我把那个
# d" ~$ V+ a; e1 |- }memo字段放进去后,运行时只能显示出“(memo)”字样。从书上找到计算字' W9 x" j7 |/ L/ w+ s5 `3 e
段的用法后,我在TTable中增加一个计算字段MemoHeader,宽度为40,在此
& o( c! |5 b& wTTable的OnCalcFields事件中输入:* ?4 s* Q  _7 K$ Q6 P0 i; d# s
with MyTable do
* r4 K' i' K1 uFieldByName(‘memoheader’).asstring:=FieldByName(‘memo’).asstring;* C/ K2 x; q2 ?+ ~, B( z  y: b
在DBGrid中放入MemoHeader,运行,OK!0 P  S2 L6 E1 B5 D. r0 y1 Q

! t; z+ e+ {  `
. j, Y2 e2 j( R6 U) E字段编辑器; c, s9 R+ ^; M$ v) p0 D+ X* W0 M
解决了上面的问题后,我继续学习字段编辑器的作用。原来,DELPHI通过字9 M3 z2 ?* A* \$ _
段编辑器,近乎完美地实现了数据库的字段级的控制,这包括:
/ h  h8 `7 U! j- j5 J1 m& [+ c2 @' B1)字段在DBGrid中标题、宽度、能否可见;
) L. ^, |2 V6 n8 w2)字段的显示格式和编辑时输入的过滤条件;3 l! q' t0 ]6 v- q. w$ S
3)字段是否只读;) i1 h/ R: n- ?0 @0 _- B
4)字段的类型:数据字段/计算字段/查询字段/内部计算字段;
# R  x% o' n/ z3 R$ \) ]1 a  N5)字段的显示/赋值/修改等事件的定制。" S* n5 X5 c7 [' s( i8 H5 V. b, }

( j5 t( U7 A! v+ t1 L: p- t8 C& V" ^" F$ \" B+ x/ `" j6 D, e
设计Form时的快捷键/ [: G6 M9 U: H) P' R$ M0 j
Del 删除所选组件! Y% f( E  ?2 L; K; m+ A7 H
Esc 选择当前组件的容器(通常是Panel,Group或Form)
5 c3 e" a/ ]: G+ k* D, e1 gF11 在Form或Unit和对象检查器之间切换
( X2 O& O$ A0 e$ }* |. ^* _, mF12 在Form和代码编辑器间切换. Y! U+ ]. G% p! t/ }% W0 O3 U. g
Ctrl-F12 显示“查看Unit”对话框
  r0 c; Z9 o% T* y5 t- N( X% bShift-F12 显示“查看Form”对话框4 @4 _) L3 E3 U' y  m  k. X
TAB 下一个组件
# X+ s) W5 o$ uShift-TAB 上一个组件/ j/ I) U  u( b! ]% x  }
方向键 选中此方向上最近的组件7 C) n; }9 ~. m% c+ j4 L
Ctrl-方向键 将所选组件移动一个点
6 m6 I  I' R0 J$ a( n5 H9 K9 BShift-方向键 将所选组件改变一个点的大小- l3 P7 o) x8 Z/ E4 K) w  q9 P
Ctrl-Shift-方向键 将所选组件移动一个格
/ C( Y- p4 b; L! x& }; z6 E8 pShift-click 按住Shift键再用鼠标点击组件,可以选择多个组件。
0 S7 h! S" ~6 u; G" w7 S" q7 [–= 下面这条是我摸索出来的 =–) N3 d, H, g+ V  ?" l
Ctrl-drag 按住Ctrl键在一个容器组件(如Panel,QReport,Groupbox等)
& Z, H; q8 d7 O里拖动鼠标,可强制选择鼠标拖过的矩形框中的所有属于此容3 O& Z. y$ z" u, I$ u& k4 c
器的可视组件但不包括该容器组件。7 V: M: q% _4 @- g& a
$ n$ G, H/ p% V0 x2 t. Q

8 o6 E! Y3 j: W* x使用QReport的若干经验
2 i8 d8 u. F( \1)QuickRep1.DataSet:=query1
1 Q9 B7 |) ~8 X7 P) f5 l不然无输出结果
3 [( g  ^$ s* p' @/ a+ ~. R2)从qrpt2man.doc中查知,格式化输出结果的方法是:
- R  g$ O/ p; t在QRDBText.Mask中设为.00;0,将使输出带两位小数。
, Y. b5 S9 P$ b# m3)设置Group时,先加入一个QGroup,再加入一个QRBand,将QGroup的$ N  g* d4 g3 q+ a! j
FooterBand设为刚才的QRBand,就可将其联系起来。
- |& w, y5 ]6 k7 c" W! i8 Z4)在Group中打印的合计数,其ResetAfterPrint设为True,可实现分组合" B  b& J, n7 x; {# F3 V# ~

/ b* p0 Q  y, ~format(‘%*.*f’,[8,2,123.456]); //等价于format(‘%*8.2f’,[123.456])
. p/ }4 z5 P( v) u+ }format(‘%d %d %0:d %d’[10,20]);- x  E) u$ n4 }6 n

$ P, s  F, H/ ?  U1 r- E$ I% F( {( a( P0 s' G' J. Z
0 Q' E1 Z' U+ X; _* y2 P: j2 @
播放一个wav文件) I7 n4 F1 F& h- G# {, ~6 R, o
use mmsystem;
: m8 G/ _3 A( @SndPlaySound(‘hello.wav’,SND_FILENAME or SND_SYNC)0 h9 ^2 y* F/ ^% }

: W6 {3 K9 \4 i+ T使你的form适应不同的显示分辨率/ J; N  ^9 |; k7 ?' M* G, R
假设你在800*600的分辨率下设计的form,第一步:/ o* k8 [# I2 |8 P' d% T7 w) _- w1 J  S
inplementation2 V. t& D: y* O, N
const! ^( |* j0 |+ D7 O! ?4 X
ScreenWidth: LongInt = 800; {I designed my form in 800×600 mode.}! @0 g- g; {  s! E% o% V. \$ G0 A
ScreenHeight: LongInt = 600;
9 p8 U+ s1 k: z) \" E' t) Y  u; A1 o+ F" G1 ?3 H7 H
{$R *.DFM}
5 l+ B' H- E  O& B
& S9 H% X5 U/ O( x" Z( Sprocedure TForm1.FormCreate(Sender: TObject);
, K" b, ~% u- N1 ~* Rbegin
) g  ]) ^6 Z8 s# ^' R5 Hscaled := true;
: I' a: Q( I% k' ~  Fif (screen.width <> ScreenWidth) then/ z& r. Y& V# n6 B1 b# Z$ \
begin
' c$ m7 M( r: k" _- E: x# @height := longint(height) * longint(screen.height) div ScreenHeight;
2 B4 ^* n2 P+ E( u. U! uwidth := longint(width) * longint(screen.width) div ScreenWidth;" |/ n1 J6 v) N( {: o! a. l5 E5 k
scaleBy(screen.width, ScreenWidth);
6 U# W! i, }5 a: n2 k. o  |+ gend;
; ]+ p/ ]6 N+ S3 c9 y, Rend;
7 H; {, @; l+ E) q3 M" M* j& ^3 Y
下一步,要让每个子控制的字体改变到合适的大小:
' ]' T; `& J; atype
% v: R9 e' {! j8 g1 _/ TTFooClass = class(TControl); { needed to get at protected }7 x, E: C) l6 C3 g5 G) v3 @. m
{ font property }3 b# D8 z: z, `
3 Z) Q5 f) S/ X# t
var! _. N, z( b; M+ e# y
i: integer;
1 V& X2 \2 M2 @. P- @6 nbegin; O- [4 W8 s' _0 _( \) a6 U* M* u
for i := ControlCount – 1 downto 0 do
4 p6 @+ t" l5 \, b- e1 `+ p9 RTFooClass(Controls).Font.Size :=
1 t5 ^$ T+ q: V# T  m. g$ u(NewFormWidth div OldFormWidth) *
0 H) q. }/ b  {/ h' }+ qTFooClass(Controls).Font.Size;9 h- C1 V8 J. ~5 L' n
end;
7 t" T! Q6 q7 f& X3 R9 D! t+ h2 h# b6 P. t: P3 ~! W) A) d4 r
用raise引发一个错误处理例程
0 [# d* ]* c4 H- |& b8 I# L示例:先给出下面的定义
+ `& m7 ]1 S+ m7 ?* s4 Htype EPasswordInvalid=class(Exception);' M( r. Z, x# r* M- r
这样你就可以随时引发一个”password invalid”的例外:; i! M; _2 z, X- i
if Password<>CorrectPassword then
$ r* \; _+ H8 z$ F+ T4 u2 Kraise EPasswordInvalid.Create(‘Increect Password entered’);3 Z9 X1 w8 V% D/ E
运行后,出现信息框$ N8 i* c' p1 h9 }, |' Z) f" t
Project Project1.exe raise exception class EPasswordInvalid. @1 C# |4 V5 w
with message ‘Incorrect Password entered’. Process stopped., o( L  I$ O2 y8 P3 F
Use step or run to continue.$ w) C0 z" D9 \5 a( F
再按Run按钮,出现一个信息框:* L7 d5 X8 L, K) y* A
Incorrect Password entered.+ ^6 P- e& X  X' q$ X5 \
0 L3 V9 n! D) u# [: F) K
5 b* h1 `: p7 O$ C
从DEMO例程中学到的若干小技巧# g  r) a/ j9 b
在demo\internet\http\webbrows\main.pas中,
9 N, e* z2 ^: ^0 dprocedure TForm1.DocumentSourceClick(Sender:Tobject);8 W) X7 b3 \4 A. A- W, p
begin
$ C& t. i( U5 v$ \8 L! V5 B( _with DocSourceForm do
) R: Y1 [& R: p* q3 R% u9 Abegin
# I  P, M4 E4 A6 J" U0 i4 Hshow; // 显示HTML源码的FORM' |4 q& k- s5 v% ^/ ?2 a# Z5 T
Memo1.lines.clear; // 清空memo1中内容
6 r% v# y, d4 ~: Z+ |Memo1.lines.add(HTML1.SourceText); // 植入源码
' D2 H1 c; j- V+ CMemo1.SelStart:=0 // ***& G2 j- h4 X+ ~2 ^
SendMessage(Memo1.Handle, // Memo1的窗口句柄
- Q6 U" x% U$ X4 cEM_ScrollCaret //将Edit Control中的caret光标滚动到视野中
( x# E: u* [8 I7 s! _2 n5 @% k1 r5 B0,0 //这两个参数暂不使用
/ c- H" W0 M& d; G2 Vend;# ]# O1 J' I. `  Q) @
end;* t  e# e+ a0 ~2 ^
(此SendMessage系一WinAPI调用,给一个或一组窗口发送消息,直到
3 ?: |2 K+ `/ S- \  N" E相应窗口处理此消息后才有返回值。相似的另一函数为PostMessage,
! H+ O% N. a; v5 z8 A4 v' X2 e/ R它将消息放入消息队列中后立即返回。); ~6 x9 Z6 [8 Y1 A9 v
*** 清空当前选择并将光标移动到指定字符(0代表第一个字符)。如同时
- f  v9 {; W& i" [) \2 ]: c设memo1.sellength为一非0值,可选择一段文本。
# R( V7 K) ~& @. l( @) B' ?8 a
& d8 e/ n1 @. F% H
" O% B! U4 c+ n奇怪的I/O error — 我在开发过程中发现下面这两条语句' y2 g% R% w$ ^% `" z
assignfile(fDesc,CDDatadir+describefile);
$ E$ L$ K  _1 }& Ireset(fDesc); 7 C3 V3 V' a* N" T  m9 S6 @$ u
每当我第一次运行到这里时,总会出现 I/O Error 183 的错误.
& f9 q7 X5 N; i; Z8 |6 f7 Z最后我想这也有可能是没有清除 ioresult 的原因.在两句之间加入6 A* J  x/ b6 y
if ioresult<>0
( Z" }; |" Z$ Vthen; % u3 Y; q, A+ I# D/ y
oooook! 可以了.
" z% O2 W9 L6 f) ]) S5 m2 ?- j0 Z, ?: q3 H
3 ]# ], O" {3 P( @( m* s4 }8 t
值得注意的I/O error
5 _  I+ G0 Q# Y8 x& s6 Q) A" \$ A% [AssignFile(F, fname);
* }) t+ P  ?; N& [Rewrite(F);
) N) o" A; Z5 e当文件 F 经 Reset(F)打开的情况下, Rewrite(F)会引发一个异常: I/O error 32
( M/ j1 r3 A  u反之,经 Rewrite(F)打开, Reset(F)也会引发同一个异常./ Q! e; ^/ C2 ?* i# t! X) z
Reset(F)两次,closefile(F),再Rewrite(F),或反之,也会引发同样异常.0 n# f" A/ e. d
3 K. T8 l) q- J0 n1 R* B  c

, P6 c2 H2 r3 ~4 R7 P5 T' R8 k% {1 N+ ]
string和pchar的相互转换:. g$ N9 {% U2 |) b( j
string –> pchar: pchar(s  N/ `( y. T& @
tr:string);2 C3 g2 v: J* R
pchar –> string: strpas(p:pchar);: E: o$ m) {% P4 r' p; f+ K8 O
$ I' b! t4 A3 J% i* p5 J
# ?/ \, b" ]; e2 G& i- j4 p+ H
: b. }$ k- P- e1 h# g
在Delphi代码中定义数据库. o" r1 L- o, h; i* G' t& c
procedure tform1.create_tbl;
; }2 Q2 Z; x0 n* G7 Hvar tbl:ttable;3 t' v9 _* B* x
begin) k/ w. X. s7 D% c" Z; f( w
tbl:=ttable.create(self); // 如没有声明中的”tform1.”,Delphi不认这个self
) u& }, u7 p3 l: U  W- x2 ]* \with tbl do
$ H5 Q5 F* |0 \, k+ J: }' x2 F- W/ X6 Mbegin5 j6 T% p3 F* h( y) R# ~8 n
datebasename:=;dbdemos’;$ B3 x  u0 k# N" ]9 }
tablename:=’my_tbl’;# e) z" X& r& Z1 W! F
with fielddefs do# `1 R; n9 f9 F' [% q# j% P
begin0 h5 D% R' E; {3 n. ?
clear;
: q4 ~. Y; ]2 J+ E+ e; q% e/ }2 @add(‘No’,ftInteger,0,false);
3 e7 N: ~: a% hadd(‘Name’,ftString,0,false);
! O2 O7 C+ U( w7 |* S$ B* u
0 w, ~* E6 s4 }5 S/ a4 Pend;
% n: c' V/ \# P  Z9 H& R. Nwith indexdefs do3 C- x5 r% w' z# v7 V6 l2 U1 @
begin
, ^; q) V6 [/ J2 [+ K0 B+ n2 j+ \clear;9 H8 l3 V) h  S3 S9 D$ g; Z% s( l
add(‘primary’,'no’,[ixPrimary,ixUnique]);
6 s& t! v" ^' N/ U5 i( k' I0 Y3 ?0 B5 h
end;
) X( y) H. \2 W% Q4 J! m& |CreateTable;1 L/ g, q& G8 a! p9 Z7 R
end;
# Q! e, J  O2 w9 w8 S' Wend;
1 M, M' V* S/ R" Q2 c0 W: X$ c3 l1 |: W; e
. I% V7 U; f+ o
string、TStrings、pchar的相互转换(这里是我的个人经验)
, v1 ~0 u; A  E2 F+ x假设有如下定义:
! j) X5 q+ M. Q. E* a! pvar
9 b) D: X7 Y3 |$ \! cp:pchar;; J0 X: E$ w8 _9 n6 T2 d5 V  T9 V
s:string;
! q2 D: U1 j$ i, v' Iss:tstrings;2 E( w" B6 B; W6 ]' h( `" f
begin9 L5 [; Y- Y' @2 i& }6 l( k
ss:=tstringlist.create; // 开始时一定不要忘记创建ss( w: e: v* o: F7 y
ss.text:=s; // string –> tstrings/ Z! P1 T' |+ N7 T; q& |
s:=ss.text; // tstrings –> string5 U: ^( G5 ]9 y1 k' d$ z
p:=pchar(s); // string –> pchar# F( z: S! f$ v4 h4 W
s:=p; // pchar –> string+ H- a2 u5 H" y1 @9 h4 [) A' \2 w
showmessage(s); // 合法语句
. }! f- s0 ]$ a* M7 k8 S" ~showmessage(p); // 合法语句  W- g, D' V- B
… …
6 G* M5 ~: k* \6 D& Y9 `ss.free; // 最后还要记着释放ss占用的资源& _0 k/ f7 `9 y: W  M: g7 Y$ O; o
end;3 U$ J) V! J  p# `

5 m: X6 o' d: Z8 K2 S8 v! m$ r$ }, j) b% F$ z

$ }* z! H7 D. R, K- W- R% e9 i在设计Menu时,常用的ShortCut可从下拉菜单中选取。但我发现可选的ShortCut有些不在列表中,如ESC,Ctrl-Shift-A等。我试着在ShortCut项的右边输入:ESC,竟然成功了。再试Ctrl-Shift-A,这回Delphi自动把它变为Shift-Ctrl-A

TOP

發新話題