打印

delphi 技巧合輯

delphi 技巧合輯

INI文件的操作要点
+ |+ v" E+ l# o  V(1)在interface关键字后的uses子句中加入
' |6 a) e! h! y2 }6 euses …,inifiles;
" ^/ L9 {: _0 Y, v(2)设置变量:var inifile:=TIniFile;
$ ~0 J. M/ W; l) L0 p: [% ?(3)使用前,一定要先做:
4 ]/ r- r% A: C3 qinifile:=TIniFile.Create(inifilename);$ \8 n) {* L+ z+ @7 H
我在这里绕了个弯子,写成
4 ]2 q/ n2 L9 d# finifile.Create(inifilename);/ V+ g, Q1 S$ p4 j# J- S

4 Q  P4 Z3 }" R4 dTShiftState用来检测CTRL,ALT,Shift,以及鼠标按键的状态,9 ~, Y9 T( L! t& e
常常用在键盘或鼠标的事件处理程序之中。
( R/ \" G' T. B; V( a
* b6 w+ J1 J( P$ A+ RDCU文件(编译的库单元)的重用4 t) a* j0 k& ]$ T% E! |3 T+ Z
(1)在interface里的uses子句中引用。如Windows,Dialogs,( Y7 `) J, r: S0 t$ F  g; l( u
等等,要求被引用的DCU一定要放在Delphi 3\Lib子目录中。
, T3 ?5 d, U/ t(2)在implementation里的uses子句中引用。如果是自行编写的
+ L. g# X0 w: B) d! ]) _" ADCU文件,应采用这一方式,并将被引用的DCU文件放入当前
2 \9 ^, a9 V+ b6 F9 v1 e工程所在的子目录中。$ A9 A; M4 D# T! T% ~1 t
executefile函数(在FmxUtils.DCU中定义)不能用在FormCreate
) S& a3 y: q  R! F& b事件中。真奇怪……
: o/ p) S' i5 R) [
8 j4 d/ A8 b" D5 b5 z3 L- j! p内置的版本号控制功能
8 p! ?; }7 ?. S, v6 a在Project Options中的VersionInfo项里,有版本信息的定制,
* b9 ]8 n6 X. ^3 U: T包括一个有趣的版本号自动增加功能(Auto-increment build
* Q3 f4 z3 _' ~8 i, enumber),即每Build一次,版本号中的Build Number加1。选中5 {. Y$ U* d' r) z4 g, n$ r3 o/ J
Include version information in project,编译,用资源管) Y5 U  T9 u8 p0 L: W8 E" E8 b
理器里找到生成的.exe文件,点右键,查看“属性”一项,就
$ T; h. q4 z; n会看到在属性中多了一页“版本”,里面就是你刚才输入的各
  t  w4 A1 M. l7 X8 j. S+ N项内容。0 N( @3 ]9 n( K, B

/ @+ D/ _2 T' k- W5 i, l- j
% X9 O  y$ _, r& p) K定制Speedbar
6 L- m* Z6 X8 j( O. w右键点击左上角的加速键条(speedbar),选中Properties,' K- J! v6 G; U0 U, B3 A, B
在列表框中找到你想要加入speedbar的命令按钮,将它拖到8 ^6 X3 t4 _8 Q. K
speedbar上的合适位置即可。如果speedbar上没有多余的空间, E9 y8 j; J6 s+ H, ]3 @
来容纳新的按钮,可把鼠标在speedbar右框处变为双向箭头的
  K  G( J( p6 Y# F) M& B形状,向右拖动一段距离,就可腾出空间。如想删除speedbar
  t$ h8 H+ r+ `! O: r* ]$ f- m8 o上的某个按钮,可简单地把它拖出speedbar的范围,就能删除。
