打印

delphi 技巧合輯

delphi 技巧合輯

INI文件的操作要点
7 V0 ^: B1 S5 U  Q/ _' u. u! Z, h. P(1)在interface关键字后的uses子句中加入* p* t7 [( {) Q- O4 J2 P" y
uses …,inifiles;& ^4 U; ~, O5 W3 o6 R6 [
(2)设置变量:var inifile:=TIniFile;
% k; y: Y) z1 N0 N9 f(3)使用前,一定要先做:. D' {1 |& W- t  ?
inifile:=TIniFile.Create(inifilename);
6 V9 @# R1 K  Q) v我在这里绕了个弯子,写成# H. ?/ x5 V0 u: N+ ?2 x+ l3 y
inifile.Create(inifilename);
% v. U% U6 N) x" }3 M/ a- |* S( K
! f5 q4 R) `+ a8 qTShiftState用来检测CTRL,ALT,Shift,以及鼠标按键的状态,
- f" b7 R/ s0 u常常用在键盘或鼠标的事件处理程序之中。) Z1 R) j9 V. H3 S& D3 x
" X0 a* B! k8 p  K. }% |
DCU文件(编译的库单元)的重用
$ J0 u4 `/ D, ~/ K$ u(1)在interface里的uses子句中引用。如Windows,Dialogs,+ |7 c5 k$ V  M+ \6 z& ^3 G; T
等等,要求被引用的DCU一定要放在Delphi 3\Lib子目录中。
/ Y2 K# `  |# Y: d3 w(2)在implementation里的uses子句中引用。如果是自行编写的3 t1 c$ ?- F0 }+ s
DCU文件,应采用这一方式,并将被引用的DCU文件放入当前
- P/ x7 [' ?. X, |工程所在的子目录中。" G! ]2 ]# j+ G% Y* ?
executefile函数(在FmxUtils.DCU中定义)不能用在FormCreate' {  E- P; x% K) U. A/ o' y
事件中。真奇怪……& Z& y: E9 D) F' g) K0 ]9 K

$ j3 b) |4 |' ]2 S内置的版本号控制功能
* y. m* X( M; e在Project Options中的VersionInfo项里,有版本信息的定制,! a) m. S. f. K- l5 k" Y# E
包括一个有趣的版本号自动增加功能(Auto-increment build
: w0 g& }( D# j$ q4 xnumber),即每Build一次,版本号中的Build Number加1。选中7 b9 k# G+ ]- g9 k8 Z2 A1 Q
Include version information in project,编译,用资源管0 p0 r' o3 n, W' H6 k1 n: |' c
理器里找到生成的.exe文件,点右键,查看“属性”一项,就" i9 u; S' r% L- M$ p( \
会看到在属性中多了一页“版本”,里面就是你刚才输入的各
, J5 T6 \$ g* q4 E项内容。
+ J2 T5 g8 Q+ y9 f& [
. h* K0 A  B; m  @- u+ N# K
7 o$ y: T5 }8 j; U; }0 T定制Speedbar
2 ?/ ~! @! b' C1 y: b右键点击左上角的加速键条(speedbar),选中Properties,
- m( t4 f( }8 F3 D5 G在列表框中找到你想要加入speedbar的命令按钮,将它拖到1 i8 q% _  s( k, M
speedbar上的合适位置即可。如果speedbar上没有多余的空间! Z8 G' [5 ^, ?3 `& Y
来容纳新的按钮,可把鼠标在speedbar右框处变为双向箭头的/ }2 b. p; s) t- ^  [, }" O
形状,向右拖动一段距离,就可腾出空间。如想删除speedbar
, z8 S2 S7 H8 S/ {5 S. x* k: }7 M上的某个按钮,可简单地把它拖出speedbar的范围,就能删除。
; o1 n: d2 X2 C+ B2 o  l- W6 v& T# b# m& a2 V) ~* d" }7 G

