打印

delphi 技巧合輯

delphi 技巧合輯

INI文件的操作要点
5 i, i  v! ^% s4 ](1)在interface关键字后的uses子句中加入8 |7 [3 c6 o9 w. h! Z: Z, H" v
uses …,inifiles;
' l/ H/ J; q# h  v(2)设置变量:var inifile:=TIniFile;
: i; `  j% O* n$ D" e3 m(3)使用前,一定要先做:
' R3 c" M0 Z5 `2 V7 uinifile:=TIniFile.Create(inifilename);- f- l. Q$ g, q0 W1 i2 n
我在这里绕了个弯子,写成, _% Y* [9 x0 U0 p- T
inifile.Create(inifilename);
' j, Q, N6 z7 K) ?
; K3 \' d  @1 o3 j- a8 dTShiftState用来检测CTRL,ALT,Shift,以及鼠标按键的状态,. _: ^5 p8 f' x5 _* P
常常用在键盘或鼠标的事件处理程序之中。- \/ O7 B4 s% x: E' h

# Z) [; ?% g% |  t7 KDCU文件(编译的库单元)的重用
- N3 A$ ^) J4 Q8 ?' A6 O9 f(1)在interface里的uses子句中引用。如Windows,Dialogs,
, G' x( E7 @% |7 ?( p& c6 G* \等等,要求被引用的DCU一定要放在Delphi 3\Lib子目录中。
5 c3 m5 j# t; g( X" \(2)在implementation里的uses子句中引用。如果是自行编写的
( T# ~$ H  {1 f& |5 }DCU文件,应采用这一方式,并将被引用的DCU文件放入当前6 J1 {, S% K% p0 d# k' A, c2 m$ h
工程所在的子目录中。" A3 Z8 L" [* t1 ?0 v' w
executefile函数(在FmxUtils.DCU中定义)不能用在FormCreate
5 N3 B) ^1 l7 j! k( r+ s9 b事件中。真奇怪……
5 l- \: H+ c( P, f/ g3 k1 N9 ^+ P  _
内置的版本号控制功能! t( P1 \: g% Z9 y
在Project Options中的VersionInfo项里,有版本信息的定制,' C& J; r6 v5 [% |- e3 @4 z& |
包括一个有趣的版本号自动增加功能(Auto-increment build
& c2 F! _) e8 g' e3 _5 d2 onumber),即每Build一次,版本号中的Build Number加1。选中9 d. L5 L' ]+ R, B& F& g- E. W
Include version information in project,编译,用资源管6 D) j! x. X; K  l2 |
理器里找到生成的.exe文件,点右键,查看“属性”一项,就
( q/ E* ]3 z/ p) Z4 G! x会看到在属性中多了一页“版本”,里面就是你刚才输入的各
8 m! X9 y5 _0 W* K项内容。
  F, @2 p+ O) m5 S; u* P3 M7 G( l9 Q

; M& M% O5 A0 h1 l定制Speedbar$ V) l! K8 Y- I% P" J4 R& }; x
右键点击左上角的加速键条(speedbar),选中Properties,
& P: ]0 h7 M& f) d8 N5 f: B在列表框中找到你想要加入speedbar的命令按钮,将它拖到6 a/ ~0 @6 r5 i! B4 a
speedbar上的合适位置即可。如果speedbar上没有多余的空间
3 ]1 l9 |5 n: a来容纳新的按钮,可把鼠标在speedbar右框处变为双向箭头的
" v, U* b% E1 h5 k3 l形状,向右拖动一段距离,就可腾出空间。如想删除speedbar
2 i% j& C; v# ]8 L上的某个按钮,可简单地把它拖出speedbar的范围,就能删除。
+ H$ H7 k) L9 v4 ?* y
2 ^* H9 Z& F9 q/ m$ [9 \9 Z4 }* |8 U% A$ c, l' w0 x7 {; {
计算出的字段3 q9 t, g! P2 N! X% n
在写一个程序时,我要在DBGrid中显示出一个memo的部分信息,当我把那个; I" W2 w1 ]  s
memo字段放进去后,运行时只能显示出“(memo)”字样。从书上找到计算字) X3 Y7 G% z9 ^& Z
段的用法后,我在TTable中增加一个计算字段MemoHeader,宽度为40,在此
  ~* M; w3 X! D1 D( z7 bTTable的OnCalcFields事件中输入:- \5 T7 S5 k: }
