打印

delphi 技巧合輯

delphi 技巧合輯

INI文件的操作要点* ^7 F7 W3 c( G" z! C! {- h
(1)在interface关键字后的uses子句中加入3 ?6 [4 Y3 h3 b
uses …,inifiles;8 F0 a; g5 A; x9 ^4 K
(2)设置变量:var inifile:=TIniFile;: K, y4 X: Q' W! {: i
(3)使用前,一定要先做:
. }  C% n# q) u8 l/ ninifile:=TIniFile.Create(inifilename);
$ T" \" Z- b) x1 R/ m8 y我在这里绕了个弯子,写成9 c% f: R" r" c& @5 O$ w4 D
inifile.Create(inifilename);- L2 X3 r& I! M7 w1 l3 ~+ g2 b

8 j5 e8 J, d3 ^, m# m4 v. y; L5 hTShiftState用来检测CTRL,ALT,Shift,以及鼠标按键的状态,% }* n! Z- T2 C% A# Q2 Q! p
常常用在键盘或鼠标的事件处理程序之中。% w7 P/ T& S1 W. m) n

% J: }: f# `; [; w' d2 [DCU文件(编译的库单元)的重用2 T; j. D) K: A. r# [2 P
(1)在interface里的uses子句中引用。如Windows,Dialogs,6 e. f- G: `0 T5 R
等等,要求被引用的DCU一定要放在Delphi 3\Lib子目录中。- L( X7 t  o4 n' G0 T9 F4 D
(2)在implementation里的uses子句中引用。如果是自行编写的
  ?1 `- D3 O' d% UDCU文件,应采用这一方式,并将被引用的DCU文件放入当前