1 m6 o% I, u) l7 N& m计算出的字段
% z6 q  e/ B8 q  R+ a$ D在写一个程序时,我要在DBGrid中显示出一个memo的部分信息,当我把那个
& e* @+ F- d1 H; r' Z$ s; c& vmemo字段放进去后,运行时只能显示出“(memo)”字样。从书上找到计算字
) y. ]" C& v* W, ~& V. W3 _段的用法后,我在TTable中增加一个计算字段MemoHeader,宽度为40,在此! _; r, F) E6 l9 `5 G
TTable的OnCalcFields事件中输入:
$ W. I* Z$ z6 h: M" R5 D; s4 wwith MyTable do
  j& Z6 K( a& B! r0 U0 [# P; zFieldByName(‘memoheader’).asstring:=FieldByName(‘memo’).asstring;
9 _7 U3 P" \# h) D. G. ^5 {) e在DBGrid中放入MemoHeader,运行,OK!
5 A$ i% W' v  K& M. o8 |* g' c+ W0 w1 t  ]2 B& U3 N* \' R

5 o, t6 n5 l' N1 Z字段编辑器# T  k8 z* p1 g" t
解决了上面的问题后,我继续学习字段编辑器的作用。原来,DELPHI通过字
$ I; O7 L) q$ [% f段编辑器,近乎完美地实现了数据库的字段级的控制,这包括:
& V% i4 l/ t' P- F1)字段在DBGrid中标题、宽度、能否可见;3 w6 s) D- o  d: [
2)字段的显示格式和编辑时输入的过滤条件;
. ?1 P- M9 g, A3)字段是否只读;) _% z5 y; R/ j0 O
4)字段的类型:数据字段/计算字段/查询字段/内部计算字段;2 F1 F0 e% V' X. p0 I- V, a; Q* F
5)字段的显示/赋值/修改等事件的定制。" f' g) W& F* [2 ]& ~- Z

