打印

delphi 技巧合輯

delphi 技巧合輯

INI文件的操作要点
: @6 b! c1 Z  R(1)在interface关键字后的uses子句中加入
2 X5 v" x4 I" S" tuses …,inifiles;1 p6 k; C7 p, J3 ^7 U7 o
(2)设置变量:var inifile:=TIniFile;
! d3 A: c3 e# N4 N' I& d(3)使用前,一定要先做:1 F, g! Q. x! U7 v: \4 j( o
inifile:=TIniFile.Create(inifilename);3 Z8 R& s& c9 c6 [0 J
我在这里绕了个弯子,写成+ N+ Q4 y  Y' H" E: }
inifile.Create(inifilename);
! S- {7 n' }: o
3 Q: ^: O# v; w% o; N( g5 h6 `TShiftState用来检测CTRL,ALT,Shift,以及鼠标按键的状态,6 X. L* c2 X4 a/ l& a) `9 ?% [4 q
常常用在键盘或鼠标的事件处理程序之中。
0 w0 C- c, A0 b) D
7 j  D7 x5 ^& V' v- @, W% o: V" w; Z/ n* eDCU文件(编译的库单元)的重用+ e: ?& Y! h) [& J3 D5 _
(1)在interface里的uses子句中引用。如Windows,Dialogs,* l9 D+ \* I7 [! k% @. v: L
等等,要求被引用的DCU一定要放在Delphi 3\Lib子目录中。
8 S" R6 R: \. P2 u(2)在implementation里的uses子句中引用。如果是自行编写的% U0 H0 U, ^/ x6 Y; d) _/ x
DCU文件,应采用这一方式,并将被引用的DCU文件放入当前
- V6 a! L0 |/ E工程所在的子目录中。+ E- ^! [0 o7 Q4 k, W
executefile函数(在FmxUtils.DCU中定义)不能用在FormCreate
3 G& J* p/ d, F, S事件中。真奇怪……, a: B$ a9 c3 u9 N" B5 C, A
9 v: M$ Q+ _1 x, g3 P9 s
内置的版本号控制功能
, d+ s! t1 P* b- ^在Project Options中的VersionInfo项里,有版本信息的定制,' M+ J. L5 ^: `# z
包括一个有趣的版本号自动增加功能(Auto-increment build
( S5 T8 u2 T2 ~' @& Cnumber),即每Build一次,版本号中的Build Number加1。选中& T0 l. `2 Q2 c1 r
Include version information in project,编译,用资源管$ L3 R' T5 E. _" w; o/ i
理器里找到生成的.exe文件,点右键,查看“属性”一项,就' W- L! M; w8 H; z2 u
会看到在属性中多了一页“版本”,里面就是你刚才输入的各
. R/ T$ m* I4 t3 P/ i/ B& P7 `. l0 s项内容。! J0 T5 l$ ?5 Z8 F* |

0 B' e" X0 q& z* T  C1 P$ i* P8 G, s4 t. h# p
定制Speedbar
8 P  M# K( s+ m, \/ k+ l5 d右键点击左上角的加速键条(speedbar),选中Properties,
- R7 m* K# h' P5 b& h) k在列表框中找到你想要加入speedbar的命令按钮,将它拖到+ ^5 B" I0 T+ P4 e4 o
speedbar上的合适位置即可。如果speedbar上没有多余的空间1 V2 Z% f) Y( D% m* [; n
来容纳新的按钮,可把鼠标在speedbar右框处变为双向箭头的) A& ^/ l  M- ?: k4 f- A$ g4 [
形状,向右拖动一段距离,就可腾出空间。如想删除speedbar
8 N3 n( z: F6 D1 X" `; e上的某个按钮,可简单地把它拖出speedbar的范围,就能删除。: F& b. E; i: F" }: T/ r6 t

. m9 i: i% Z2 B) n
  M- k; G. i: F2 J计算出的字段$ A. h, X5 G# [% o5 r; T! w2 O' O
在写一个程序时,我要在DBGrid中显示出一个memo的部分信息,当我把那个8 ~% W8 ^* M. E4 r9 Q" L
memo字段放进去后,运行时只能显示出“(memo)”字样。从书上找到计算字- @% v6 x  n. v3 p- t' x
段的用法后,我在TTable中增加一个计算字段MemoHeader,宽度为40,在此' {( ]& q" Q- V- ?2 N
TTable的OnCalcFields事件中输入:( Y" Z6 c' s% n! e/ e
with MyTable do
! w+ D3 c+ Z. u& z4 {6 V: fFieldByName(‘memoheader’).asstring:=FieldByName(‘memo’).asstring;
  _$ ^0 \/ x1 I5 N/ D在DBGrid中放入MemoHeader,运行,OK!5 L( y  ~5 X. A2 z6 B  L8 i, v

, ]: G' H3 X; X9 g
! a3 K& p3 S7 J% o字段编辑器
$ y3 s* }5 r% X: e$ X9 ]3 U: T( O解决了上面的问题后,我继续学习字段编辑器的作用。原来,DELPHI通过字! B( |9 L" U/ O" b
段编辑器,近乎完美地实现了数据库的字段级的控制,这包括:
) t( c2 P1 E$ `2 A1)字段在DBGrid中标题、宽度、能否可见;
' ^1 ^- q! _$ j7 y4 W  N0 ?. j2)字段的显示格式和编辑时输入的过滤条件;
2 I  g! W* K, a! O1 Z! n7 c3)字段是否只读;+ p' ^- k2 Z: `( W% _% U
4)字段的类型:数据字段/计算字段/查询字段/内部计算字段;
! L" L; a2 \8 }+ e5)字段的显示/赋值/修改等事件的定制。
4 [7 h0 G- }; W" k4 Q: B9 A& V  F5 d) x- d
0 V/ {! s0 `9 F& X7 L7 m
设计Form时的快捷键
  d' @  S" ^; S0 ?Del 删除所选组件
& e+ j9 s- Q+ gEsc 选择当前组件的容器(通常是Panel,Group或Form)
# M# l3 Q/ z: `+ z' G6 E; G6 qF11 在Form或Unit和对象检查器之间切换
8 ?/ N. y7 I& |. oF12 在Form和代码编辑器间切换
4 N* {* ~3 Q* ?) \Ctrl-F12 显示“查看Unit”对话框
; c' ~: m1 ?) r! N+ v( b; zShift-F12 显示“查看Form”对话框5 b# C" p- ?  K4 e- @
TAB 下一个组件
. X4 {9 y: t, A: Z% K6 O% e" `Shift-TAB 上一个组件
6 u- j6 q8 b! q: N, r方向键 选中此方向上最近的组件* C0 |3 C* z: V1 f( D
Ctrl-方向键 将所选组件移动一个点4 r$ g; b- h) A' S  c" p- X1 b" G
Shift-方向键 将所选组件改变一个点的大小
5 D' U0 H0 X% k# A+ ]1 oCtrl-Shift-方向键 将所选组件移动一个格9 E6 ]- y. T2 U' I2 ]( A
Shift-click 按住Shift键再用鼠标点击组件,可以选择多个组件。* F. j8 U8 a( L
–= 下面这条是我摸索出来的 =–5 {# V+ y: X# J2 }' _8 _9 h6 U) v
Ctrl-drag 按住Ctrl键在一个容器组件(如Panel,QReport,Groupbox等)8 P7 Q" S( A7 s# [( i
里拖动鼠标,可强制选择鼠标拖过的矩形框中的所有属于此容1 ~9 Q# O4 n& B) C
器的可视组件但不包括该容器组件。
/ }- ^$ X, a) x
5 Z" e6 R( _6 H2 @0 E6 B8 N$ k
: ?6 F9 u: C8 ^使用QReport的若干经验
/ x2 `$ D6 ]* Q5 \5 j# I' q. |1)QuickRep1.DataSet:=query1
- R& x/ |2 x% }: k不然无输出结果
. {# O$ u& C# w3 \8 I4 p# K% O2)从qrpt2man.doc中查知,格式化输出结果的方法是:
1 H& U9 n) V2 L- P% x: b在QRDBText.Mask中设为.00;0,将使输出带两位小数。
3 F& [) g. g- l" g3)设置Group时,先加入一个QGroup,再加入一个QRBand,将QGroup的7 f0 ^! }. z6 T! Q- O% n" i3 L  B2 M
FooterBand设为刚才的QRBand,就可将其联系起来。
& p. F$ H* g0 s% }0 S! P# a4)在Group中打印的合计数,其ResetAfterPrint设为True,可实现分组合; h$ w8 `9 M) I7 {9 Z1 ?9 [. ]7 u# z

: {8 M" R. G7 n4 lformat(‘%*.*f’,[8,2,123.456]); //等价于format(‘%*8.2f’,[123.456])
' d$ N/ l8 ]4 y8 jformat(‘%d %d %0:d %d’[10,20]);; W3 t$ F& d  C; _1 t4 D4 J
* z1 U4 O7 ]. \3 w
& G) Y$ r+ t8 D/ @' o

3 x2 ^% N& m9 o6 R播放一个wav文件# r- n( J+ S5 h: ?% n4 w$ u2 d
use mmsystem;
2 h; a3 _1 O3 `* ~. B/ U4 }SndPlaySound(‘hello.wav’,SND_FILENAME or SND_SYNC)8 o3 V+ L$ e1 {$ d
/ k% _1 L, ?' w1 d2 Z. x, e
使你的form适应不同的显示分辨率
) r% O( i6 C1 t' U. E2 S7 C) T假设你在800*600的分辨率下设计的form,第一步:
0 f7 P4 }  B' u9 H+ h- m/ Finplementation/ [- U5 {8 c& i
const4 ]/ w6 n5 X7 I
ScreenWidth: LongInt = 800; {I designed my form in 800×600 mode.}
' @) n' |( `6 G! [# T" pScreenHeight: LongInt = 600;, V: Z+ s* i' |) X/ K
) H- v5 q+ y( ~; s. V
{$R *.DFM}8 H" @( `% L; s  i5 Z: H/ n
6 R, p* T9 c+ S( P. _$ [9 C
procedure TForm1.FormCreate(Sender: TObject);
  m8 F; b, Z6 Y. |7 V/ j7 Gbegin
8 v) p" H. B% U# u, \8 F7 |scaled := true;
5 |4 Y. ?7 W! a9 C9 Cif (screen.width <> ScreenWidth) then  R/ [5 m6 F3 \! Y- R
begin
" H# q% V* \& F2 y2 k6 I, `: |8 z" Mheight := longint(height) * longint(screen.height) div ScreenHeight;
5 n& x/ b7 j  C& J8 @' N2 A* C" Dwidth := longint(width) * longint(screen.width) div ScreenWidth;
/ V9 N' k0 m: g4 s9 F2 U; EscaleBy(screen.width, ScreenWidth);
) \$ c* m8 j: uend;# n  x& M* I8 g# ?9 ~" Y4 o$ V9 E
end;
! f, G: M1 P- X$ v8 T
" e% X# T; H0 b1 ~3 T% L下一步,要让每个子控制的字体改变到合适的大小:
/ A# M, \3 J9 a* ~8 d* Utype9 \! y! F2 z: L  y
TFooClass = class(TControl); { needed to get at protected }
. a* Z* h8 t: d: C( h! t4 |- @{ font property }9 ?* C/ t- V# K+ l2 e
9 R( w0 I# ^, }" s' V
var
( \0 q# ]* ~+ M" ~1 B* n1 ri: integer;
0 Y* L8 _0 }$ tbegin
: I2 a- x# A4 z) `: _' ifor i := ControlCount – 1 downto 0 do
' K- P; X. j' g8 s. R& ^; K) b+ M4 qTFooClass(Controls).Font.Size :=
7 Y  D" o8 B0 J(NewFormWidth div OldFormWidth) *2 J! M. y0 r% _, M: N4 y. ?& N5 e
TFooClass(Controls).Font.Size;/ X- m/ F. d; n5 }
end;
5 `; e1 e- f! l0 f- T1 w# h6 O6 A% d& p% n
用raise引发一个错误处理例程
, P! _/ V+ [7 W$ Z, E7 }  x示例:先给出下面的定义- Z; C/ y) L" i0 o" K2 B/ O
type EPasswordInvalid=class(Exception);, Q" k: D2 d# F1 D
这样你就可以随时引发一个”password invalid”的例外:# G: _" d/ h& \5 k, Q( m$ C
if Password<>CorrectPassword then: `9 N5 C" r, ?4 }' N
raise EPasswordInvalid.Create(‘Increect Password entered’);
5 m- z/ V1 Z9 O8 @9 o2 [# {+ P, L运行后,出现信息框
: ]1 a0 f7 T5 z7 yProject Project1.exe raise exception class EPasswordInvalid8 F9 w) n8 p4 p/ R# a4 L6 ?1 x
with message ‘Incorrect Password entered’. Process stopped.4 d/ h5 r8 Q  Y
Use step or run to continue.
8 h& |* r$ J: A9 j7 w再按Run按钮,出现一个信息框:
% J* }5 Q9 f% ?- LIncorrect Password entered.
0 v4 H: f4 t& d! t2 P( L
0 D( z* _" ^0 I  h6 c+ K5 S1 e8 A$ D' Q/ V
从DEMO例程中学到的若干小技巧, s8 q- J  j5 R; L& t  F
在demo\internet\http\webbrows\main.pas中,
0 n% B0 X" F" y9 sprocedure TForm1.DocumentSourceClick(Sender:Tobject);. |  D" N8 H! k: Y) z( Z2 d
begin& P  I. q9 F: \3 {
with DocSourceForm do
& [$ U* ?$ u0 Z0 H  q3 ibegin. P# |  @5 z) ]$ p/ T3 z" s( B$ `
show; // 显示HTML源码的FORM
8 u7 e7 q/ }( A+ e; P3 G/ V9 NMemo1.lines.clear; // 清空memo1中内容
! ^/ S! _# X2 l3 {$ GMemo1.lines.add(HTML1.SourceText); // 植入源码" T: Y9 |( B4 s
Memo1.SelStart:=0 // ***
6 v- c- H8 v4 ]4 i; |! \SendMessage(Memo1.Handle, // Memo1的窗口句柄+ j. n; x: ^6 \8 v6 E5 {! v5 I- o
EM_ScrollCaret //将Edit Control中的caret光标滚动到视野中
" p3 n1 O3 T5 G, |8 _: }0,0 //这两个参数暂不使用
/ n( `' H1 E; t8 h7 vend;
* h  C6 ~% ^4 y$ Gend;$ @+ {& x7 I8 O! r# B* X: y
(此SendMessage系一WinAPI调用,给一个或一组窗口发送消息,直到8 J+ ?! M" m9 C. r* W) r5 f
相应窗口处理此消息后才有返回值。相似的另一函数为PostMessage,
! ~! ?/ w1 l( H# B! V8 F它将消息放入消息队列中后立即返回。)
- h' v( h8 C& h+ {* N/ d*** 清空当前选择并将光标移动到指定字符(0代表第一个字符)。如同时8 ~( A$ B& t9 ^% e
设memo1.sellength为一非0值,可选择一段文本。4 t. D" ]" {1 S- H4 r( Q/ \- L4 t

$ j- o0 D" O9 Q% P3 ?. v. z( X- M
' J8 J- t; J1 K2 c奇怪的I/O error — 我在开发过程中发现下面这两条语句$ {$ A7 H8 v7 N- J- ]$ T7 |1 \
assignfile(fDesc,CDDatadir+describefile);' R' k( c9 K4 T
reset(fDesc);
* p, O9 r' B  K  i每当我第一次运行到这里时,总会出现 I/O Error 183 的错误.0 B- ^4 e- g0 U7 _  R5 T* O
最后我想这也有可能是没有清除 ioresult 的原因.在两句之间加入3 A" v: y8 L" ]7 t# V& R4 _
if ioresult<>0
# F# T" N  d6 i% u' ?- Ithen;
5 V& s  S" ~/ b2 _" yoooook! 可以了.8 {' s( v$ X( }

0 @% d3 \9 H& T" @# o% D: T, k$ U; R5 Y/ J. t2 \- x1 y
值得注意的I/O error( n  M2 g4 C( a+ A+ g! K
AssignFile(F, fname);
/ n! E# m3 h- C. l6 O3 s4 }. tRewrite(F);
6 {7 b' V4 c8 |当文件 F 经 Reset(F)打开的情况下, Rewrite(F)会引发一个异常: I/O error 32( |5 F& ~) R" u; N& S, M
反之,经 Rewrite(F)打开, Reset(F)也会引发同一个异常.  S6 e) W/ f+ K8 B
Reset(F)两次,closefile(F),再Rewrite(F),或反之,也会引发同样异常.
7 T4 ^) q- J. f3 c0 ?
, t* ?7 C! q+ s' k5 e% f5 D' K; {+ a9 q: i* R( g5 g

! }' p/ ], G$ N9 d" y" {; a: Ostring和pchar的相互转换:
1 X+ N  \5 O+ B, n% `string –> pchar: pchar(s
7 t/ e6 r" _, f6 ltr:string);8 R; t) q  M/ I8 D6 E: |, ~3 l7 b0 K7 l
pchar –> string: strpas(p:pchar);
1 N8 d( I) a8 M% }; P3 Q( k9 R8 M. U2 A- D; q4 a9 K

' I! V7 w+ s' \) T( x0 }& _  ]) ?; }3 c8 e3 K
在Delphi代码中定义数据库
* A- t6 J  j& Z% w# `( Lprocedure tform1.create_tbl;) Q1 T/ f0 e& n8 T, U+ b
var tbl:ttable;2 H2 t4 v7 ]( q* \% P
begin
) ^7 d2 T  e( K) E8 Ftbl:=ttable.create(self); // 如没有声明中的”tform1.”,Delphi不认这个self
$ B5 J' H, U* O  V  t* P3 hwith tbl do
" w7 X& J. w* i# i( \, g1 Rbegin. d# W1 {, b2 D! {2 r% p& x
datebasename:=;dbdemos’;0 T0 Q6 d. u. L+ W! ]9 _
tablename:=’my_tbl’;- k! ?5 }2 n# s0 Q- C' r2 Z, w
with fielddefs do
: J( i# n8 O1 ubegin
+ A5 l# C, Y' C0 ?: Qclear;+ t+ M4 Y) Z. @0 k7 T
add(‘No’,ftInteger,0,false);8 J7 L/ s, y5 ]( b, a3 ]" x% c8 U9 }
add(‘Name’,ftString,0,false);2 W; W/ D- x" J4 b8 O
# A4 y! H% G% `$ Y
end;, e5 `9 S( w0 r0 B
with indexdefs do! J( N% v$ [$ Z. P( T* m; W
begin0 Z3 C' M) V5 q9 Z5 i; Y
clear;
. B' v9 T* v+ H2 R2 Cadd(‘primary’,'no’,[ixPrimary,ixUnique]);
  D+ Z, o% [1 o! o- V- E' A( S6 M. k. E& F& o/ _" w% |# ~7 f
end;
0 ^; J' l0 `( q5 m, c" f$ L# tCreateTable;
' S/ C0 {$ r# k2 J7 Jend;5 Y& w5 s, J( e$ O9 X
end;
. N) j$ f/ n* [1 e& W
+ ], s" `, h% s8 Z/ p% w& p$ f" A; p  v$ I0 l* U, ]( X% b
string、TStrings、pchar的相互转换(这里是我的个人经验), N2 q$ s" l6 r9 Y
假设有如下定义:8 g4 u$ }3 @+ L' l- w6 N  M6 M
var9 `6 }( J/ @1 y( f+ Z
p:pchar;
9 F- f' a+ q. r" K* e3 es:string;" r$ f5 h& A: o$ \& x9 e
ss:tstrings;/ y, R6 u6 [& M. S! O& Q
begin
( h( X# H. W. o2 S1 a$ j9 H9 [ss:=tstringlist.create; // 开始时一定不要忘记创建ss" D2 y5 W& p2 A: G# b# h3 f( K
ss.text:=s; // string –> tstrings
' ]3 f+ ~5 v; g" N: [$ Q, is:=ss.text; // tstrings –> string! I6 }) W; L  u* r3 a
p:=pchar(s); // string –> pchar
8 [) m" X% k* Y- zs:=p; // pchar –> string' H+ [9 K- S. L$ D& }, }9 _) _( A
showmessage(s); // 合法语句3 `! k: O4 r2 g# e
showmessage(p); // 合法语句
! S; F) S; k7 V/ L+ ~… …
8 F) B/ [: L3 h8 o5 d2 Bss.free; // 最后还要记着释放ss占用的资源5 x7 Q) ~9 g1 n) _: }4 C3 j9 m, K: ?
end;3 e, H( D7 [# J$ r
  |1 W2 s5 v6 L3 s: a' `" q$ m  p

: P* i$ a, S  }2 f# z5 \
: d- C+ w$ U+ }* D1 y" ~在设计Menu时,常用的ShortCut可从下拉菜单中选取。但我发现可选的ShortCut有些不在列表中,如ESC,Ctrl-Shift-A等。我试着在ShortCut项的右边输入:ESC,竟然成功了。再试Ctrl-Shift-A,这回Delphi自动把它变为Shift-Ctrl-A

TOP

發新話題