; w1 z- X8 i- v/ d工程所在的子目录中。
. m) v" E. E! xexecutefile函数(在FmxUtils.DCU中定义)不能用在FormCreate
( |/ M$ z5 o9 u; B1 @3 M: [* H事件中。真奇怪……
9 o7 r5 L- a+ W+ u; W
1 T8 J  \3 h" E9 d8 V内置的版本号控制功能
# B! E$ {7 P& J( {$ R# b在Project Options中的VersionInfo项里,有版本信息的定制,
  n! @. U; r5 n. a( ?6 M包括一个有趣的版本号自动增加功能(Auto-increment build* Q/ U% X4 L8 `& P0 H1 {& w
number),即每Build一次,版本号中的Build Number加1。选中
) n2 w( A, n4 fInclude version information in project,编译,用资源管$ L5 H2 u$ {, h: b& X: [7 v: f
理器里找到生成的.exe文件,点右键,查看“属性”一项,就+ E; ]. b7 v3 @5 H
会看到在属性中多了一页“版本”,里面就是你刚才输入的各
. m( F4 R0 u8 r, E* q2 r1 v2 b: r" o项内容。, g/ i. H+ D! S6 K, q) n0 t

- [, W5 j6 j# E) V5 z6 U) E
2 M5 a/ P: b9 V& B2 J2 \# Y* q7 r定制Speedbar* w6 q& q) T( t+ b$ [$ v% z% ~
右键点击左上角的加速键条(speedbar),选中Properties,- ~1 u* N0 w& m, Y
在列表框中找到你想要加入speedbar的命令按钮,将它拖到6 }+ q# h) h) w( _& b- m, i1 q
speedbar上的合适位置即可。如果speedbar上没有多余的空间
. J) m; V* }' m来容纳新的按钮,可把鼠标在speedbar右框处变为双向箭头的( n: D" h* k- Y0 D1 F; k3 Y' |
形状,向右拖动一段距离,就可腾出空间。如想删除speedbar& e2 e2 y' V2 r* `; }& Z
上的某个按钮,可简单地把它拖出speedbar的范围,就能删除。$ @: f- L" |0 ?6 R8 {

7 p- l1 R& [& Y1 r/ k  O- u+ C4 s  a/ Y  H) {. y+ Y1 e8 ~! \
计算出的字段
$ R  c+ S7 F: k; E在写一个程序时,我要在DBGrid中显示出一个memo的部分信息,当我把那个7 w4 [. e3 R. w( l/ i
memo字段放进去后,运行时只能显示出“(memo)”字样。从书上找到计算字
9 N, H+ F8 R& e( e- @段的用法后,我在TTable中增加一个计算字段MemoHeader,宽度为40,在此5 e: ]7 n) D9 p
TTable的OnCalcFields事件中输入:
' F7 O8 W3 {5 m3 {with MyTable do
' ^! U( q( _9 w! H' P9 CFieldByName(‘memoheader’).asstring:=FieldByName(‘memo’).asstring;
( o1 K, K3 T6 g$ ^# k2 l7 \/ U在DBGrid中放入MemoHeader,运行,OK!/ n  A  i# Y0 a  I
, v5 D  z) X) S: J

( q) ~2 d; x# q% O' q) f字段编辑器
3 m% c5 h: T" O3 n+ ]. j解决了上面的问题后,我继续学习字段编辑器的作用。原来,DELPHI通过字
) F+ a5 s. S6 K. H, P+ T& H段编辑器,近乎完美地实现了数据库的字段级的控制,这包括:3 F# x7 v! Y, E* ^+ ~' D& B  J0 E
1)字段在DBGrid中标题、宽度、能否可见;
9 W3 C7 q# J0 M3 I2)字段的显示格式和编辑时输入的过滤条件;
) D. M1 ^0 J# _+ l3)字段是否只读;
* |) c2 v) L+ [" |4)字段的类型:数据字段/计算字段/查询字段/内部计算字段;
' u2 e) v; |7 O3 ]5)字段的显示/赋值/修改等事件的定制。
9 q7 s3 }) A6 ~* r) s. M6 J+ o* b7 p& ~6 |! q
, H2 X  Z1 I( W0 h  i3 ~
设计Form时的快捷键3 d0 b) I& T  [. ^) ?. N
Del 删除所选组件
& P4 z7 ?: u0 }' j6 Q/ K2 a3 CEsc 选择当前组件的容器(通常是Panel,Group或Form)
7 I7 [4 Z5 l5 W2 QF11 在Form或Unit和对象检查器之间切换; N  V: r- F- T9 q
F12 在Form和代码编辑器间切换
& _5 T7 G. l- ?3 \0 m8 r" NCtrl-F12 显示“查看Unit”对话框  ^! k% @5 A3 R0 w/ P
Shift-F12 显示“查看Form”对话框
' r% f6 c% T3 x; ETAB 下一个组件
/ }: \- Q4 D. z+ ?8 B1 RShift-TAB 上一个组件  O# \: s+ o: F5 x
方向键 选中此方向上最近的组件5 Y7 O# P$ |9 ~8 Y# g
Ctrl-方向键 将所选组件移动一个点
9 L  X% ~8 z8 a3 WShift-方向键 将所选组件改变一个点的大小& s+ m" U* M6 h8 G/ b
Ctrl-Shift-方向键 将所选组件移动一个格
# W$ a- h/ Q: e9 `Shift-click 按住Shift键再用鼠标点击组件,可以选择多个组件。
- e/ z7 K* I6 h7 n; P–= 下面这条是我摸索出来的 =–
: l) p% K+ O6 JCtrl-drag 按住Ctrl键在一个容器组件(如Panel,QReport,Groupbox等)9 k  t6 v# m, n9 E( f% l
里拖动鼠标,可强制选择鼠标拖过的矩形框中的所有属于此容; @* K0 u' [. V9 n5 ?6 R
器的可视组件但不包括该容器组件。; ~% `" ^. Z1 M' I# d6 G& B. U8 q
: s2 O: p6 U% h: A9 L

3 y2 D+ C* ]6 l9 X- l8 n. W2 [$ t使用QReport的若干经验
8 ^+ w- W' E: U8 M+ ?1)QuickRep1.DataSet:=query16 v0 n/ }3 L$ t
不然无输出结果
  I4 s0 X- B; `2)从qrpt2man.doc中查知,格式化输出结果的方法是:
  w  b- W. s  k7 q+ |* Z/ l0 Z在QRDBText.Mask中设为.00;0,将使输出带两位小数。
( ~  A- }6 }. l' P5 Z: I( x. g3)设置Group时,先加入一个QGroup,再加入一个QRBand,将QGroup的' F& }7 V4 G+ y2 c# @# o
FooterBand设为刚才的QRBand,就可将其联系起来。& c; A2 r! U$ M5 ]. D
4)在Group中打印的合计数,其ResetAfterPrint设为True,可实现分组合
6 @& M. P* ~/ I' D9 Y! W* t# o- G& s  _. F  g% M
format(‘%*.*f’,[8,2,123.456]); //等价于format(‘%*8.2f’,[123.456])# ^9 M+ J( P( @& @
format(‘%d %d %0:d %d’[10,20]);
. n4 _$ J9 D7 C0 H$ J' p$ n5 |; C: ^+ T0 w* f
4 @  ]" h' a3 b" o