4 @+ }: h5 D# p) q
& s) Y5 b1 J8 z% I8 ?# q4 Q& H设计Form时的快捷键4 [* Y/ N9 R' `; c- r! U
Del 删除所选组件
' r* u5 w8 i- k# s1 r; a2 pEsc 选择当前组件的容器(通常是Panel,Group或Form); z6 ?$ n0 e+ Y: O6 y" y
F11 在Form或Unit和对象检查器之间切换
+ Z! W6 n: O% l6 g$ I8 LF12 在Form和代码编辑器间切换
! B0 c. l3 E  b0 BCtrl-F12 显示“查看Unit”对话框
) ?+ V; u  ?. Z+ P9 L- @Shift-F12 显示“查看Form”对话框
- {0 A, y+ l) f6 HTAB 下一个组件/ q$ u1 ]3 X, c9 m
Shift-TAB 上一个组件
0 ^0 b8 L$ S3 e  ]3 a3 Q  s方向键 选中此方向上最近的组件/ |3 d" B* c& b9 G# j
Ctrl-方向键 将所选组件移动一个点5 [5 t* j7 a* z0 n+ S+ x; i* Z) f0 N2 N
Shift-方向键 将所选组件改变一个点的大小
8 Q- ]5 ^4 F( w  y/ @  s( yCtrl-Shift-方向键 将所选组件移动一个格
/ s9 b8 S! p. ]& S0 I: B1 @# mShift-click 按住Shift键再用鼠标点击组件,可以选择多个组件。
( C8 C5 p) Z9 T- q( A) o3 E* z–= 下面这条是我摸索出来的 =–5 z3 ^6 U* o' B! o, }
Ctrl-drag 按住Ctrl键在一个容器组件(如Panel,QReport,Groupbox等)
$ s  H. m+ r& }0 \4 F( ~  v里拖动鼠标,可强制选择鼠标拖过的矩形框中的所有属于此容+ S( W9 a, f4 k
器的可视组件但不包括该容器组件。
1 R( m3 S0 E( k- ^$ {. [( W1 f3 E: R5 ~4 t. ^

7 O/ ?+ `4 q  i, |7 D( `6 ~使用QReport的若干经验
- Y/ D  d5 }# B9 U1 j1)QuickRep1.DataSet:=query1
+ V% D3 i, V- p: c6 J; l9 d" m不然无输出结果
8 l2 j( b. a& R& w2)从qrpt2man.doc中查知,格式化输出结果的方法是:
* V, {. Z7 z) y( D# s在QRDBText.Mask中设为.00;0,将使输出带两位小数。& o1 w/ ~. Q$ g+ A  R8 J" Q7 b
3)设置Group时,先加入一个QGroup,再加入一个QRBand,将QGroup的0 C* b# p6 k: u2 l) X6 b% r+ _6 F
FooterBand设为刚才的QRBand,就可将其联系起来。
- i6 `+ a- A; l  X7 D; U- y  R4)在Group中打印的合计数,其ResetAfterPrint设为True,可实现分组合1 k4 f9 `7 t' ]. D/ e$ g9 P
5 ^# |2 b* y* G! g. K. @/ ]
format(‘%*.*f’,[8,2,123.456]); //等价于format(‘%*8.2f’,[123.456])9 l8 M& r5 a7 h! F
format(‘%d %d %0:d %d’[10,20]);
0 v4 W' F( S/ [4 k, U
" u7 d8 X0 r# |4 V: `! q* F/ |
+ z( ^0 w$ Q* x
  U8 r3 {' |" O; n1 h2 v5 V" p- T播放一个wav文件
4 S; [; f9 @5 Tuse mmsystem;$ N4 K: h3 k$ V" v) R5 u
SndPlaySound(‘hello.wav’,SND_FILENAME or SND_SYNC)
8 {( N! N5 o) ]' ?7 N. w* M  Z6 y) T& X+ D
使你的form适应不同的显示分辨率% S0 D' K5 {" {' Y/ Z) n9 \- N5 ^
假设你在800*600的分辨率下设计的form,第一步:
9 A* O: M3 m3 L( @8 jinplementation/ J3 u9 p7 a/ o* Z$ H0 q7 i
const6 H2 @/ c6 j, ^+ G( h: L
ScreenWidth: LongInt = 800; {I designed my form in 800×600 mode.}
5 L; ^1 m. i- TScreenHeight: LongInt = 600;8 `: k- j- t( u% y: H7 q
# E. {" u6 W9 z+ v+ z5 _
{$R *.DFM}
9 T2 G8 ^- J& D# T3 K" y) u
9 `( z7 u3 X8 i9 k) v- aprocedure TForm1.FormCreate(Sender: TObject);( Z  s+ s4 p7 k6 O5 y3 u1 N
begin4 |- `! f1 A  t7 p* n
scaled := true;& U' u  v; g  l* }+ f5 w
if (screen.width <> ScreenWidth) then
6 g+ A/ [9 K2 @2 h! ybegin( |2 ]2 r3 I9 z9 k, v7 w4 Y
height := longint(height) * longint(screen.height) div ScreenHeight;1 I2 A3 _, T0 k
width := longint(width) * longint(screen.width) div ScreenWidth;
# N3 @1 C+ Z& {+ C% A# ZscaleBy(screen.width, ScreenWidth);
: R$ ^: c3 Z! y- D  T# T! kend;/ T- ^/ m  d* i: O
end;4 }, {6 A+ z4 v" O5 B+ J

( V, D4 o9 F( p6 B( c' Q下一步,要让每个子控制的字体改变到合适的大小:0 x( g! ?4 s# h0 F& T, @5 l
type, b& P: X7 N5 m# z+ }! N: G6 g
TFooClass = class(TControl); { needed to get at protected }9 K% e: n: c% d& ~) C2 r/ I
{ font property }) B: a0 ?# o# l. X
4 S7 h5 A2 n! ?0 B! M2 M0 ^- V, s
var
; S7 |6 c- U1 {/ i  z1 A: U5 L- N# Oi: integer;& R( _; y. Q. o# b, v3 H1 w
begin
- {+ T# `2 \) K5 s& z6 z3 h, Ufor i := ControlCount – 1 downto 0 do
% K0 P" f4 u, h7 Q- \$ f  [7 v9 i( sTFooClass(Controls).Font.Size :=8 a( x" @) @0 ^" k. b7 L
(NewFormWidth div OldFormWidth) *$ d4 z; f) J3 B" _% K+ d3 s
TFooClass(Controls).Font.Size;' z6 s5 ~) S2 [' w4 C. R/ q; i8 u+ p
end;. I" C0 m& D$ a/ e0 {, i- E, _
+ ~9 W/ z9 ?; b7 f' H; F. ^: R
用raise引发一个错误处理例程2 F2 L# q6 d' w* T
示例:先给出下面的定义
2 f0 t8 Y! M" M3 I9 l; atype EPasswordInvalid=class(Exception);% Z+ _  C# D" b! ^9 E
这样你就可以随时引发一个”password invalid”的例外:' ^( x; v; J0 M
if Password<>CorrectPassword then$ K( D3 T$ C/ ^
raise EPasswordInvalid.Create(‘Increect Password entered’);% _" z5 b/ C2 x1 C) R
运行后,出现信息框8 p# j. t  g, t  t' o! W8 P' x
Project Project1.exe raise exception class EPasswordInvalid
3 f7 @5 M4 \$ Wwith message ‘Incorrect Password entered’. Process stopped.* k  H5 m- s; a; W
Use step or run to continue.# y& ?4 O8 q! h( a9 B( w- ^
再按Run按钮,出现一个信息框:
! @# ?5 w3 j0 l4 n% E0 uIncorrect Password entered.- }" ]& V4 d% H. j
& {% ]* f, o, M5 I4 l
" K0 M! E0 Q$ m, o* h" |0 L, [! ]
从DEMO例程中学到的若干小技巧" F0 ^4 y6 n: \5 C! \
在demo\internet\http\webbrows\main.pas中,
* k1 k( s) H9 e' Lprocedure TForm1.DocumentSourceClick(Sender:Tobject);3 U' y: q* ~6 I& B/ F
begin: K, c& }/ T5 t7 d% e
with DocSourceForm do
" s. h* {7 r( P/ Fbegin
& O: J: B0 T+ i* ^/ sshow; // 显示HTML源码的FORM: c$ q/ E2 ^' m2 Y4 M6 {: [
Memo1.lines.clear; // 清空memo1中内容
" I, |! T" i3 M% }Memo1.lines.add(HTML1.SourceText); // 植入源码
  w0 ~$ n' i% S3 e! n+ oMemo1.SelStart:=0 // ***
1 B. A# g* Z6 o$ k7 kSendMessage(Memo1.Handle, // Memo1的窗口句柄8 L  l4 Y9 S! j* K
EM_ScrollCaret //将Edit Control中的caret光标滚动到视野中
/ g7 R" o* Z! [- K# B! e0,0 //这两个参数暂不使用' }9 g5 ?) @7 R  @
end;
* R6 z, b' ]. O' tend;
! w1 |. L9 d' g0 K  W  A2 Z(此SendMessage系一WinAPI调用,给一个或一组窗口发送消息,直到! S+ l7 C, _! k! D6 [! A
相应窗口处理此消息后才有返回值。相似的另一函数为PostMessage,
5 X1 Z: ], E7 Y) m; H3 X它将消息放入消息队列中后立即返回。)
9 @; c/ x" h6 ?% T' L8 ^*** 清空当前选择并将光标移动到指定字符(0代表第一个字符)。如同时% `3 m6 X$ X4 f$ S
设memo1.sellength为一非0值,可选择一段文本。& \2 V5 ]  D0 y- K$ d
" s# H4 k8 D+ K

3 ]. u. l# K5 k3 K  |奇怪的I/O error — 我在开发过程中发现下面这两条语句
2 _% g2 {  A- J+ O& G$ i( A$ w9 M3 tassignfile(fDesc,CDDatadir+describefile);' P; t, M3 a/ S& J. D% H& k* S1 V
reset(fDesc);
  j# j7 I. ?8 l& m每当我第一次运行到这里时,总会出现 I/O Error 183 的错误.0 {4 ]4 }, Z: z' X; Q" t- i: B. c
最后我想这也有可能是没有清除 ioresult 的原因.在两句之间加入/ r: @, x  ]% c! w" k! q" f- t
if ioresult<>0
2 }, C) G1 q: a5 |1 U7 Dthen;
9 L4 m" i" e# I* e6 n; O6 F% Woooook! 可以了.$ n7 t" z& G  O8 m- Y

! D, x: D" b# M6 X1 a
8 z3 `- ^& J# K7 c. O值得注意的I/O error
  v, S) a2 v, a( }0 GAssignFile(F, fname);
! i) ]6 L' g, f1 wRewrite(F);# h8 u& k2 @& r1 \2 E" @  }
当文件 F 经 Reset(F)打开的情况下, Rewrite(F)会引发一个异常: I/O error 32, Z2 t' `  w% S8 q4 j/ F1 }
反之,经 Rewrite(F)打开, Reset(F)也会引发同一个异常.! U, ~; H1 |% U8 {: ?9 Y! N1 e
Reset(F)两次,closefile(F),再Rewrite(F),或反之,也会引发同样异常.
2 Y5 Y, f1 ^' A& a/ g- W3 F8 |' f! Q, k( r  L4 Z" ]

  g; O3 k, n! n( x
* x( b$ G( b8 B# ~8 Mstring和pchar的相互转换:
& }9 c6 F) k0 p  R, t& n6 Q( ~string –> pchar: pchar(s1 y6 I+ b" H( o' w7 H; K
tr:string);
6 i' }& M9 N# s( _  n; W5 Hpchar –> string: strpas(p:pchar);
) Q7 y4 ^$ H6 R2 z8 V9 [  i% Y# v
! A; p3 C- ?. e3 @7 P% v; c! K% g

, I& M  h( U2 P2 E2 t+ }在Delphi代码中定义数据库
0 Y- V  b4 Y$ ?- R: C1 {procedure tform1.create_tbl;+ j2 C+ a' m( t& p; O: B# B# Q" w
var tbl:ttable;
/ ^, i5 Q; i* j, b3 g( i! T) V$ Wbegin/ p8 h& H6 L- {' R) G( E' q, T
tbl:=ttable.create(self); // 如没有声明中的”tform1.”,Delphi不认这个self( \6 N0 `! \# S/ |! Q
with tbl do! |: a; T  L% H6 M
begin
6 K1 C7 k5 f* i4 p- Sdatebasename:=;dbdemos’;9 y/ K6 B2 Y+ D1 e( ?; x
tablename:=’my_tbl’;5 ?' C1 `$ V: f2 V' _; ~+ D
with fielddefs do
* [+ {7 S* H0 M( d2 z% p( Bbegin1 M9 x, }! f$ b5 P' _. g8 a
clear;
! k5 E. ]8 P# R: n) W* ^add(‘No’,ftInteger,0,false);2 ~8 S" A8 [; w. [; R
add(‘Name’,ftString,0,false);' k9 k8 h2 K. z; O

/ f) [! z# @$ }% y( C6 A6 j& J% X! Eend;2 R2 S4 L. \7 q* N0 `  i
with indexdefs do! s; ]  Z( b1 v2 ~+ ]2 T) s# e5 {
begin
  T4 f8 {3 r8 h! S( c8 Jclear;) X" z1 g6 m, S
add(‘primary’,'no’,[ixPrimary,ixUnique]);
* w: g; W& @9 ^  e- `9 E' B4 |4 R! {3 a3 u0 y6 b
end;
. `& l9 U3 c- r( pCreateTable;
: ^6 W6 \0 Y1 T. H$ |/ J8 iend;' ^% _! p& v$ V* @
end;
) s4 c6 h8 {" o3 ?+ Y8 t3 S4 A1 O1 k8 e2 K! X
3 u# |& a' M2 l$ G2 _
string、TStrings、pchar的相互转换(这里是我的个人经验)
* g4 u) d4 i2 C! @9 I3 T5 j( f( |假设有如下定义:& `2 O7 a: D/ x2 A4 M
var, M$ C! R6 j! V3 G4 g% z
p:pchar;" c: c+ O6 u" i  u0 T  Q
s:string;" q4 k3 w% m; F" n& w% {
ss:tstrings;0 T' T9 V  b: u: G, L5 x4 [
begin
0 S; [* O) A9 H$ v8 fss:=tstringlist.create; // 开始时一定不要忘记创建ss3 p6 c- X- F4 ~4 H
ss.text:=s; // string –> tstrings
5 E# b7 ?" c$ x2 J1 m& w7 rs:=ss.text; // tstrings –> string
/ _( Q; \7 Z7 x2 Z! ep:=pchar(s); // string –> pchar
/ E- P& M1 H5 K& j$ us:=p; // pchar –> string
5 F5 X0 R3 z( M4 gshowmessage(s); // 合法语句
" h  W3 w+ n- n" \! E, rshowmessage(p); // 合法语句$ H, \: T* F6 H- Y, c) o/ G9 T
… …
5 x& b, j4 B% m8 R. |0 W1 Mss.free; // 最后还要记着释放ss占用的资源
1 ]' s( W3 P5 m2 `# `9 J9 v4 j# kend;9 d/ g. s$ \7 C

2 \, q" E! \( i% W2 @5 e$ Y) o5 f- k9 q. k% `

# @! t5 @/ J# X在设计Menu时,常用的ShortCut可从下拉菜单中选取。但我发现可选的ShortCut有些不在列表中,如ESC,Ctrl-Shift-A等。我试着在ShortCut项的右边输入:ESC,竟然成功了。再试Ctrl-Shift-A,这回Delphi自动把它变为Shift-Ctrl-A

TOP

發新話題