0 c3 ^$ G% X; N/ x6 V
6 u. [( C6 C# O6 }9 T( T& y3 O, s% N/ j2 }7 ^1 n( d: D: J1 ?3 r
计算出的字段4 W0 v4 f1 ^/ i% X
在写一个程序时,我要在DBGrid中显示出一个memo的部分信息,当我把那个
" g1 ]5 @5 p! [0 qmemo字段放进去后,运行时只能显示出“(memo)”字样。从书上找到计算字
: g) S5 |, ^. ?  c, ?段的用法后,我在TTable中增加一个计算字段MemoHeader,宽度为40,在此! P" L. {4 z7 {2 j
TTable的OnCalcFields事件中输入:( n+ n( ~' ]( G& h' d/ ]) `  e
with MyTable do
( I, B0 G- \8 T* z4 iFieldByName(‘memoheader’).asstring:=FieldByName(‘memo’).asstring;
% H# _& U- A. L. ^- H在DBGrid中放入MemoHeader,运行,OK!! \4 E( Z9 {  e3 x9 ^
' H5 E0 {& N7 l( T+ f" a

' Y. r2 k% Z+ }+ u字段编辑器
( B  f5 i; r" E7 i0 G- z" ~" p解决了上面的问题后,我继续学习字段编辑器的作用。原来,DELPHI通过字* y2 Z( y# O5 R5 Q2 g
段编辑器,近乎完美地实现了数据库的字段级的控制,这包括:$ K: ?0 A1 R( n' ^
1)字段在DBGrid中标题、宽度、能否可见;
- A+ t2 B5 _; J/ P, W" D2)字段的显示格式和编辑时输入的过滤条件;# G' {/ V2 m# h' F/ D4 `) C
3)字段是否只读;
$ {. v4 U- M( j! @; F4)字段的类型:数据字段/计算字段/查询字段/内部计算字段;& H: c" |/ @* k) I: d2 r5 f/ r, @- N
5)字段的显示/赋值/修改等事件的定制。2 j9 Z! Z2 k8 y  T  w8 h
) k) B( l: l8 p$ n9 h7 w, z
$ M) b( x) x3 w. F
设计Form时的快捷键
6 m5 C$ o' N! C# h. S8 lDel 删除所选组件
" i: _; V; x+ o) ?7 e" Q! c2 vEsc 选择当前组件的容器(通常是Panel,Group或Form)/ @( ]% G) v. v- _8 k& M; F% c
F11 在Form或Unit和对象检查器之间切换
% g8 y: R- c7 \# P; W6 S. \" bF12 在Form和代码编辑器间切换
' _9 D, s' U$ A. v" Z+ hCtrl-F12 显示“查看Unit”对话框
' `" p: G5 r! a3 M$ ^Shift-F12 显示“查看Form”对话框' t3 l5 B5 f4 h  n2 W" G
TAB 下一个组件( B: R8 t& n' p6 n
Shift-TAB 上一个组件
  n1 }& f3 o; [2 g; W1 i方向键 选中此方向上最近的组件: V, B: ^2 ~9 L1 H. _
Ctrl-方向键 将所选组件移动一个点; Q( ?& B7 M4 F% P
Shift-方向键 将所选组件改变一个点的大小
# @- C; T0 z5 `Ctrl-Shift-方向键 将所选组件移动一个格  p& o, N5 r. i  K
Shift-click 按住Shift键再用鼠标点击组件,可以选择多个组件。" i$ Y$ q+ E/ O4 A+ h/ Q' V" J. ?
–= 下面这条是我摸索出来的 =–( a; G; |- D; K8 b. R
Ctrl-drag 按住Ctrl键在一个容器组件(如Panel,QReport,Groupbox等)
0 e$ u  ~& O+ R5 q- L: D' W4 G里拖动鼠标,可强制选择鼠标拖过的矩形框中的所有属于此容1 ~% B4 ^% r2 z, W- T
器的可视组件但不包括该容器组件。
# J6 ?  a0 N. ^8 L& J& D9 R, k9 C" i( ^2 Q8 u
0 D9 g2 m% A' ~7 v* J8 v
使用QReport的若干经验
) G5 q8 h9 q. q. U% ~1)QuickRep1.DataSet:=query1
, w& ~, n2 m- l' f不然无输出结果
- Q' q% O* y) i' b2)从qrpt2man.doc中查知,格式化输出结果的方法是:1 |4 p: B; n% A5 D  J
在QRDBText.Mask中设为.00;0,将使输出带两位小数。' V  h0 X4 u" O# a. ^
3)设置Group时,先加入一个QGroup,再加入一个QRBand,将QGroup的
" }9 P% l2 x% QFooterBand设为刚才的QRBand,就可将其联系起来。+ s8 q; R' a% Q1 z* p
4)在Group中打印的合计数,其ResetAfterPrint设为True,可实现分组合
' g* {8 H' ]/ N- Q/ Y. q7 }9 Q' n1 n- Z
format(‘%*.*f’,[8,2,123.456]); //等价于format(‘%*8.2f’,[123.456])$ U+ H2 _9 S/ f
format(‘%d %d %0:d %d’[10,20]);4 D: r3 k, N7 N) c3 Y% X

