打印

delphi 技巧合輯

delphi 技巧合輯

INI文件的操作要点
+ n1 p3 o  I2 P/ t+ K; r; N8 e(1)在interface关键字后的uses子句中加入
* L( C. W; q9 {% }/ g* ~uses …,inifiles;" m* D0 ]+ N/ k9 A% ?, H1 e) c
(2)设置变量:var inifile:=TIniFile;
, n2 G6 U" m1 A9 w/ ]5 s; A(3)使用前,一定要先做:$ g. I  {$ y7 N6 ^3 W9 z: O
inifile:=TIniFile.Create(inifilename);
2 @9 S- n1 J2 h. ^& x5 J: L我在这里绕了个弯子,写成
, j1 k3 x9 ~0 ?0 P/ Z8 Ginifile.Create(inifilename);
: l' A: K, f& Z* q: R. I2 w8 d2 {# ~2 Q* ]& o
TShiftState用来检测CTRL,ALT,Shift,以及鼠标按键的状态,
! V& y# n5 D: [, R常常用在键盘或鼠标的事件处理程序之中。8 [. r- f/ E, `6 C+ Q
0 b) S, L% T) e" |  o
DCU文件(编译的库单元)的重用
- f4 v$ r0 T' @: n) J' [(1)在interface里的uses子句中引用。如Windows,Dialogs,+ P6 |* N: V% ^  t9 a, [5 S4 v5 b
等等,要求被引用的DCU一定要放在Delphi 3\Lib子目录中。" F' ^( o5 [+ T7 A
(2)在implementation里的uses子句中引用。如果是自行编写的
/ H1 k; b+ ?% Z3 WDCU文件,应采用这一方式,并将被引用的DCU文件放入当前
# ~8 b" v9 t7 ~! E  `: A工程所在的子目录中。0 J6 R: h2 e# b: F. L3 E  o
executefile函数(在FmxUtils.DCU中定义)不能用在FormCreate+ L# ]8 _! L% i2 |6 Q" \3 a
事件中。真奇怪……
# p1 w8 R4 w7 C' h
0 a- v4 C; w4 F3 O内置的版本号控制功能
  b% n6 k% {4 S$ ]* r; I1 P在Project Options中的VersionInfo项里,有版本信息的定制,0 [  y- |( U$ c" L' D7 u! A# X
包括一个有趣的版本号自动增加功能(Auto-increment build
0 ?2 E* ~# Z# Qnumber),即每Build一次,版本号中的Build Number加1。选中" _& M! k. z1 ^* h. N
Include version information in project,编译,用资源管/ M8 E8 O& G3 T' p
理器里找到生成的.exe文件,点右键,查看“属性”一项,就
- v9 f9 ^* l! m, J& H& ~会看到在属性中多了一页“版本”,里面就是你刚才输入的各% A8 \5 l5 j7 C# _& a) _
项内容。
! C' i# r' H2 K7 x3 J- h
' e, C, v/ w( k. h# y  ~/ L$ {4 [) B) ?1 |) o
定制Speedbar
! c( {9 z" V/ S. v2 m9 l* s/ d+ U$ t右键点击左上角的加速键条(speedbar),选中Properties,
6 i2 q# b; _% S9 U* ^在列表框中找到你想要加入speedbar的命令按钮,将它拖到
3 |+ D. X/ p! ~0 W1 uspeedbar上的合适位置即可。如果speedbar上没有多余的空间( P* `- T) w1 S& m: C* X
来容纳新的按钮,可把鼠标在speedbar右框处变为双向箭头的( J. S- y6 |: `; e
形状,向右拖动一段距离,就可腾出空间。如想删除speedbar% g9 Q- L* b  a$ k4 A- s
上的某个按钮,可简单地把它拖出speedbar的范围,就能删除。
6 p$ R: ]/ C4 A6 V4 `; V1 l4 ]3 i4 q' d: B4 X

- a9 Y, g8 B6 K  P2 Q& R计算出的字段
: A; H2 H) o' V/ C% l, h1 A+ }在写一个程序时,我要在DBGrid中显示出一个memo的部分信息,当我把那个. m5 q6 g, P6 U2 R$ y2 C
memo字段放进去后,运行时只能显示出“(memo)”字样。从书上找到计算字( `! E; h( T7 i' w
段的用法后,我在TTable中增加一个计算字段MemoHeader,宽度为40,在此
+ s  p+ t# B4 QTTable的OnCalcFields事件中输入:
- e+ |# L  N9 _8 ^5 f( V" f8 Uwith MyTable do8 V# P/ ]- {3 M" m5 S
FieldByName(‘memoheader’).asstring:=FieldByName(‘memo’).asstring;
, e9 `4 B3 K8 W+ l2 j0 j在DBGrid中放入MemoHeader,运行,OK!
; j3 S3 o' O' _% ^
5 b" P( M! R; O* W2 s
4 V+ \* \) E# y( ~% _' U& L字段编辑器
. `$ W) R# n: i& z+ `解决了上面的问题后,我继续学习字段编辑器的作用。原来,DELPHI通过字. r3 B( f% \' X/ s8 y2 g
段编辑器,近乎完美地实现了数据库的字段级的控制,这包括:8 y& C: r; o6 E+ V
1)字段在DBGrid中标题、宽度、能否可见;
- x6 F" |' p# S. V$ |6 B. D2)字段的显示格式和编辑时输入的过滤条件;
! H1 ~1 x7 ]6 l5 R  K3)字段是否只读;$ B. E- l" Q3 m( f, F) k9 l
4)字段的类型:数据字段/计算字段/查询字段/内部计算字段;0 W* l$ |# B) F; H  _/ x2 C0 Q8 E. q
5)字段的显示/赋值/修改等事件的定制。3 J! |9 f, ^+ x

" \- t( Z$ s1 ^$ C, }/ E( Z% g* J* |% [9 q2 q
设计Form时的快捷键$ C+ x$ c: Z5 H6 s
Del 删除所选组件  O: @, v9 D8 J: T2 A
Esc 选择当前组件的容器(通常是Panel,Group或Form)
' ?- ^5 e) [& IF11 在Form或Unit和对象检查器之间切换
# c/ ]) c! O/ oF12 在Form和代码编辑器间切换
# |3 U, U5 p0 I) l$ Q! ?4 Y; }Ctrl-F12 显示“查看Unit”对话框
1 j8 J6 @1 B8 A1 jShift-F12 显示“查看Form”对话框
1 s( J7 U) w' {TAB 下一个组件
; I- j) @: U9 }; q: `8 _Shift-TAB 上一个组件
9 R5 Y( r4 q" p0 h! `方向键 选中此方向上最近的组件! m& m8 ^8 o, v5 B# r
Ctrl-方向键 将所选组件移动一个点, X3 X$ n2 O$ Q1 h0 l& u
Shift-方向键 将所选组件改变一个点的大小
. w* ]: B" M/ l$ K; tCtrl-Shift-方向键 将所选组件移动一个格4 _# q! s3 K9 e' I0 R
Shift-click 按住Shift键再用鼠标点击组件,可以选择多个组件。
0 h4 m1 }7 p" x. l/ l+ F–= 下面这条是我摸索出来的 =–
5 w0 G" ~+ H, m' |' ]. KCtrl-drag 按住Ctrl键在一个容器组件(如Panel,QReport,Groupbox等)) S- I1 ^6 P" l" J$ P
里拖动鼠标,可强制选择鼠标拖过的矩形框中的所有属于此容" d7 }1 Z5 ?0 ^( I9 ~$ F
器的可视组件但不包括该容器组件。, ^: q% \3 M6 H9 B
) `  b# l& ~0 B- n

2 H  Z" g- r6 F使用QReport的若干经验. c5 Y9 I# F/ b* N$ V, K7 L2 k
1)QuickRep1.DataSet:=query1
5 x8 j# C" \+ I  F: t- g+ B不然无输出结果2 D9 \0 F4 r, i9 C$ I9 i
2)从qrpt2man.doc中查知,格式化输出结果的方法是:
3 N) O: u6 b0 c* L+ o在QRDBText.Mask中设为.00;0,将使输出带两位小数。
3 ?( }5 R& t9 y" d! }; i% t3)设置Group时,先加入一个QGroup,再加入一个QRBand,将QGroup的
/ B  E- C# L$ `5 l% b0 B! IFooterBand设为刚才的QRBand,就可将其联系起来。
6 U, X5 `! k. i- p. j2 O4)在Group中打印的合计数,其ResetAfterPrint设为True,可实现分组合- i. b' ?# j& t4 a  h# |9 X

9 n) t  B7 Y$ j) @! G3 q- Mformat(‘%*.*f’,[8,2,123.456]); //等价于format(‘%*8.2f’,[123.456])# t' z* k- u  _2 I
format(‘%d %d %0:d %d’[10,20]);
$ k5 q9 m# K3 H  t  m  _2 c3 t: U! H

3 |! U5 m3 m, g, ~3 ^
2 x/ T6 X( a) u; f7 R播放一个wav文件
/ U& P4 t) ~4 X( Ause mmsystem;
! r  j7 X6 Y. U! qSndPlaySound(‘hello.wav’,SND_FILENAME or SND_SYNC)4 H, D$ b; O: m' i  Y& ^3 X$ q

# J6 [# p3 N( D: m& j3 A使你的form适应不同的显示分辨率5 B$ I1 f8 L  }$ Y- i. A
假设你在800*600的分辨率下设计的form,第一步:0 j6 H6 Y1 y, K  K( _! }6 ~5 Y
inplementation
4 v; \% @1 O5 E2 Mconst
5 v: t; ^- w$ AScreenWidth: LongInt = 800; {I designed my form in 800×600 mode.}, K& k, R2 V( z
ScreenHeight: LongInt = 600;1 v1 G" R9 D  m+ v2 _% e+ [
; k3 J5 c, S* ~! S
{$R *.DFM}& g; l' i8 N, S

: ^$ Y9 ^6 {- @( g3 `( lprocedure TForm1.FormCreate(Sender: TObject);
! T$ T" l/ n+ u$ S* U0 M  r; I6 }begin
) h! D) m$ ~; a  Gscaled := true;8 x8 g, c" A( A4 k
if (screen.width <> ScreenWidth) then9 s6 F  B, P: F
begin. M  N" u1 Y' M: Z4 P( F
height := longint(height) * longint(screen.height) div ScreenHeight;
" ?- k% \# S2 q- o0 nwidth := longint(width) * longint(screen.width) div ScreenWidth;  O. w; F# _% _1 t3 n
scaleBy(screen.width, ScreenWidth);
; |( V, W4 ^: T2 ^# b  r, aend;
3 Q1 k' s( I) S' z- Bend;: v! ~3 K( z) I1 z: X
9 i- M6 a6 r* V) I" @
下一步,要让每个子控制的字体改变到合适的大小:
" F& p( w! |2 Ytype, q" m# @5 Z# }3 o3 z9 ?' d
TFooClass = class(TControl); { needed to get at protected }
/ b  }( I8 j4 e$ t+ z{ font property }9 k9 O% W$ r$ c5 G: M- X

' w7 a. B9 B2 E& i5 w) Kvar
3 l: S1 x7 C( B7 d. q0 K% O6 ni: integer;% U7 w8 M: Y9 G9 f, {
begin: `" s% b+ m& t4 A5 e/ S; x5 v  x
for i := ControlCount – 1 downto 0 do
3 y$ E3 B, y/ d: T4 _% K  z) XTFooClass(Controls).Font.Size :=6 ]- K- @2 [( ]) V6 \
(NewFormWidth div OldFormWidth) *
* _7 o3 h6 L4 F1 g- dTFooClass(Controls).Font.Size;; {; u) r6 B3 k. d" T
end;
, d) q8 ^& I! D  b! \& q" {! f0 |+ Y8 ?; I% c) ?; r, a* J0 X; S
用raise引发一个错误处理例程
% g/ T/ N& A4 O! J7 f: i# v9 q示例:先给出下面的定义' f; _7 B/ ^- _& I# M: d
type EPasswordInvalid=class(Exception);
! h! h3 `$ w' d1 o2 B这样你就可以随时引发一个”password invalid”的例外:
! d) R$ O5 t9 M' rif Password<>CorrectPassword then: j: B" L' |  D
raise EPasswordInvalid.Create(‘Increect Password entered’);
8 q: F$ r% |+ w7 P' c' `: ]运行后,出现信息框
( D1 {! r5 ~  v/ w4 _* v& ^Project Project1.exe raise exception class EPasswordInvalid
" ?2 |, p: A  s+ P/ A/ Ywith message ‘Incorrect Password entered’. Process stopped.
9 w) l/ B! {9 |  C& GUse step or run to continue.6 W6 l  h( H7 G* L0 {
再按Run按钮,出现一个信息框:( x, Y8 @1 i0 _( t3 S3 s! }
Incorrect Password entered.  d8 j/ k# c$ ^; E: b
. k/ k9 A; ]  C+ ?5 [2 a

0 V0 }/ ~4 Y$ l从DEMO例程中学到的若干小技巧7 {0 ]0 x5 m. a. Z; S
在demo\internet\http\webbrows\main.pas中," P( Q) f  E" {$ m
procedure TForm1.DocumentSourceClick(Sender:Tobject);
9 J- D+ N* w. ?9 `/ e' V( Tbegin
! a0 j- n. h0 g! Twith DocSourceForm do3 q: A* b# v+ |8 _$ E
begin
- Z% f& E4 h1 q9 ]6 Z4 R2 Q( Mshow; // 显示HTML源码的FORM8 n* d3 z/ t$ J1 }
Memo1.lines.clear; // 清空memo1中内容# V$ \4 M8 ]. y. D9 Q0 o
Memo1.lines.add(HTML1.SourceText); // 植入源码
% \% M0 W/ s0 r: V( zMemo1.SelStart:=0 // ***8 o* b2 v$ B  M
SendMessage(Memo1.Handle, // Memo1的窗口句柄
! I, ]& k& {& [7 a2 ]EM_ScrollCaret //将Edit Control中的caret光标滚动到视野中
% p/ N" a- z2 v3 r+ e0,0 //这两个参数暂不使用  ?2 i" a1 j; ^+ E- o
end;  z3 Y' G% C  \' p- T" v
end;
6 H3 [  \$ ~+ @" w8 J1 }(此SendMessage系一WinAPI调用,给一个或一组窗口发送消息,直到
8 @. J2 d0 C) B* D* E( Z相应窗口处理此消息后才有返回值。相似的另一函数为PostMessage,
4 d$ q. e, o/ p. k/ e+ e它将消息放入消息队列中后立即返回。)+ d* X! M/ B; v, g. b6 U/ x1 u
*** 清空当前选择并将光标移动到指定字符(0代表第一个字符)。如同时1 k2 v6 M, A: e
设memo1.sellength为一非0值,可选择一段文本。
$ D7 Q" J1 _: T! Q( r; C( n6 Z/ I
) ^; z* ?1 t! L& y! n3 {
7 n' u# s, f9 s9 a. I* e; U$ X7 A. \: s奇怪的I/O error — 我在开发过程中发现下面这两条语句4 f8 ?0 k. G0 J; V& V% a" N6 ~; R! U( e
assignfile(fDesc,CDDatadir+describefile);  z) {0 s7 V* Q' S/ |( X6 I9 L
reset(fDesc);
9 A7 m4 g! `2 H2 s  C, s7 ~每当我第一次运行到这里时,总会出现 I/O Error 183 的错误.
1 M( `6 L- C" f最后我想这也有可能是没有清除 ioresult 的原因.在两句之间加入% D5 K  W2 x' m! v
if ioresult<>0
7 c6 p3 _: z& T7 l+ Wthen;
. ~2 z, X' [( L, Y) k1 roooook! 可以了.
; ?" _8 q! R+ V
# @1 k& a# w/ h5 I2 v0 T, S! _: d1 Z( K# y2 ~) T. J/ |) A
值得注意的I/O error' G' }  M/ \: W/ D' l
AssignFile(F, fname);6 W4 t7 R3 v/ \0 k
Rewrite(F);7 `% X2 S! E$ {' m' f: R: }0 L  q7 k
当文件 F 经 Reset(F)打开的情况下, Rewrite(F)会引发一个异常: I/O error 32" w# n7 Y& c$ K# A6 H
反之,经 Rewrite(F)打开, Reset(F)也会引发同一个异常.. v7 g- {, e9 ]- M5 K1 k+ [( ^
Reset(F)两次,closefile(F),再Rewrite(F),或反之,也会引发同样异常.
0 V. G) q! z7 H2 ~* U) E/ A
( I" s8 A$ H( I5 e0 f- I4 d1 k% W6 j3 n9 {; w/ n* v/ P
% d9 v7 G7 Q2 O
string和pchar的相互转换:/ Z& S: t& d. |2 {; u( n
string –> pchar: pchar(s
; {+ W! N; r- Y; w5 e+ }4 _% Ytr:string);" c/ y1 a! I5 V+ d+ x0 j
pchar –> string: strpas(p:pchar);
* Y$ D: j6 X/ v4 v
- k4 [9 Z" z4 h- q4 d3 q- }
6 y5 [4 e- G, ?, G' G8 [" g( x' x% p/ _5 z* E* N5 b4 s1 H
在Delphi代码中定义数据库
' l$ U$ j, _9 S1 n3 c; rprocedure tform1.create_tbl;/ v0 _7 H/ i+ k. t) J# i
var tbl:ttable;+ u6 p, C! m0 w8 z; q4 P% F) ]
begin
+ U3 g- ?# u; K9 f8 m4 o* Dtbl:=ttable.create(self); // 如没有声明中的”tform1.”,Delphi不认这个self8 D- N# F* H0 ]  p+ S/ p
with tbl do
0 g' m. P! q/ v* m& p5 I! D" Tbegin% u, _5 L$ K( e4 E: O
datebasename:=;dbdemos’;
1 i; L8 k) [. G! V: dtablename:=’my_tbl’;
8 B  C; m0 F& q2 z7 `/ O. A" ?8 Xwith fielddefs do
- O) V  w: j: B8 Bbegin
: y2 a' z: V3 b. o4 l9 j3 cclear;
1 z+ _/ b0 [: Q. ?  `& i7 O" `add(‘No’,ftInteger,0,false);' K, I& M5 A, C/ {
add(‘Name’,ftString,0,false);4 O  {' y- _% K& t
…: j0 e" b: k- L9 J
end;
4 \- \+ v" z2 s0 Hwith indexdefs do
) n2 d/ B( [5 n7 M4 wbegin, N  u& w8 ]) x; z8 T; W
clear;
0 _7 ]! X* e% N9 g0 s! Fadd(‘primary’,'no’,[ixPrimary,ixUnique]);" W( T6 H8 U7 `1 E" T6 @
…
8 \/ X( q, w2 |* m) Hend;
( t. P/ X: Q5 i9 f1 RCreateTable;$ q" R( ~+ F, @+ e
end;: Q, I/ h0 }! j! r7 E
end;3 e5 b# Y' d4 D* b4 E

( @4 {$ i: Z1 Z8 [0 @! a4 d, y- A
  b, [$ ]) x; X$ M0 P; g, rstring、TStrings、pchar的相互转换(这里是我的个人经验)8 d. J0 F+ B  n! S/ o
假设有如下定义:/ e4 ?2 ^( u6 }! ~! a; Q% f4 m
var
! o7 B* }6 J1 ^# x6 r" _7 V, Up:pchar;
3 e* c2 v9 H" |) {s:string;
- z) V% \# W$ \ss:tstrings;
' W6 I2 h9 @- {* m7 d/ c3 \begin, i4 [. Y/ n1 ~  n9 h2 `
ss:=tstringlist.create; // 开始时一定不要忘记创建ss! p, v& ?  Q) {  x
ss.text:=s; // string –> tstrings
# S- @) r6 ?: P5 Ts:=ss.text; // tstrings –> string
+ A( T# H" r9 }: x' @p:=pchar(s); // string –> pchar! o' C/ P6 y6 W
s:=p; // pchar –> string3 U) t" M% M5 f' z8 V: t* M0 u
showmessage(s); // 合法语句
' H* H& t+ X$ G5 D& Jshowmessage(p); // 合法语句
7 f2 S* g2 j9 G( t… …
% P. }/ \0 P  I2 p8 Jss.free; // 最后还要记着释放ss占用的资源
5 s6 _7 H9 I6 i6 n# D- _end;& H' g+ q" j) K2 b

' K) Q" q6 b9 ^! ]7 C/ R; m1 q1 T" P, q, C& Q: U' h7 \
! k+ X- r4 ], B- h1 r
在设计Menu时,常用的ShortCut可从下拉菜单中选取。但我发现可选的ShortCut有些不在列表中,如ESC,Ctrl-Shift-A等。我试着在ShortCut项的右边输入:ESC,竟然成功了。再试Ctrl-Shift-A,这回Delphi自动把它变为Shift-Ctrl-A

TOP

發新話題