: [/ a. |) n: M! G播放一个wav文件
; b1 H. R/ W7 O& i9 c0 G/ ^7 euse mmsystem;6 g4 p) h+ w  A/ m
SndPlaySound(‘hello.wav’,SND_FILENAME or SND_SYNC)
  \& t# @" a5 E: d: K7 C, r( F& ]- o& V
使你的form适应不同的显示分辨率
3 x5 r. N% t0 M1 M* A2 a9 W假设你在800*600的分辨率下设计的form,第一步:
( Y+ P( A3 F0 {8 F/ Xinplementation
' P  d% ~2 W1 @const0 s# _! {- G) i; M+ q
ScreenWidth: LongInt = 800; {I designed my form in 800×600 mode.}% U7 @  N; F1 o
ScreenHeight: LongInt = 600;1 I( N- n& h/ A+ k, e! b

, l9 i; m0 m9 P* N7 s' j! f; P{$R *.DFM}  Z! I5 A3 R# u
0 c4 h$ o/ [) N6 ?
procedure TForm1.FormCreate(Sender: TObject);
! P6 W5 h$ O  p/ ]; Obegin; L" U5 P' {, h( _2 P0 l
scaled := true;
% a2 o! G( [3 f& Z2 Zif (screen.width <> ScreenWidth) then7 E. L( V& T, E  u6 h$ x( _
begin
( Z6 V# t0 r4 I9 pheight := longint(height) * longint(screen.height) div ScreenHeight;
% D: t7 L; t* N7 S* Jwidth := longint(width) * longint(screen.width) div ScreenWidth;0 w  }8 P/ A$ j6 i) `) n! X( l
scaleBy(screen.width, ScreenWidth);7 T4 l, D5 @: z9 T/ L/ p+ Z
end;- P8 k$ G. ~- ^  f; ^- Z1 V
end;. N3 b% T; g1 L
' Q' ]7 N. C4 f, c- K! `
下一步,要让每个子控制的字体改变到合适的大小:$ S, P+ {, [9 ?' `5 a7 L3 ?) P' }
type/ y+ ]2 H9 C$ I* s( }: f1 j
TFooClass = class(TControl); { needed to get at protected }
* g. i. Q2 a/ \! _4 O  a  ?" d{ font property }8 _: X6 t5 ~+ W) T! k  l6 f* c
9 A0 X8 B; i; N5 @
var* }3 H1 ~0 O2 \/ q  b: J1 b: m/ |
i: integer;$ ^0 l/ k4 O  p) ^
begin) w0 `8 G, |7 I# A* t+ e
for i := ControlCount – 1 downto 0 do. s# H. V0 G" B( H. x/ Q
TFooClass(Controls).Font.Size :=
3 B( Q1 r9 a4 l/ ~) s(NewFormWidth div OldFormWidth) *5 Z* P0 S2 W4 k2 m( i
TFooClass(Controls).Font.Size;$ [( u" d7 C8 m; r  |& j
end;
, x! d! o2 Z- d+ ?/ q2 Q" C0 m4 h+ C. o$ |6 {
用raise引发一个错误处理例程
. H' |0 H3 `/ L7 Z" K6 x7 A示例:先给出下面的定义
: |0 `* a) a3 W: [6 N/ Z4 ltype EPasswordInvalid=class(Exception);
+ T  C. |$ I9 B0 @, @# @; e这样你就可以随时引发一个”password invalid”的例外:7 o0 j' \! U3 j: F) D. \
if Password<>CorrectPassword then0 ^6 v( q: P6 ?" v% a; x
raise EPasswordInvalid.Create(‘Increect Password entered’);
# {6 Q) p% p+ C2 Q) J, \) p运行后,出现信息框, X8 k- P6 ^& H
Project Project1.exe raise exception class EPasswordInvalid
/ t3 K1 ~  i6 [/ Fwith message ‘Incorrect Password entered’. Process stopped.4 u" i+ ?5 n) t. D3 D8 h
Use step or run to continue.
" p1 {% d# D. F% |( I) {* v: x/ n再按Run按钮,出现一个信息框:
6 ^% y' Z+ o+ T/ WIncorrect Password entered.4 M2 p8 W+ u+ V/ C! a3 X

( ?! q4 {4 W) s1 u) x- r- X1 _, |8 l' q" g
从DEMO例程中学到的若干小技巧
3 T. q' e" c, n( j% a7 r7 u" W$ r在demo\internet\http\webbrows\main.pas中,
3 D: X# m: x0 z: z+ wprocedure TForm1.DocumentSourceClick(Sender:Tobject);/ d5 R" i: Q* \" M$ }. Y# q
begin- u  y. W1 u) S1 v' S% y
with DocSourceForm do# O( D5 S& z! z5 D7 j+ M/ a( Z( Z
begin
/ F" K4 X1 Y  k  \: h2 E' M  Sshow; // 显示HTML源码的FORM
' E. x9 ^+ U/ q2 L) ~+ i  f! ^Memo1.lines.clear; // 清空memo1中内容  ^; F/ l: {3 V' Y& I0 I
Memo1.lines.add(HTML1.SourceText); // 植入源码% e$ d5 k* |+ n5 g/ p+ z
Memo1.SelStart:=0 // ***  Y# C0 X2 ?& u" P% U6 @  l
SendMessage(Memo1.Handle, // Memo1的窗口句柄
% `! w. }, E; H5 c; bEM_ScrollCaret //将Edit Control中的caret光标滚动到视野中8 c7 j. x# }" U- [. w* L
0,0 //这两个参数暂不使用4 v% [/ [1 ^7 \
end;' s+ W6 s8 Y$ e. Q: K
end;
% u/ {* Q# b9 D. ~1 `3 p(此SendMessage系一WinAPI调用,给一个或一组窗口发送消息,直到0 _# T# A; g4 D$ H3 L$ t
相应窗口处理此消息后才有返回值。相似的另一函数为PostMessage,
+ g8 s& `; F- C( q: {它将消息放入消息队列中后立即返回。)# M* a# Z' o% O4 h* C: x* O5 I. N9 C
*** 清空当前选择并将光标移动到指定字符(0代表第一个字符)。如同时6 x8 {! i( j, [6 D; R; m+ a
设memo1.sellength为一非0值,可选择一段文本。4 s/ y4 |$ G+ \3 Y: H# I* g
, O# z+ U! B1 @  o8 G- Z, |: @
, i5 Q1 v2 O1 b% }
奇怪的I/O error — 我在开发过程中发现下面这两条语句
" l# K, k, r  X" T4 u5 {/ ?( V0 x6 S$ Gassignfile(fDesc,CDDatadir+describefile);
% s  l- e: y7 N2 \reset(fDesc); : ?! E+ f$ q9 D
每当我第一次运行到这里时,总会出现 I/O Error 183 的错误.
) x" y' z2 P/ q* k+ E/ j% s最后我想这也有可能是没有清除 ioresult 的原因.在两句之间加入. f9 C( m( t/ @1 n
if ioresult<>0
$ r) z: j" m/ Z* v% N: Lthen; + i5 _) Z2 M1 A5 _. U
oooook! 可以了.% z; i) P: W; ]5 f9 X  c, ?' L

; \" b2 M' i4 o2 A* ~  L* W
% |% a8 ~: I* n7 k7 ^$ J; z. d值得注意的I/O error
% q3 ?9 I2 @' P1 |: R4 ~( KAssignFile(F, fname);
* K$ o5 ?% E1 _" R, \Rewrite(F);6 Y* ]3 D" \1 H! q( O6 e
当文件 F 经 Reset(F)打开的情况下, Rewrite(F)会引发一个异常: I/O error 32
7 Q$ Q; x8 T0 H% A反之,经 Rewrite(F)打开, Reset(F)也会引发同一个异常." u9 A6 t7 N5 J; \4 S' o
Reset(F)两次,closefile(F),再Rewrite(F),或反之,也会引发同样异常.# T$ n( {6 b  |; }7 v' k

$ D! L3 A4 p0 E' n0 b$ o  B- M) e- j* c( W- ?) c6 e2 J) m
; w6 {' o8 Z) ~
string和pchar的相互转换:
1 S4 }  W, [$ `9 H/ Zstring –> pchar: pchar(s
7 I8 C7 V- d4 \4 H0 vtr:string);* M4 F& m9 n. g
pchar –> string: strpas(p:pchar);* G7 ^9 V& L& x! k2 b2 D/ g5 ], l
5 I- T' }, x! E, u: X' Z; d
4 \" x% [1 l2 s& r
  V, r. Q; L5 d
在Delphi代码中定义数据库
7 X" ~7 a& q) }, O% P" J$ D- hprocedure tform1.create_tbl;# n+ S# {0 Z2 P5 J
var tbl:ttable;5 A0 {: f4 W3 J+ k+ T
begin# {- Y& I! C# m  k- g+ ~
tbl:=ttable.create(self); // 如没有声明中的”tform1.”,Delphi不认这个self! Z! D* l  s5 `8 w  ?2 R# v7 b
with tbl do% X2 h0 Y+ }) f9 ?1 v( M7 c1 Z
begin$ y6 S  B$ b0 Z- H5 Z
datebasename:=;dbdemos’;6 K6 l( Q4 a5 _  d& o$ x" X* p: R2 ^
tablename:=’my_tbl’;
- C  H% C1 G; w7 Q( Owith fielddefs do4 K& t2 ?2 T' O: O' e  Q9 }
begin; a# u* ?6 t, `" b& c
clear;
5 n9 W5 }% s8 c6 ~8 wadd(‘No’,ftInteger,0,false);) B, t. k$ ?  f: ]$ ~
add(‘Name’,ftString,0,false);  G! F# }) ]. ~" K7 G% E/ Y

  X: ?' j9 D/ ]; S4 Lend;1 F; R( B1 A- z7 D' k- S% Y, l