8 J. f( V- b! f$ o+ r% n" c3 k9 C0 w4 F& V. `! t
2 r( ~' y0 F: {0 y* R8 l% e1 K$ F
播放一个wav文件) l/ }8 B4 ], T" O) p0 l& d+ X
use mmsystem;
" G3 L4 L% i& j1 c3 K) n4 n4 V( x+ n. hSndPlaySound(‘hello.wav’,SND_FILENAME or SND_SYNC)
9 ~+ u/ c  i5 X% j# G; K* ^+ y0 K
; k! I2 E) b. L# O! T使你的form适应不同的显示分辨率7 R. C( r( L8 v* B* ~# P- t0 X
假设你在800*600的分辨率下设计的form,第一步:
6 X, C, j2 v) z7 |inplementation
) R& |7 W4 k) ~! s/ Q7 \; R! }const" V* f" o# o. ]' i9 H
ScreenWidth: LongInt = 800; {I designed my form in 800×600 mode.}
6 w3 ?. w1 W! k. zScreenHeight: LongInt = 600;9 L# U7 `* Z6 `1 c) I* ^$ p
2 I5 {) [+ X& l' w) u+ x, i
{$R *.DFM}( Q. {. F* z6 Z( N# q: G- o6 U3 ?6 i

' K& \' k1 R( R. Y* _3 H: Oprocedure TForm1.FormCreate(Sender: TObject);
& O# k1 A( p) Z- _5 Lbegin
( B, r) N7 h( T! ]6 dscaled := true;
# W( U! ?( M3 t7 l% Y' J; z. @if (screen.width <> ScreenWidth) then
# J2 L) b6 _+ Q3 w' Y8 m, abegin* w- Y9 s& T) `
height := longint(height) * longint(screen.height) div ScreenHeight;
# g/ F# c. j* h6 s7 h# z6 [width := longint(width) * longint(screen.width) div ScreenWidth;
! Q+ x& E9 L) X: N7 R8 sscaleBy(screen.width, ScreenWidth);
) H% d) f8 y. E5 L# Pend;
8 x) H! h2 J' x' T/ p5 k3 Wend;2 H* m' m+ n, L( K
1 g2 o9 P1 e: @. F  `2 q6 w
下一步,要让每个子控制的字体改变到合适的大小:8 d5 v. c& J- x- _0 h4 m$ ~
type
0 q/ @! {" P4 LTFooClass = class(TControl); { needed to get at protected }
; {1 n# W2 _7 n: k1 |# P. |{ font property }
& N8 q0 A" R; i0 [" V, _! I% W6 h0 G$ H" R+ ?
var* i  Q* F: z' H. g9 u" ?* G
i: integer;
9 y( f+ |* M8 m7 M7 u) xbegin/ Z: G3 ~2 ?/ B0 t; f
for i := ControlCount – 1 downto 0 do* h" h7 \% j2 E5 m4 l" |% ?
TFooClass(Controls).Font.Size :=6 W2 f& s$ _, P
(NewFormWidth div OldFormWidth) *
* k+ g8 p3 c, o) M* eTFooClass(Controls).Font.Size;; w- J% H5 R5 t1 D: M3 p. |
end;
0 F" E3 s$ e/ D6 I) W' _# q. K/ K, S( E8 G; C$ W
用raise引发一个错误处理例程" z/ m/ ]8 W9 Y+ T
示例:先给出下面的定义
0 S# U3 _5 V8 D7 O5 [1 C! S0 atype EPasswordInvalid=class(Exception);
) i! |( y- O  Z' J; t2 P. S' ?9 B这样你就可以随时引发一个”password invalid”的例外:; O2 p* V' a  c' e% u( i
if Password<>CorrectPassword then$ w" o1 r+ N4 z8 p( K& z
raise EPasswordInvalid.Create(‘Increect Password entered’);
* n( m6 [( I8 ~9 W" ?5 X运行后,出现信息框
: w) Z( R8 l& i: j$ Z( i! \# CProject Project1.exe raise exception class EPasswordInvalid1 v9 `# v; n5 D% z% E
with message ‘Incorrect Password entered’. Process stopped.* s/ |$ y. j$ w/ C
Use step or run to continue.
( l- i0 ]2 t( K( o2 {$ @# L再按Run按钮,出现一个信息框:
! N% `0 z3 _0 }  m: |3 V8 M! ?Incorrect Password entered.7 y# h& C9 Q5 b3 t; a- y

% [/ m$ N/ v- f! `& a* k* d$ ]: ^) i" ?) q/ {9 f
从DEMO例程中学到的若干小技巧% A) {8 s$ T0 D/ E. t
在demo\internet\http\webbrows\main.pas中,! n0 L( C! J; W/ F( O
procedure TForm1.DocumentSourceClick(Sender:Tobject);5 y8 Z; h2 q/ t: q) @
begin, y$ k' z; D/ e. n! o' y$ l) I, c4 J& E
with DocSourceForm do
% U9 e' |: l6 Vbegin
5 ]) u7 n+ w( g! i) pshow; // 显示HTML源码的FORM7 y* z  l) {% b; Q9 m
Memo1.lines.clear; // 清空memo1中内容
2 P1 Q0 @; v* f! P' l4 DMemo1.lines.add(HTML1.SourceText); // 植入源码
  p3 u- h1 n2 d% w+ oMemo1.SelStart:=0 // ***: `4 e6 e1 C: m! e, x3 s# h
