打印

delphi 技巧合輯

delphi 技巧合輯

INI文件的操作要点
, P8 b' @4 |' T  e6 J(1)在interface关键字后的uses子句中加入
1 [% ~( I  l. W& t% D) q3 \uses …,inifiles;
. D0 N- A5 s5 J5 l& J(2)设置变量:var inifile:=TIniFile;
9 I1 p0 ]4 o# b(3)使用前,一定要先做:3 [2 [1 Y$ P9 _0 p
inifile:=TIniFile.Create(inifilename);
: g" {7 @1 E, P1 F/ d, J( u% r我在这里绕了个弯子,写成
7 ^# A. B, R; _8 q+ y+ ~inifile.Create(inifilename);; C$ j/ w- Q7 o- v# r0 K0 a
% O$ _4 Y" v2 n  c' t; ^
TShiftState用来检测CTRL,ALT,Shift,以及鼠标按键的状态,
3 A' @* C% H" X! s; p常常用在键盘或鼠标的事件处理程序之中。) E$ b6 J( d1 d( n# b+ c
& g5 w  ]* x6 L" i6 P& S% x( `
DCU文件(编译的库单元)的重用* `0 g% Z5 L% M9 D$ _4 i
(1)在interface里的uses子句中引用。如Windows,Dialogs,
3 n' B$ L: s! X% d等等,要求被引用的DCU一定要放在Delphi 3\Lib子目录中。
4 Y7 ~' ?' F  U3 o(2)在implementation里的uses子句中引用。如果是自行编写的6 t* _6 x8 F  x
DCU文件,应采用这一方式,并将被引用的DCU文件放入当前
! B( O3 j1 r! A% l! v工程所在的子目录中。5 I+ P& F, e6 @  K& E2 }
executefile函数(在FmxUtils.DCU中定义)不能用在FormCreate( i1 o3 S5 X) |
事件中。真奇怪……' k0 ]: _# u7 E2 o: d3 V
6 x8 e/ b8 l3 K
内置的版本号控制功能
1 ?7 ?$ `3 Z# X- |! Z6 |在Project Options中的VersionInfo项里,有版本信息的定制,8 ?2 D8 w$ v) {& @( `1 N
包括一个有趣的版本号自动增加功能(Auto-increment build* e( [* r+ R; {) n
number),即每Build一次,版本号中的Build Number加1。选中
$ X  ?& `7 ]$ E# G# p9 h( l8 p/ xInclude version information in project,编译,用资源管, e6 k# S' c$ M9 s7 h
理器里找到生成的.exe文件,点右键,查看“属性”一项,就
( _+ B% g# L+ H* W4 Y" x会看到在属性中多了一页“版本”,里面就是你刚才输入的各
8 w3 ?8 g- R6 f1 Q7 ^/ o项内容。
& A1 z! k. x8 B! G4 d9 r' d( a, F4 e3 S9 P  Y& k

9 X: A" i; B4 h- C+ E定制Speedbar
' T( Q+ `6 Q% g8 i/ d右键点击左上角的加速键条(speedbar),选中Properties,: G- ?4 u6 E8 [) j2 @
在列表框中找到你想要加入speedbar的命令按钮,将它拖到0 R. \; p* h# v9 X; L
speedbar上的合适位置即可。如果speedbar上没有多余的空间
! Y0 d7 p/ x3 j来容纳新的按钮,可把鼠标在speedbar右框处变为双向箭头的
0 a" r( W5 u4 V# |形状,向右拖动一段距离,就可腾出空间。如想删除speedbar
4 S* ], z( V6 d( `# v上的某个按钮,可简单地把它拖出speedbar的范围,就能删除。
; h; M( O% G* Z$ Q. e; ]& I
  w$ `% Y) `/ u2 U5 U/ B5 H# v  A% r1 w0 ^! j1 r
计算出的字段$ f$ |" C/ s& n" [& b0 T+ W
在写一个程序时,我要在DBGrid中显示出一个memo的部分信息,当我把那个  z' e+ O7 w4 u. p* z) F6 O
memo字段放进去后,运行时只能显示出“(memo)”字样。从书上找到计算字+ U4 R/ ]4 R% w  x  @* M( N* Z1 \
段的用法后,我在TTable中增加一个计算字段MemoHeader,宽度为40,在此2 i( T+ u6 y- C, a! A; @) ]7 N& \
TTable的OnCalcFields事件中输入:
1 D: \& C' f* ]- S1 T& ^with MyTable do# J: p2 R+ R3 |6 u9 s/ t  [
FieldByName(‘memoheader’).asstring:=FieldByName(‘memo’).asstring;- G% V; [9 K  G9 V* I6 R$ Q4 j
在DBGrid中放入MemoHeader,运行,OK!/ V! o; ^/ [4 o! \- m$ c

" ^8 z* P, s0 L5 U
! x4 B# M4 G8 `% t  e! e8 g字段编辑器
) F: T; }+ T0 @/ A) x+ E# G解决了上面的问题后,我继续学习字段编辑器的作用。原来,DELPHI通过字
- ~8 f6 ^# b( W( x) s/ l5 h: y3 B段编辑器,近乎完美地实现了数据库的字段级的控制,这包括:
7 N8 I7 O& Q4 K8 R6 W1)字段在DBGrid中标题、宽度、能否可见;) @0 l& s+ L6 X* f# c$ [$ N
2)字段的显示格式和编辑时输入的过滤条件;6 _1 m/ ~# W5 s( C6 y
3)字段是否只读;
1 A( m6 g, [/ Q1 M0 y1 r! \# L4)字段的类型:数据字段/计算字段/查询字段/内部计算字段;
: m5 n3 B$ z* v$ h2 Q# ^9 v5)字段的显示/赋值/修改等事件的定制。
+ D9 Y" h0 u9 C# P$ G& B
5 k- N3 o: B" o1 q& Q' r9 m1 s: c0 S$ P
8 @" p* {! R; N& @设计Form时的快捷键
0 O# A* y" L+ k* }5 ]! cDel 删除所选组件; j& u, F" o8 `& _8 D
Esc 选择当前组件的容器(通常是Panel,Group或Form)0 E8 I5 v; c& O1 t' @! c. \" `
F11 在Form或Unit和对象检查器之间切换/ R5 w" A/ ]7 R5 l0 B% h5 ~& ~7 E1 i
F12 在Form和代码编辑器间切换* h: Y: n) j# s
Ctrl-F12 显示“查看Unit”对话框
! ?7 ~7 r0 X  b+ A2 G$ }Shift-F12 显示“查看Form”对话框# ~0 H" H4 q) Y& A( Y. i
TAB 下一个组件
, s& @5 ?0 J3 V2 U1 \7 o& UShift-TAB 上一个组件
0 X: j) s- n# M6 j) U/ d* {; L! f方向键 选中此方向上最近的组件9 S) J8 b" _8 ]/ f% d8 _
Ctrl-方向键 将所选组件移动一个点
7 _9 P1 B" l& I; v" N, }; pShift-方向键 将所选组件改变一个点的大小" l. o2 f! ~# R. y7 o- N# {$ y
Ctrl-Shift-方向键 将所选组件移动一个格' q: \  Z0 t0 Z2 F5 O
Shift-click 按住Shift键再用鼠标点击组件,可以选择多个组件。
  Z/ u1 k7 T4 c) m# |! J" L% y–= 下面这条是我摸索出来的 =–