with indexdefs do
9 x$ w+ L! c& X3 y* _: ^begin
6 p2 Z' Z! M, T9 q  Aclear;& U: H' r. d  w" N* }
add(‘primary’,'no’,[ixPrimary,ixUnique]);
6 ~6 z  ]0 j3 `& E6 V, M: q
9 ^/ M& J9 \5 Dend;0 s4 T; m% f) Z' X* U4 X) a  U9 d
CreateTable;6 X/ x+ e, Q" \7 N8 ?+ o
end;
- p/ X! `' V7 eend;
. G; S0 n' g' w9 V
; ?* ?& I; R% u# r9 |. l8 \  z7 K$ W! y+ h2 Y
string、TStrings、pchar的相互转换(这里是我的个人经验)2 ^" L" i: T# s( N( u3 D
假设有如下定义:  Z& L6 c2 J) y0 i- {
var! E% |4 u% Y& j7 k
p:pchar;
3 u3 M# O& u/ as:string;9 T4 c4 o- U# A5 M" q
ss:tstrings;
' n  g+ ~3 e1 d) M6 i- h7 J9 w  [. @begin
& ~4 E  o1 d: J8 c8 \: |3 X  Tss:=tstringlist.create; // 开始时一定不要忘记创建ss
4 G6 X8 d( K" K! X- }ss.text:=s; // string –> tstrings+ O/ B! ~# z! X- E5 x, B1 _4 J2 o
s:=ss.text; // tstrings –> string4 ^& b4 i5 Q0 D9 U1 Y
p:=pchar(s); // string –> pchar
8 {$ m2 G9 X: b& f% G, t) Bs:=p; // pchar –> string  n+ g3 f+ l, c7 e
showmessage(s); // 合法语句
% u1 @5 _0 L4 X0 n7 Tshowmessage(p); // 合法语句
: x9 `, e: q6 ?5 m… …
' r' g9 Z: h+ Z- [ss.free; // 最后还要记着释放ss占用的资源# ~6 v9 v1 x2 r2 o! M2 F$ e
end;
* m; w; d9 i  B' P: w1 W
* t4 V. R  o. C- ]/ l$ n: F* E/ j6 M6 E
- d& M; O  U+ q6 ?$ c
在设计Menu时,常用的ShortCut可从下拉菜单中选取。但我发现可选的ShortCut有些不在列表中,如ESC,Ctrl-Shift-A等。我试着在ShortCut项的右边输入:ESC,竟然成功了。再试Ctrl-Shift-A,这回Delphi自动把它变为Shift-Ctrl-A

TOP

發新話題