SendMessage(Memo1.Handle, // Memo1的窗口句柄+ Y. y0 K! z0 L( {; H$ b
EM_ScrollCaret //将Edit Control中的caret光标滚动到视野中/ r* }1 D; u. _  `" U
0,0 //这两个参数暂不使用
7 D- X# a: R& `end;. h' \2 U2 P' m9 F
end;
$ c- a  [5 a" n$ y3 x(此SendMessage系一WinAPI调用,给一个或一组窗口发送消息,直到- L* E5 X3 E3 ~0 q& Q( ~% W
相应窗口处理此消息后才有返回值。相似的另一函数为PostMessage,
" b8 q$ j5 {, c  R+ I它将消息放入消息队列中后立即返回。)5 B% g; W( W2 A& S3 ]
*** 清空当前选择并将光标移动到指定字符(0代表第一个字符)。如同时+ y6 W( g/ ~4 C( b
设memo1.sellength为一非0值,可选择一段文本。; T- l7 R  x1 p8 X% S/ a
5 g: O# x1 ?' k! Q

/ H' _7 d6 x9 J/ ?% P2 _奇怪的I/O error — 我在开发过程中发现下面这两条语句
3 s3 P2 o5 u" q- qassignfile(fDesc,CDDatadir+describefile);
: ?8 p/ q7 Q0 w+ G/ J) zreset(fDesc);
; n4 v4 t, r' w每当我第一次运行到这里时,总会出现 I/O Error 183 的错误.2 B- u: F) y. U  O1 S  j3 E
最后我想这也有可能是没有清除 ioresult 的原因.在两句之间加入6 }2 c7 W$ b  B- O6 k
if ioresult<>08 U7 s- }" ^" U- l
then; : H9 a! a% k3 {  n
oooook! 可以了.
/ G$ Q% a% X/ g: s" Q' K  D7 G! z7 s3 B6 C

% O9 `9 _) t4 o- A: w% e值得注意的I/O error
; o9 f7 m4 K4 ^$ }  v' l, VAssignFile(F, fname);
+ E, O- h' {# q, SRewrite(F);
( V7 ^/ g0 m& L2 e当文件 F 经 Reset(F)打开的情况下, Rewrite(F)会引发一个异常: I/O error 326 u% [. r: M# X
反之,经 Rewrite(F)打开, Reset(F)也会引发同一个异常.
1 ~! U4 g7 ?3 T# W7 m1 CReset(F)两次,closefile(F),再Rewrite(F),或反之,也会引发同样异常.
1 _' _0 g, m$ ?: i9 z4 l" o, F9 @/ x) T) a$ |- a% S

  Y8 \  T7 m3 g( G6 a
- X" T, r, r2 N% R$ \string和pchar的相互转换:" u3 ?/ f& V* U4 n
string –> pchar: pchar(s
" R/ Z, w. ^) I% Y, U6 L& z8 V8 Atr:string);
9 U# Z' o. G! a8 A" Jpchar –> string: strpas(p:pchar);
" b+ V$ U% q$ e3 ?
& w) _4 d' j2 V: t( E/ L, u. I" C8 D2 d, |+ I

* e6 K  J/ L* e; C; N9 F在Delphi代码中定义数据库/ p2 O4 b! U9 e$ [3 x
procedure tform1.create_tbl;3 r) K. `. s8 h4 e8 x( d8 ]9 J
var tbl:ttable;( M8 W+ l! {2 p) n
begin
( G& {- O+ g& G3 f5 ^; y4 x% Ytbl:=ttable.create(self); // 如没有声明中的”tform1.”,Delphi不认这个self
: h$ D3 M7 w7 b( z1 ?, ]with tbl do
2 V" E1 \/ U, w! tbegin+ J1 x) o' S! y* r
datebasename:=;dbdemos’;
5 S! [% x7 X% @- ptablename:=’my_tbl’;
6 d) {7 U+ t% j( \8 A' _with fielddefs do
. y0 I& E1 r- M3 n0 ebegin% T1 x0 u  e# o
clear;0 D6 s. I3 F! z5 g
add(‘No’,ftInteger,0,false);( A0 C6 O6 n0 s2 k( o7 a  K
add(‘Name’,ftString,0,false);) l% M' c1 x* ]- \/ U! O; \# y3 R
…
2 Y. Y8 B, ]+ q! q- yend;% {$ c7 \' u$ L8 \( B1 [" j
with indexdefs do
) G) N) f0 N8 g2 Kbegin5 q5 Y) X. R. }1 A: F2 f
clear;
% l* ~2 [3 `; h& a8 badd(‘primary’,'no’,[ixPrimary,ixUnique]);5 {0 W1 d# |$ L3 @- M' e
…
; t# y# {' d# o8 U/ Iend;
; g8 u$ ?4 h1 \' a9 Y$ x6 oCreateTable;
9 o' W& C! j; b7 A5 K. s% R) jend;
) W! r$ n, \# fend;2 c- X+ \7 X/ |
2 j. N% P8 R+ T- M. u, c; H& C
- Y3 ~' b$ V* ^1 k, y. B. @" b
string、TStrings、pchar的相互转换(这里是我的个人经验)2 l) ~: R& ]5 @" E+ `/ g2 K: F$ Y
假设有如下定义:  E8 P8 E9 A  r+ K8 P+ x0 }% L# R
var
5 K* _# k# X7 \% D3 H, k% R" Np:pchar;; T* D6 `+ x6 X; x3 B. W
s:string;6 R3 [: f1 |9 m  s5 E
ss:tstrings;
9 c. k# z0 \3 M; ~: [' lbegin
& J3 k9 V- r/ |  |ss:=tstringlist.create; // 开始时一定不要忘记创建ss) S2 ]! Z' Q1 I) [) A
ss.text:=s; // string –> tstrings
+ T% a+ W( R6 y5 Bs:=ss.text; // tstrings –> string
' c9 R5 r6 |0 N* {. J: Ip:=pchar(s); // string –> pchar2 c  e8 q9 j* F" W# L0 G
s:=p; // pchar –> string
  A& S0 ^8 g& n( \! \showmessage(s); // 合法语句
5 c& i$ ~9 |6 u$ E5 a  vshowmessage(p); // 合法语句
! I! r. V1 z' i+ N, M… …
/ O+ A5 d9 }: ]2 `, zss.free; // 最后还要记着释放ss占用的资源/ I0 _: M) u5 f
end;
3 s; ?8 C' b5 W, h! r
4 o' Y8 r+ m5 p; ^! R$ g  u5 t8 J" }$ G% S) r9 |2 [' [9 Z$ x

7 P1 M! p* Q6 x; V- N; k4 V在设计Menu时,常用的ShortCut可从下拉菜单中选取。但我发现可选的ShortCut有些不在列表中,如ESC,Ctrl-Shift-A等。我试着在ShortCut项的右边输入:ESC,竟然成功了。再试Ctrl-Shift-A,这回Delphi自动把它变为Shift-Ctrl-A

TOP

發新話題