打印

delphi 技巧合輯

delphi 技巧合輯

INI文件的操作要点
' r- d3 L* r5 Q(1)在interface关键字后的uses子句中加入7 {9 s+ @$ ~9 e6 n, d
uses …,inifiles;3 B4 \6 d  W/ d/ p: X$ l
(2)设置变量:var inifile:=TIniFile;$ H5 [: i/ Q2 n9 ]" i4 G& N; P9 @
(3)使用前,一定要先做:7 z7 u, Y9 c; I. _
inifile:=TIniFile.Create(inifilename);# v. j7 h4 {: W1 `! l  H8 j
我在这里绕了个弯子,写成
% E& M" Z! W9 o; q+ O$ vinifile.Create(inifilename);6 j6 x/ @0 k- f6 X5 T7 F
# |6 g. |, {  w) x
TShiftState用来检测CTRL,ALT,Shift,以及鼠标按键的状态,
5 {  B# o7 _$ N常常用在键盘或鼠标的事件处理程序之中。0 f( b$ f, s0 x6 u2 C5 m' ]% a
; m, p" W) D! t1 ]3 X2 X
DCU文件(编译的库单元)的重用- y/ C# p6 |" ^' [3 t
(1)在interface里的uses子句中引用。如Windows,Dialogs,
, a; @( D! k2 S" c等等,要求被引用的DCU一定要放在Delphi 3\Lib子目录中。1 Y. j$ h- v! l5 K4 I
(2)在implementation里的uses子句中引用。如果是自行编写的8 L5 b0 ~2 y# Y+ W, v
DCU文件,应采用这一方式,并将被引用的DCU文件放入当前
# O1 U! u) C4 H7 q6 o工程所在的子目录中。: p& H. Z! e$ ?3 v" d. h
executefile函数(在FmxUtils.DCU中定义)不能用在FormCreate0 w. }9 V9 ^$ P! e& E$ R& W5 D2 {
事件中。真奇怪……" z3 F- y* w* ]) c. U0 t

3 o0 `( b; X9 ^内置的版本号控制功能
3 @1 E1 {' X8 z2 y在Project Options中的VersionInfo项里,有版本信息的定制,$ ^0 c1 m4 l# |3 g. V  R5 b7 U1 \
包括一个有趣的版本号自动增加功能(Auto-increment build
4 ^+ Z& ~) I$ x3 D% N7 C9 Anumber),即每Build一次,版本号中的Build Number加1。选中( h; ?+ ?$ S1 J8 |& t
Include version information in project,编译,用资源管
% Z, y5 F6 j; u- ~" S" }理器里找到生成的.exe文件,点右键,查看“属性”一项,就6 B( a6 G% t+ b- t, m
会看到在属性中多了一页“版本”,里面就是你刚才输入的各
9 q5 _3 M4 ^# _# n7 A项内容。( y5 W* Q) d0 @* g6 M4 t! X

( s# N$ X* [. f9 L$ Z8 Y4 r4 T% T3 k) q7 R% N  N& B- H1 |
定制Speedbar9 ~5 X% z0 o# j8 Y
右键点击左上角的加速键条(speedbar),选中Properties,
4 l+ l3 @. M! h! y, ~5 Z在列表框中找到你想要加入speedbar的命令按钮,将它拖到! i/ [2 h* r& C& W( ^* {# W& j9 b
speedbar上的合适位置即可。如果speedbar上没有多余的空间
! o% A( t' V8 H7 d0 w, P7 P9 @来容纳新的按钮,可把鼠标在speedbar右框处变为双向箭头的# _8 U4 k! ?9 ?" x
形状,向右拖动一段距离,就可腾出空间。如想删除speedbar
) `4 r5 n  A6 @& z上的某个按钮,可简单地把它拖出speedbar的范围,就能删除。
2 ^8 ?. @0 V/ s
- U* G( i% d5 g+ P4 J/ A
) z) I! U2 ^1 A6 W2 a计算出的字段/ D" I3 O* h- v! Q
在写一个程序时,我要在DBGrid中显示出一个memo的部分信息,当我把那个
8 B6 Q: S+ Q6 F: K. G# umemo字段放进去后,运行时只能显示出“(memo)”字样。从书上找到计算字7 Q1 u7 r% j0 I/ t3 A$ J0 j
段的用法后,我在TTable中增加一个计算字段MemoHeader,宽度为40,在此- q1 M' X8 P" J3 V% |% b
TTable的OnCalcFields事件中输入:6 @0 v+ c& v# ?, h: b; p* v, U
with MyTable do* ~- ^9 w; y9 K$ B, \( t! a9 ~, ^
FieldByName(‘memoheader’).asstring:=FieldByName(‘memo’).asstring;/ K! E' Z2 s# N' g
在DBGrid中放入MemoHeader,运行,OK!+ P( {$ ^# @. x, e! C) U* p: W
7 @8 T1 F7 a/ `  c
7 z6 m9 ^3 U, y- F$ k% f0 K& b/ @
字段编辑器
) f  Z" H; [% R$ c" u解决了上面的问题后,我继续学习字段编辑器的作用。原来,DELPHI通过字
% P  G1 z7 [4 n3 n: z段编辑器,近乎完美地实现了数据库的字段级的控制,这包括:) A4 O2 ^& b" ]& k1 J
1)字段在DBGrid中标题、宽度、能否可见;% S3 F0 i" B# d/ z& S
2)字段的显示格式和编辑时输入的过滤条件;
6 X, \0 q! o7 T% Z9 H3)字段是否只读;
% o- ]; p: d7 X3 z7 m0 {9 U4)字段的类型:数据字段/计算字段/查询字段/内部计算字段;" Y9 d7 j( C* y5 D! r# N
5)字段的显示/赋值/修改等事件的定制。
0 C: C; [1 e. E% U$ z
% ?2 z/ n$ M' h6 ~5 w( v1 f9 L$ ?8 I7 O5 n2 s- ~6 `
设计Form时的快捷键3 Z0 X/ ]4 Q- v" w3 c
Del 删除所选组件
! v8 ^/ [0 ?2 j& ~+ zEsc 选择当前组件的容器(通常是Panel,Group或Form)1 G2 g. ~3 x9 [4 l' o% b, N3 t' q0 @
F11 在Form或Unit和对象检查器之间切换
" ]2 K& d" t% y0 ^# o- \* oF12 在Form和代码编辑器间切换+ s: R2 [. r* ]' m; G( U7 U6 M2 ?) w
Ctrl-F12 显示“查看Unit”对话框
, P, p1 [5 [+ }; vShift-F12 显示“查看Form”对话框
, G6 {+ C/ {( h9 @TAB 下一个组件
( ]5 g8 @5 f' DShift-TAB 上一个组件- }) l' }2 R0 G4 R' k
方向键 选中此方向上最近的组件
5 d+ E# Z; u) z* M4 t6 v) F' xCtrl-方向键 将所选组件移动一个点4 O) ?: d; h! X2 L* r* u, e
Shift-方向键 将所选组件改变一个点的大小& c( x: l% i, y: `( `* [- U
Ctrl-Shift-方向键 将所选组件移动一个格
! n! w0 q/ |: `% P/ y. _. jShift-click 按住Shift键再用鼠标点击组件,可以选择多个组件。- B" Q" U! G2 ]5 l; I
–= 下面这条是我摸索出来的 =–/ O- g* i/ z% I7 v, U7 N
Ctrl-drag 按住Ctrl键在一个容器组件(如Panel,QReport,Groupbox等)
/ o: Z4 {) N& A里拖动鼠标,可强制选择鼠标拖过的矩形框中的所有属于此容
! \# Q/ R( n9 p' U% `器的可视组件但不包括该容器组件。
# \! s+ M) t4 \  Q8 T, G( p& O% z9 O- p$ V+ N( y3 n
* k+ q. q6 {6 U8 W  W! c
使用QReport的若干经验/ L  h1 n  {- K2 W
1)QuickRep1.DataSet:=query1! L. M- x8 L( a+ A
不然无输出结果! ^4 ], d4 x1 Y$ S: ^* y) N
2)从qrpt2man.doc中查知,格式化输出结果的方法是:$ D2 A0 {( |& J( ]' D5 a! n$ j
在QRDBText.Mask中设为.00;0,将使输出带两位小数。! d$ _' M* \8 w7 }2 `
3)设置Group时,先加入一个QGroup,再加入一个QRBand,将QGroup的
, d9 j5 s5 w3 r) h$ x8 p1 QFooterBand设为刚才的QRBand,就可将其联系起来。9 v& U/ Z' Q3 p4 x" x; }
4)在Group中打印的合计数,其ResetAfterPrint设为True,可实现分组合. u8 n1 M& v6 R$ |
% R. I3 W' m4 k/ |' J1 @, Y2 p
format(‘%*.*f’,[8,2,123.456]); //等价于format(‘%*8.2f’,[123.456])( m2 m+ @- m+ W- k1 i# D$ o2 I
format(‘%d %d %0:d %d’[10,20]);; T9 R3 F) [. L3 f/ o9 g% t. S

5 F( o) R, t6 Z2 T) h3 N1 r
& `6 {9 s8 l6 X$ M
, V' ]* T0 l! n, s4 A0 m: m( @( {播放一个wav文件
' s% W. M0 I# _5 i& ^  d  ause mmsystem;  h) y* P8 l$ q; I
SndPlaySound(‘hello.wav’,SND_FILENAME or SND_SYNC)' g0 l6 O) s; c. c, _# w
7 C1 S" G2 ^& f: {4 n% R3 w* |( }& w3 p
使你的form适应不同的显示分辨率; i) p& b2 k, @1 ]
假设你在800*600的分辨率下设计的form,第一步:
% j2 B$ z: t$ Q. l- ]1 D6 s; ~inplementation
. h7 h/ a- r6 ]' k/ Q0 ]const" x. v  a9 y! Q
ScreenWidth: LongInt = 800; {I designed my form in 800×600 mode.}) H) ^3 c% ?, l7 y+ B
ScreenHeight: LongInt = 600;
; Q3 ^9 j. w) |6 z7 l3 p# M! N
{$R *.DFM}
8 w- z3 s- T( f8 q6 H; E& Y  s+ ]# s9 q' {: r7 _
procedure TForm1.FormCreate(Sender: TObject);2 V4 o& k+ e5 L" ?/ Y& H
begin
9 W+ X; O; H( h( }. {: R  `8 d8 tscaled := true;+ y) k7 ?" U8 v0 U; n) F
if (screen.width <> ScreenWidth) then
: `) m* ], [- E: {. }" ?3 d( n, Cbegin
3 o! M0 J8 _! t! H6 ]. `height := longint(height) * longint(screen.height) div ScreenHeight;
! M2 u, k  N7 ]! I, a1 A. mwidth := longint(width) * longint(screen.width) div ScreenWidth;
- I9 f8 u, ~; Z5 A7 z) `% QscaleBy(screen.width, ScreenWidth);9 h. y# b3 P( \% e& S9 J* r! \: c
end;
9 P2 r% o- B6 n5 ]$ O$ o2 Rend;5 t5 C# z0 n- ]: }4 D9 u

2 O+ Q, m  Y7 |* ~/ m! V下一步,要让每个子控制的字体改变到合适的大小:
$ Q2 S, ~/ q9 q3 _. Utype
% k' E# N. [  @4 `$ {8 O, YTFooClass = class(TControl); { needed to get at protected }$ J# P. D( \# d/ C7 I
{ font property }
9 y2 ~' c$ ^+ s: u
/ B/ F( J8 v$ H6 V# i7 J+ evar- h5 L6 I( t! H1 L% r! o2 R& z
i: integer;
- G9 o; m9 h  O! L/ z1 Gbegin7 b: |4 ~  }6 M4 Y
for i := ControlCount – 1 downto 0 do
/ i! U/ r/ ]. u  D/ J0 OTFooClass(Controls).Font.Size :=
# J; R# x, N) J; y- ](NewFormWidth div OldFormWidth) *- |, M  i0 v, y0 n& j5 z7 B
TFooClass(Controls).Font.Size;
$ ]9 |4 S7 e4 O9 V4 h/ Tend;0 v: X& _2 H( \- k; k+ h4 }

/ W( S8 V. D6 f  O3 w用raise引发一个错误处理例程2 y: O* y2 D9 w  p/ D
示例:先给出下面的定义
) j6 c5 N+ K6 Q9 a5 c+ Htype EPasswordInvalid=class(Exception);* O7 p$ t% L. c# c
这样你就可以随时引发一个”password invalid”的例外:
1 i  P6 X% n4 M8 l% s" X% C/ f( N* Wif Password<>CorrectPassword then
: n/ G+ |" k! }- E. e7 q+ sraise EPasswordInvalid.Create(‘Increect Password entered’);
, b, I4 Y* Y0 B2 Z* @( B+ U0 i运行后,出现信息框( y  ?0 ^. j2 Y
Project Project1.exe raise exception class EPasswordInvalid
' O" i3 V* U- T' p6 q9 [# W- i) }1 bwith message ‘Incorrect Password entered’. Process stopped.+ B: Y, w: M2 I% ^
Use step or run to continue.9 u% q1 Q" N: h. _  J- n( x
再按Run按钮,出现一个信息框:8 g6 L  S4 t4 X1 L. M- W
Incorrect Password entered./ c3 S; R4 O$ M  j) n- Y
. K! N3 D: P; u" e( `

3 r0 m6 U" ]' i) g% J3 ^' Y从DEMO例程中学到的若干小技巧% m% ^7 Z! z+ o% J
在demo\internet\http\webbrows\main.pas中,9 h: c  P& r1 l' E6 z2 {
procedure TForm1.DocumentSourceClick(Sender:Tobject);. N6 @( T) O3 d* Y4 l' C8 e( U
begin
' b. s# i- H% t1 S7 gwith DocSourceForm do
, u+ v# z: U0 H+ A. Vbegin$ Y1 t8 D% n% S$ F, [% S$ X0 E
show; // 显示HTML源码的FORM
  J- Z9 e6 ]  J' M" F9 B. t) F" K( H  PMemo1.lines.clear; // 清空memo1中内容# N; k: Z1 ]4 l2 u5 d, ~
Memo1.lines.add(HTML1.SourceText); // 植入源码9 x+ Z6 O, k" b  k* v8 s- F
Memo1.SelStart:=0 // ***/ [4 `" T4 y1 y$ K/ E! O" a/ l+ u
SendMessage(Memo1.Handle, // Memo1的窗口句柄6 @5 N/ m+ ~) c  b+ ]4 B) c/ Q4 V
EM_ScrollCaret //将Edit Control中的caret光标滚动到视野中
1 G( C8 V+ f8 A! Z0,0 //这两个参数暂不使用+ f/ J5 \1 l0 {# \$ r, `
end;
; e2 x4 U6 r& x. Lend;9 x" l9 G. }% a. J7 [1 j, o& I6 K
(此SendMessage系一WinAPI调用,给一个或一组窗口发送消息,直到: d1 o! L8 }# c
相应窗口处理此消息后才有返回值。相似的另一函数为PostMessage,
  X; a) I0 e/ ^6 C; u$ M它将消息放入消息队列中后立即返回。)) S# J9 p$ T* Q0 @& q8 y% R8 o' l
*** 清空当前选择并将光标移动到指定字符(0代表第一个字符)。如同时( y0 A* ~4 |" D! k+ o+ k
设memo1.sellength为一非0值,可选择一段文本。0 \7 T2 E) W+ G' m6 J% {
; k4 J7 L) t$ j' b. y

3 D% x; f% F0 ]奇怪的I/O error — 我在开发过程中发现下面这两条语句
8 j6 E( J: Z* Wassignfile(fDesc,CDDatadir+describefile);1 h1 t) k% V: s9 z, c' O
reset(fDesc);
5 Z* q8 Z  p, L8 P6 S! P每当我第一次运行到这里时,总会出现 I/O Error 183 的错误.
% @4 s. K2 L  e  [; A/ \最后我想这也有可能是没有清除 ioresult 的原因.在两句之间加入8 l( g* ]8 B3 s- `1 U/ E  r3 F: v% V7 A
if ioresult<>01 t( t! M$ P: }
then; 6 `, z2 b% }. S  K% ^) Q, \& d
oooook! 可以了.
8 x0 a& q) g/ u2 ^( \# K1 J7 L; u# `
3 q7 T6 J: ?. d) r! J3 r7 W! Z
值得注意的I/O error) y6 M' ~# Z( O$ m( u% ^
AssignFile(F, fname);
& Z+ |/ v/ Z5 ^) VRewrite(F);
% I% N& M4 d# z! a2 a当文件 F 经 Reset(F)打开的情况下, Rewrite(F)会引发一个异常: I/O error 32( a* O, W9 A9 f2 G+ s
反之,经 Rewrite(F)打开, Reset(F)也会引发同一个异常.% |# E/ Z9 \% h7 E7 {' {5 h( i
Reset(F)两次,closefile(F),再Rewrite(F),或反之,也会引发同样异常.
7 e( k$ ?7 y2 m5 [! a( w, _, m0 U: Y# W1 R% h/ t5 z/ O
/ }% x1 D, p7 j. N$ j
: H( Q6 N6 [0 |% ?1 I, Z  l/ f$ R
string和pchar的相互转换:
0 J/ i- R, O- d- [' ~string –> pchar: pchar(s
+ I- t* H6 S! a: Y& {5 n8 ?tr:string);
7 |8 H. S* Q' X6 W* t" t& Tpchar –> string: strpas(p:pchar);6 T5 m6 w/ k! n7 e7 R
8 h+ M: ^* [0 F, B4 O* W: U" \
3 G8 K. p1 W2 a5 m& x8 C" E) P

+ K2 l; e1 l9 K$ ~# P' Y5 N7 |* c在Delphi代码中定义数据库
6 M: g! N, V- z2 r2 Sprocedure tform1.create_tbl;
* D! r* E1 ^# X, Q. yvar tbl:ttable;+ K  T; m; H# X% G" @6 B+ }
begin7 Z1 U( A# R. Q  {  E
tbl:=ttable.create(self); // 如没有声明中的”tform1.”,Delphi不认这个self! H- i, g# m+ s: Q' q' f" H
with tbl do
: Z$ n) ]6 o4 U+ ~& J7 o7 u1 ]begin) Z: M+ z4 a6 m4 c+ G7 v" |) ~
datebasename:=;dbdemos’;
! X# t  _; R4 F8 o/ u# Z4 @) s. Ltablename:=’my_tbl’;% P* W3 o2 S+ N2 \9 m, `0 ^
with fielddefs do+ r; T' Y- I- x& n
begin4 x& M  {" T. P  i+ u( V
clear;
  q8 ?; W+ o" a, ~# qadd(‘No’,ftInteger,0,false);" ]4 p5 B2 G1 |: u$ I5 V' }
add(‘Name’,ftString,0,false);/ l$ P' {: ]- Z: K0 L% W, Q4 V

, y5 a% C1 Z" D, ~end;
9 D& D* A& Q; twith indexdefs do  B! O6 b  i4 m- X7 ?( A
begin- e7 G9 h1 F$ o/ T" m% I
clear;6 K) B' [  [2 X  `6 b
add(‘primary’,'no’,[ixPrimary,ixUnique]);# b+ O2 }  @/ j! O3 L

  t# ^3 M# V% o" tend;
0 v9 V& l9 R  pCreateTable;
6 Q1 _! H6 G3 `8 G* V7 a% b, {end;5 Z6 r* V( x; G. r
end;
- A5 {3 M: y! [0 P( H  [- D3 t+ m( N6 k+ Z' H3 M' W
0 j, Z! r' x1 N( O- g
string、TStrings、pchar的相互转换(这里是我的个人经验)
+ [% C- W% s8 n& \  N+ h! f假设有如下定义:
# I. l  C. \( O5 f3 Nvar
- ^8 v2 ]' s3 O6 j4 ~: t5 Kp:pchar;
0 d- o+ v/ G& X3 j; }: R" as:string;
' g' s2 T' V6 y3 d4 _6 s' Jss:tstrings;
# s* W, x" a9 x( I/ gbegin
. b, n  ~, C2 T( ]! f% J5 m* _1 Xss:=tstringlist.create; // 开始时一定不要忘记创建ss  j% d+ \) V, c, g) A$ }+ H+ G
ss.text:=s; // string –> tstrings4 h& [+ C3 Z7 I; N5 C
s:=ss.text; // tstrings –> string
4 I3 I8 v' j# o) u% cp:=pchar(s); // string –> pchar0 M. q8 E/ y5 j" j; K+ ?
s:=p; // pchar –> string
% F$ M+ R( V" i4 fshowmessage(s); // 合法语句$ S! D( c3 D  g0 f) U, O: _5 e
showmessage(p); // 合法语句) [/ X8 x2 n6 O3 `  G$ E
… …
0 V( o: _4 \( P1 h5 T( gss.free; // 最后还要记着释放ss占用的资源; _! ^6 }- x* h! J3 }
end;
. C$ ], d7 Y& O  b7 F( n0 }! @% Q
. f( l& d' s; u
. N. E3 _' F: S8 d5 `5 ?
+ T+ T5 \) d# Y( q" t在设计Menu时,常用的ShortCut可从下拉菜单中选取。但我发现可选的ShortCut有些不在列表中,如ESC,Ctrl-Shift-A等。我试着在ShortCut项的右边输入:ESC,竟然成功了。再试Ctrl-Shift-A,这回Delphi自动把它变为Shift-Ctrl-A

TOP

發新話題