2 l* `0 [& g# O8 V( N6 yCtrl-drag 按住Ctrl键在一个容器组件(如Panel,QReport,Groupbox等)  S3 J" ?8 M" X( a' o
里拖动鼠标,可强制选择鼠标拖过的矩形框中的所有属于此容2 o5 L. |6 r! i% y
器的可视组件但不包括该容器组件。
- C5 m! p5 f9 x8 B
; T, ^4 n8 e% j7 _( f/ U5 `! E& R4 P% {' `6 {& Z/ n1 i
使用QReport的若干经验0 ]: t/ w: D6 V6 A
1)QuickRep1.DataSet:=query16 J) S4 c8 l; t  f5 B3 S. ]! f/ K
不然无输出结果& v+ F' v/ [& w9 N  D$ ]
2)从qrpt2man.doc中查知,格式化输出结果的方法是:4 I6 Z8 t, |2 [# `
在QRDBText.Mask中设为.00;0,将使输出带两位小数。
7 a. y# _* b1 U; l7 G8 C3)设置Group时,先加入一个QGroup,再加入一个QRBand,将QGroup的
  }4 e! w' ~0 B# `1 W- v+ O9 A6 n, ?FooterBand设为刚才的QRBand,就可将其联系起来。
6 }$ |8 W! c0 q* @/ W4)在Group中打印的合计数,其ResetAfterPrint设为True,可实现分组合
6 t3 E* O& @9 d- Y3 J, K6 w. G# F2 Z3 I  n1 l( O* e% i! l7 N) r, q
format(‘%*.*f’,[8,2,123.456]); //等价于format(‘%*8.2f’,[123.456])
" m* a7 {+ p8 s( N) \format(‘%d %d %0:d %d’[10,20]);
: P' w2 V' I6 _: ^0 U7 E& g0 e6 N$ g5 H0 [5 E

& E( X! {2 k/ |+ j% L, p
9 |, x' ]4 l9 L% q2 G# |1 {播放一个wav文件9 b0 n/ _# f5 u, ^$ ^
use mmsystem;% h5 G8 `- e0 y: i. v( r" f+ H
SndPlaySound(‘hello.wav’,SND_FILENAME or SND_SYNC)
! l3 L- H5 u7 Y$ j! j2 J- \
9 Q& P) M# {# g# z4 [使你的form适应不同的显示分辨率5 K7 o$ R6 p  U: E
假设你在800*600的分辨率下设计的form,第一步:
4 u/ ^. e/ q1 qinplementation, N3 \4 R5 P! z9 ^9 t
const1 X+ x2 y' a) n6 H; ]. w+ V3 h1 }
ScreenWidth: LongInt = 800; {I designed my form in 800×600 mode.}0 w) R% n0 E4 |# @
ScreenHeight: LongInt = 600;
, _3 g3 T* Y" X( a  O5 \% Z: N0 l* P( U. J
{$R *.DFM}7 A8 c9 P6 F3 N3 a

" n8 o% E$ u9 dprocedure TForm1.FormCreate(Sender: TObject);4 C" Y6 y2 k% S; Y5 @/ y9 G
begin
/ i# c$ K) L/ N1 Q% x7 uscaled := true;
5 f3 _' v* t, N( v5 ]if (screen.width <> ScreenWidth) then
6 l! ?$ b3 Z  O, d# w# O8 Mbegin2 ?3 P6 Z/ P0 `
height := longint(height) * longint(screen.height) div ScreenHeight;
  l/ K- j* |, i$ m- ^7 R6 G% Dwidth := longint(width) * longint(screen.width) div ScreenWidth;# |* e/ w9 @5 l+ W+ s8 J/ {* T0 R
scaleBy(screen.width, ScreenWidth);
$ p% d9 X& J0 B" H- e* wend;
3 P! [! ]8 b" zend;
* E# ~& q$ C% E% N& R# W- V  f% w; L9 ]- o8 D& m
下一步,要让每个子控制的字体改变到合适的大小:) i2 r9 s: V1 [- L3 O7 ^
type) T; [+ H  e$ d) [
TFooClass = class(TControl); { needed to get at protected }
0 ]* V! Y, F- W0 Y( h! m{ font property }3 Y3 @0 C, g6 f- X0 Q' n

0 j& N; ?# \- G+ q( O$ r- |var
! B2 Q4 L: Y9 Y9 \  G3 `; p0 qi: integer;$ i4 Z% u$ s. w6 `4 N3 b! E
begin
! @" V' w2 \1 \- L* B, k& ifor i := ControlCount – 1 downto 0 do) m$ s, }5 o' L* U
TFooClass(Controls).Font.Size :=! A7 M( y- q# a, L
(NewFormWidth div OldFormWidth) *
3 r4 m. I/ N) q; S$ n6 gTFooClass(Controls).Font.Size;7 B1 O6 M0 V, D8 l! T# F4 z- i
end;' L$ M& \; |: v& b6 o
3 y% Y6 l, q- C' g7 v
用raise引发一个错误处理例程; j- ~% m3 O+ {. y. A/ }
示例:先给出下面的定义0 @* w8 c, Y. {0 Z/ D* W; e
type EPasswordInvalid=class(Exception);
5 G. H, W& N8 S8 ?! N, D这样你就可以随时引发一个”password invalid”的例外:3 ]  Q/ {- C, \2 u- P
if Password<>CorrectPassword then2 ]9 l' E8 h  f. A
raise EPasswordInvalid.Create(‘Increect Password entered’);) D3 e$ t9 P- G. N- P
运行后,出现信息框( {7 L( d% i4 N; Z1 h; G. g7 e4 b8 z
Project Project1.exe raise exception class EPasswordInvalid
6 `) b, U, a6 K0 H$ nwith message ‘Incorrect Password entered’. Process stopped.
" Q2 w* o* J- J, t  V& GUse step or run to continue.1 x% S& i6 ~+ K/ K; x/ I9 O
再按Run按钮,出现一个信息框:
/ V) b9 e, g- g" bIncorrect Password entered.
2 v1 W: d  i# D7 Q) j  D5 Z0 H5 T3 a& g/ ?8 T* ^) u: p
' s! k6 k8 q: J* N  W; S
从DEMO例程中学到的若干小技巧
$ W0 f4 f% T" b; j6 C5 s1 I在demo\internet\http\webbrows\main.pas中,
& W/ M$ b0 Q( fprocedure TForm1.DocumentSourceClick(Sender:Tobject);1 i( A5 f/ x& ~* |- ^- B. S0 G
begin- v* w# I9 b/ ]$ |6 L  G
with DocSourceForm do/ O+ [, s, c2 ^; c& d4 e9 Z4 Q
begin
0 ?$ |5 f2 X4 R3 ]. b& Fshow; // 显示HTML源码的FORM( H" r4 Y4 r* F
Memo1.lines.clear; // 清空memo1中内容
) H% Q" N& h; w7 w3 w- O& EMemo1.lines.add(HTML1.SourceText); // 植入源码
. P0 Z" h& C* Z& {Memo1.SelStart:=0 // ***
# E1 ^' Q& u# M: zSendMessage(Memo1.Handle, // Memo1的窗口句柄
5 [7 y! K: b& k/ k# WEM_ScrollCaret //将Edit Control中的caret光标滚动到视野中6 F& Z) t8 _* m
0,0 //这两个参数暂不使用
6 W8 D& D: [) @  I- L! zend;" |0 P. z8 R4 |
end;' f% t; y" f  J6 v
(此SendMessage系一WinAPI调用,给一个或一组窗口发送消息,直到- U5 G& `  Q. d% S
相应窗口处理此消息后才有返回值。相似的另一函数为PostMessage,- t0 l9 U# z  v- b3 G
它将消息放入消息队列中后立即返回。)/ {$ o# M/ X) c, d  c: B  t, P
*** 清空当前选择并将光标移动到指定字符(0代表第一个字符)。如同时% x6 @4 U/ t6 O: r7 W
设memo1.sellength为一非0值,可选择一段文本。
4 P& Z0 }; z5 a' _( _) G) U
. O' i, k- n/ V  }$ j6 H0 g' e
' |& w( S5 w% ]8 i( l( }奇怪的I/O error — 我在开发过程中发现下面这两条语句3 a' O* V+ P; [) p5 ~+ N
assignfile(fDesc,CDDatadir+describefile);
+ i! [5 m3 u9 x- ~4 [2 \' _reset(fDesc); # p, _2 z5 k8 t8 K  B8 p% _
每当我第一次运行到这里时,总会出现 I/O Error 183 的错误.# _4 w" c$ \9 U2 A+ k
最后我想这也有可能是没有清除 ioresult 的原因.在两句之间加入
- o, f" Q8 c: u  ]& \/ a6 R$ ^if ioresult<>0" ]9 O# k" E  I% q" t( L& G7 i8 @8 O$ ?& B
then; , Q" K& n1 ^# f$ k2 X( ]
oooook! 可以了.1 j3 k+ Z, i& j0 s

0 F" E2 W& E7 i/ V4 M
2 a% z3 H, s2 W- c, O1 Z1 ^值得注意的I/O error
; {, v" p2 ^7 v8 @% dAssignFile(F, fname);+ D: ~6 m3 Z2 [/ T0 k
Rewrite(F);
4 y( |" y, ]1 z4 e+ i, Z$ H. \当文件 F 经 Reset(F)打开的情况下, Rewrite(F)会引发一个异常: I/O error 32) J' B$ U+ p( Z- \
反之,经 Rewrite(F)打开, Reset(F)也会引发同一个异常.* m$ u* i) K6 u- u, I4 f
Reset(F)两次,closefile(F),再Rewrite(F),或反之,也会引发同样异常.
4 k( o# P+ U. _9 D& V* r
5 a7 `. m2 \7 J9 h/ t
$ V  N8 g) w% h$ O4 D8 c+ ?
( I5 W8 c# f! m, X+ E9 dstring和pchar的相互转换:( `% p  ~# l4 x' D2 }- x) Q% ?1 N
string –> pchar: pchar(s
6 v3 o# U, k5 t* K' a: ctr:string);
0 R* d* \# Q8 s& mpchar –> string: strpas(p:pchar);
+ l' U/ |/ O9 h8 C  C7 o0 o
( g* J  _" I  r; [2 L6 \3 U, a: ~* e2 k- }1 @

5 F( v4 q, z4 U+ R4 \! r在Delphi代码中定义数据库8 ?! ~* M9 P7 I$ n5 ]+ u  ], r. f" p
procedure tform1.create_tbl;8 x8 ]4 L8 q. M$ Q8 E4 }
var tbl:ttable;
/ ]) H" p2 p8 o% lbegin3 P4 z& _" Y3 K; O( `3 @8 Q
tbl:=ttable.create(self); // 如没有声明中的”tform1.”,Delphi不认这个self
  B" X) Z" P8 J) C0 G& `4 G0 ]with tbl do
$ g: B  M( Q' V3 [# _+ K- _begin
+ g6 U- I6 @' }0 k: jdatebasename:=;dbdemos’;
; _& c1 D( g. {# Itablename:=’my_tbl’;
- g& h% {- o/ E: j" c! Qwith fielddefs do7 T, E; E4 i% V( i+ V
begin
  H3 d0 W) O, ~4 |clear;4 J  U1 L; v, I% ?, e
add(‘No’,ftInteger,0,false);
  b6 b+ `( p6 }" g5 s" g% oadd(‘Name’,ftString,0,false);
/ \/ T, \7 j1 c…
! n, X" u! A  Z  V5 f: q5 ?" ~end;
$ H- o0 q& }' r) C1 G* T" fwith indexdefs do
( {( S3 ?- |: s: i) n1 N% n& `begin
7 v" a$ X+ o. I/ W2 M+ kclear;+ E; v& c+ y! p& _5 K' ]( l- A
add(‘primary’,'no’,[ixPrimary,ixUnique]);
) J, X9 G, u" [" J- ]& w6 U( S…2 \" k. Y# O' v0 M2 U8 J
end;1 X1 g. r: @* a( P, j5 b
CreateTable;' L7 T3 R4 f$ B9 F5 D
end;* U* P$ x) \6 D
end;
# Q" o- y3 @( x  w  n
$ ], h3 Y% D+ S9 W1 }0 E  ?  u2 k' F; h2 c, r
string、TStrings、pchar的相互转换(这里是我的个人经验)( R3 C/ x- ?$ V& Y" ^5 o' N
假设有如下定义:* Q* l& ?. n. S
var
/ y  w6 |1 i# qp:pchar;, |, F; C3 Y! _* _
s:string;) C! ~" t7 X2 R
ss:tstrings;; h% d; N* E4 e: V- f
begin8 e7 h( _6 J( m! ^
ss:=tstringlist.create; // 开始时一定不要忘记创建ss+ G- B: @$ }9 z8 Q7 g  O& K
ss.text:=s; // string –> tstrings
0 }% i7 o, d4 M; r4 b) Vs:=ss.text; // tstrings –> string" Z) r3 V: f  |) |% X/ ^. G( _' Y
p:=pchar(s); // string –> pchar1 l. e# k! w4 k* |6 c: K
s:=p; // pchar –> string5 |; I3 D% j& }2 {
showmessage(s); // 合法语句/ m, w5 Q* e# ?9 L
showmessage(p); // 合法语句# p% W% r8 @/ p; l6 D
… …9 o5 D$ G! G9 V" }9 ^
ss.free; // 最后还要记着释放ss占用的资源
) t/ O5 W- a0 t8 Send;, c3 y: x8 w/ U5 N. u

9 ?4 N2 J0 @) j% P! ~
# D3 s4 _8 P6 O
3 L0 L4 E2 }0 f4 B在设计Menu时,常用的ShortCut可从下拉菜单中选取。但我发现可选的ShortCut有些不在列表中,如ESC,Ctrl-Shift-A等。我试着在ShortCut项的右边输入:ESC,竟然成功了。再试Ctrl-Shift-A,这回Delphi自动把它变为Shift-Ctrl-A

TOP

發新話題