with MyTable do
/ l% s- V; c: ^FieldByName(‘memoheader’).asstring:=FieldByName(‘memo’).asstring;
7 T) N. Y! X7 {  Q在DBGrid中放入MemoHeader,运行,OK!0 a8 q  o" }5 s1 ?
7 W. B4 f1 R7 @& Y6 C$ d  C) ~
* Q. N; h# t$ M% U
字段编辑器
7 m, p& t: y3 _" v" I8 A8 M解决了上面的问题后,我继续学习字段编辑器的作用。原来,DELPHI通过字$ e' e8 \/ b$ C4 F. [% v7 J: h% g
段编辑器,近乎完美地实现了数据库的字段级的控制,这包括:' W/ Y" z) b" S( J) j( O
1)字段在DBGrid中标题、宽度、能否可见;
5 f  \6 e, n5 H5 _, U& D2)字段的显示格式和编辑时输入的过滤条件;% k) M: E" ?% j2 V& a
3)字段是否只读;
7 ]: m( K. t) H; Z; t; W% q3 O- G7 @- D4)字段的类型:数据字段/计算字段/查询字段/内部计算字段;
  D5 I  @6 r* Z3 W' S5)字段的显示/赋值/修改等事件的定制。
2 n) S' [) v/ X6 q2 f4 \, W3 X8 P
3 j9 U" p2 N- e* m: N4 g
( {7 Z- M$ T4 d" z9 i. T设计Form时的快捷键2 p% \) O/ j% J% [1 S3 c+ `
Del 删除所选组件* C6 d5 e& ~; h5 b. _& ^7 G, ~' q' N
Esc 选择当前组件的容器(通常是Panel,Group或Form)( b" K/ U* i2 N# a; ]; [
F11 在Form或Unit和对象检查器之间切换: @; y- R% P6 `/ g5 u
F12 在Form和代码编辑器间切换
2 o0 f5 S& [/ p; o( L+ wCtrl-F12 显示“查看Unit”对话框
0 J$ M  {  B" n: E- vShift-F12 显示“查看Form”对话框
3 b1 N# L; M  N. i# ?" {- _0 `# LTAB 下一个组件7 R5 U3 o) p+ O: b7 m" q/ x
Shift-TAB 上一个组件- `! c8 w0 X: i+ T
方向键 选中此方向上最近的组件
0 }* F  }. W* E/ dCtrl-方向键 将所选组件移动一个点, ]2 l* C% D3 ^4 \+ o
Shift-方向键 将所选组件改变一个点的大小
& F& N# ]  i$ e! |7 a  G6 bCtrl-Shift-方向键 将所选组件移动一个格. c; F* C2 C# h5 w0 f* _8 v
Shift-click 按住Shift键再用鼠标点击组件,可以选择多个组件。
: H" q1 Z( o: o; v–= 下面这条是我摸索出来的 =–
* l" H0 G% w& gCtrl-drag 按住Ctrl键在一个容器组件(如Panel,QReport,Groupbox等)
$ @& @% x9 {8 \* l. r: g5 s里拖动鼠标,可强制选择鼠标拖过的矩形框中的所有属于此容
2 V, q( l+ W1 u- s器的可视组件但不包括该容器组件。
& V6 E3 c. m9 V3 D, |8 k+ v& B
/ m9 i  I, n! ?* Y# x" S- U5 p- |/ I+ z2 r4 T
使用QReport的若干经验/ w+ }- |* s0 O$ D- p
1)QuickRep1.DataSet:=query1
1 v/ m% j7 m9 L不然无输出结果
9 f; J9 T4 w' D' s$ N2)从qrpt2man.doc中查知,格式化输出结果的方法是:. q3 _3 ~1 o7 Q4 g5 {" j% y8 p, p
在QRDBText.Mask中设为.00;0,将使输出带两位小数。- v9 ~$ j5 ~! L, u7 f; K6 G; v0 ]) @
3)设置Group时,先加入一个QGroup,再加入一个QRBand,将QGroup的
1 A, g( x/ T, B  }FooterBand设为刚才的QRBand,就可将其联系起来。
3 U3 x) z5 J+ C: \  T6 l, x4)在Group中打印的合计数,其ResetAfterPrint设为True,可实现分组合5 R* ]2 y5 n) _0 x+ l& c
; d8 D# f8 \1 ]
format(‘%*.*f’,[8,2,123.456]); //等价于format(‘%*8.2f’,[123.456])
4 f6 M9 X$ {* X- u5 S5 Qformat(‘%d %d %0:d %d’[10,20]);6 A! P! x1 L% {9 ?

* g2 A+ i4 E; }# m" L. H5 ]' f3 A9 ]8 H

8 z$ i# e- a8 {3 u* b播放一个wav文件
/ ?' S9 P, O& b/ v$ puse mmsystem;0 v# X9 k  L- ?" n0 T
SndPlaySound(‘hello.wav’,SND_FILENAME or SND_SYNC)" b" ^  ~0 \7 a) W  t# X
% n( j! B; U; c; l1 ~
使你的form适应不同的显示分辨率# I: X; o. w# S3 a  s
假设你在800*600的分辨率下设计的form,第一步:
7 j# ^6 y; T' y& N" I; Qinplementation
& w7 V- E2 G1 E6 S' P% ]const
4 D$ J; E, }' W/ q/ Z* X, K, Q4 {ScreenWidth: LongInt = 800; {I designed my form in 800×600 mode.}' h, f$ m8 u; n- k6 @
ScreenHeight: LongInt = 600;$ {4 e! G! t) n2 [' c

+ O. @2 ]. I) P: f# D4 j" F2 J% L$ k{$R *.DFM}
7 }& m/ V/ O2 o# ^& ?) o: n$ q7 w7 r3 i
procedure TForm1.FormCreate(Sender: TObject);. p% b: f; C. ]$ ~. d. y& U. h& P
begin
& S8 Y2 K2 c4 b9 V+ Mscaled := true;& h! Z& S: L  I3 q6 o+ y! F( d
if (screen.width <> ScreenWidth) then$ L  C: K& k( J. W/ m% X, P
begin9 Y, Z+ B3 B% |8 a) I
height := longint(height) * longint(screen.height) div ScreenHeight;( o# O: p3 T5 ]$ T( ~; s/ c
width := longint(width) * longint(screen.width) div ScreenWidth;9 |' i- X* |, W9 d3 W% t* p' Z
scaleBy(screen.width, ScreenWidth);* V! ~( M: I( `5 O
end;
$ C( C3 W1 |4 P  Z+ q6 h; v* Vend;
! Q3 ?- h/ A! g# r, q5 I  S) Y
4 M5 d0 w: p9 M, s" e% z9 O5 M! i下一步,要让每个子控制的字体改变到合适的大小:- ?5 W8 D3 l! v) |
type
* A. N% n( _6 ?: fTFooClass = class(TControl); { needed to get at protected }! `# z) O! o' @
{ font property }' q4 {/ \! V; c
4 F7 @: ~) L1 `) V
var
% @1 b' a* C$ S  d# l; Y) [i: integer;
- P3 Y3 ^% j# n. |( Gbegin0 L1 y. k; v/ p, h2 {1 p3 V
for i := ControlCount – 1 downto 0 do
3 |0 C9 Y3 [- E& KTFooClass(Controls).Font.Size :=
8 ]8 L2 f3 [) {1 ?(NewFormWidth div OldFormWidth) *
  P/ M9 Y6 G" a& z: UTFooClass(Controls).Font.Size;
: p' r/ M: D( f0 v0 [2 t$ kend;; k2 t: S/ V  H% X0 @) A+ k
2 J# [7 J0 p6 F# ~! X
用raise引发一个错误处理例程
* r& R1 E0 M8 Z/ U% F示例:先给出下面的定义
% a  t+ q. b3 A+ dtype EPasswordInvalid=class(Exception);- Z+ P5 H* W) i1 N  G: @! U
这样你就可以随时引发一个”password invalid”的例外:
) w9 F" c' c+ ~' Zif Password<>CorrectPassword then
' I8 ~+ m9 z. Y) J9 [6 C3 xraise EPasswordInvalid.Create(‘Increect Password entered’);6 L, l, v) ^) f5 U* v
运行后,出现信息框  h, V+ r* ^& k, r
Project Project1.exe raise exception class EPasswordInvalid2 `4 S% E  y: q8 [- i
with message ‘Incorrect Password entered’. Process stopped.$ z5 G1 f! S) u0 u- v& E/ t
Use step or run to continue.
4 @# S3 \7 D0 G" y6 n1 r  z/ x再按Run按钮,出现一个信息框:
. O1 k' w* `. Q8 L1 V0 DIncorrect Password entered.+ ]7 x1 i, ], r' J; ]
' m& |& L1 Y# `2 }" a( U
2 K1 b  p, _4 [" j* J( E
从DEMO例程中学到的若干小技巧
) y& \$ V' e  M6 w# I1 R在demo\internet\http\webbrows\main.pas中,
/ S( V5 N4 ]( G( h. {7 o! H0 u. Mprocedure TForm1.DocumentSourceClick(Sender:Tobject);6 e. `  H+ t1 B; n- {/ L
begin  J9 z: D9 x* q* x
with DocSourceForm do
4 T# d/ A3 o4 i/ L  k: P7 _begin
* [+ F: K- \0 P2 k8 w$ g" J+ x/ }show; // 显示HTML源码的FORM
7 o( Z( f; B  F1 O% a) P, bMemo1.lines.clear; // 清空memo1中内容
% L& I  X3 H+ y8 M6 h/ Q  |; q4 t4 VMemo1.lines.add(HTML1.SourceText); // 植入源码
4 C# P, G* i6 `: f5 {Memo1.SelStart:=0 // ***
" T- e( M, d. [$ T0 GSendMessage(Memo1.Handle, // Memo1的窗口句柄
$ F# j1 A& _- B2 R. eEM_ScrollCaret //将Edit Control中的caret光标滚动到视野中
$ v: _1 B8 o; ~  `6 ]0,0 //这两个参数暂不使用. Q2 Q0 T( h, |
end;
6 ^: X+ ^$ n; I& Iend;' C/ t# n" T7 A7 ]% f1 L/ i6 Y3 J  h
(此SendMessage系一WinAPI调用,给一个或一组窗口发送消息,直到
3 V$ V0 E; {# q* |( O0 v4 v, i相应窗口处理此消息后才有返回值。相似的另一函数为PostMessage,& y; k" c( U6 b
它将消息放入消息队列中后立即返回。)
$ q9 d7 S; M+ u  b*** 清空当前选择并将光标移动到指定字符(0代表第一个字符)。如同时$ W8 O5 j/ z# U4 `
设memo1.sellength为一非0值,可选择一段文本。
$ d2 ^0 x# U, u+ e/ P  J: p5 T  M2 g

) v  s# V+ H9 {: {! w奇怪的I/O error — 我在开发过程中发现下面这两条语句5 U4 u! Z. U0 A' Y3 n3 s
assignfile(fDesc,CDDatadir+describefile);
4 F( A  J  g8 C  Y" {reset(fDesc); : i5 Z  Z' g& J7 Z7 x9 y
每当我第一次运行到这里时,总会出现 I/O Error 183 的错误.
' D* w1 L9 O* s% o9 f  M; }+ y最后我想这也有可能是没有清除 ioresult 的原因.在两句之间加入
. E' e  B" f" Y* c& ~  f3 w9 R$ d% \if ioresult<>0% s% c$ ^* \' d8 y, ~+ A
then; 7 `% P- i6 g% Y4 |: G% b8 l
oooook! 可以了.3 F# a3 Q, |2 t/ v( c6 N9 s( ^) w

1 E  W, M1 |; Y+ i9 G0 }* e3 G! O& ~7 k; R
值得注意的I/O error9 }2 B9 c/ S) _1 K
AssignFile(F, fname);$ C  M; y" ~% t/ H9 C6 v
Rewrite(F);3 {* T* p2 l) r
当文件 F 经 Reset(F)打开的情况下, Rewrite(F)会引发一个异常: I/O error 32) |6 l& B9 F) C6 M5 f. T1 t
反之,经 Rewrite(F)打开, Reset(F)也会引发同一个异常.6 N% ?+ l4 Z) Q8 P! M0 A1 k3 C7 W5 W
Reset(F)两次,closefile(F),再Rewrite(F),或反之,也会引发同样异常.& P5 ?7 T% g6 y: i" x+ J# T
( y) S6 m! _, R: C9 H# d; ]; W% r1 W/ Z

5 @9 F- M& O7 ]* h6 ~; v: O! Y) N+ w! ^. z4 x8 d5 o
string和pchar的相互转换:
  y% o- h3 p; a2 lstring –> pchar: pchar(s; @! l: ?: H& t  ~" G
tr:string);
+ y' p' K" x; gpchar –> string: strpas(p:pchar);
; O: Q3 N. E! p: v) F. o
+ A8 r! ~! {. o8 R- [1 M$ \
/ u( n. A8 Q- t* {+ i6 U( U
9 X( e5 Z1 q! ^4 `在Delphi代码中定义数据库
4 ~" n  f4 s, [* p# \procedure tform1.create_tbl;$ V+ S( G- t: A1 @
var tbl:ttable;
6 ~5 F' Y1 H; a/ f$ F% S: F: }begin$ S. q2 v- ^5 l* M' c
tbl:=ttable.create(self); // 如没有声明中的”tform1.”,Delphi不认这个self  g. l% P9 x+ c5 {, c7 U) n# h
with tbl do, Z- S% I. a9 e$ F1 f0 j$ K
begin5 ~4 G( K8 E6 p) d2 A$ c) g2 _
datebasename:=;dbdemos’;
: I0 E: ~/ j- S2 {* N& n# f- Gtablename:=’my_tbl’;9 q4 B0 x/ a6 v- v) a* n2 G
with fielddefs do6 H7 u! W& A8 q) Z; J
begin
, H! @  T# J# j! s9 x+ Q6 \7 x( Vclear;
9 F) W- d) x5 p0 m  b7 J, K* padd(‘No’,ftInteger,0,false);
! b2 H7 d/ G3 S  l+ V  H! Wadd(‘Name’,ftString,0,false);
2 d4 \1 ]: S7 g5 B2 \3 |+ n  k…2 c' @6 ^; k: ]  b  t4 o! W- K" b
end;
6 F$ P9 K: |' j* x# Kwith indexdefs do8 e0 Z/ _8 O; j4 N0 ~
begin
* z8 j( N" H* d: \! [1 vclear;( f& `" X( j# J
add(‘primary’,'no’,[ixPrimary,ixUnique]);! ^; y; B& s* \" I5 D$ h# |
…
$ v1 a9 ?! E/ G, Nend;
0 X$ W" D- A- Y& Y( F6 DCreateTable;! u% p0 X7 a7 S, f% h/ R
end;
* c8 J6 D+ Z' s2 d9 p' h, \end;( }8 c# m9 B9 E4 O3 Z
9 F: H* }5 B3 b/ m* Y7 m
3 r, X, t7 G0 n1 ^$ {
string、TStrings、pchar的相互转换(这里是我的个人经验)& E1 y: O" m( V6 I
假设有如下定义:
; z" y: J1 v0 {. z" lvar
8 @4 F$ Q: Q; i8 N% h' S( _. ?p:pchar;
3 K* |5 j$ m) X- W0 @2 b7 Is:string;
# {% W7 g$ s/ D$ M5 n# ^ss:tstrings;5 F  F2 T- N- y$ ?* q, ^5 V
begin5 v9 D1 I7 V* g3 d4 b: @( b
ss:=tstringlist.create; // 开始时一定不要忘记创建ss
7 v8 o( l9 b4 e& e( \6 W& z) C$ h" Jss.text:=s; // string –> tstrings
: F& A; |: x0 B# X. Xs:=ss.text; // tstrings –> string
( i6 V6 O' i3 X0 Wp:=pchar(s); // string –> pchar
' g$ ?; g7 J0 M- X3 ~s:=p; // pchar –> string. @; }1 C/ `, Y9 T2 N; U) T& U
showmessage(s); // 合法语句
$ q- {% c3 V% X; |1 g) sshowmessage(p); // 合法语句
7 K) ?9 ?! \' ]# T% ~; q; T1 [. ?# V… …
2 F# Q& n9 B2 ], ass.free; // 最后还要记着释放ss占用的资源7 h3 Z8 F' w* D5 O8 ~7 B! v& I
end;
6 C" @+ |5 }, W0 M  \- a/ z% h; V: K) s" p
! X% J) x; L1 A8 y$ T# y
& Y$ ~3 D2 a; z. f1 X* k0 l) M, F5 n. u0 X3 G% o& O! y
在设计Menu时,常用的ShortCut可从下拉菜单中选取。但我发现可选的ShortCut有些不在列表中,如ESC,Ctrl-Shift-A等。我试着在ShortCut项的右边输入:ESC,竟然成功了。再试Ctrl-Shift-A,这回Delphi自动把它变为Shift-Ctrl-A

TOP

發新話題