打印

delphi 技巧合輯

delphi 技巧合輯

INI文件的操作要点1 T1 B& ~, w, n: A. I
(1)在interface关键字后的uses子句中加入
& n6 ~" Z$ B6 R! n0 v0 j7 {4 |4 h/ fuses …,inifiles;; A* b4 G. l5 F3 S3 b" V7 F* z
(2)设置变量:var inifile:=TIniFile;
& Q5 c7 Q$ l9 `3 W5 E(3)使用前,一定要先做:7 }% @) Y, Q  L4 u5 Q1 O+ B" f
inifile:=TIniFile.Create(inifilename);6 ?; ^, s% b/ W& t) ~
我在这里绕了个弯子,写成0 I6 t- o* a: I. `* Z
inifile.Create(inifilename);! t1 `( [' |  |8 w" |( V  p

$ _0 z$ V4 b2 T9 b9 V2 W' L9 \TShiftState用来检测CTRL,ALT,Shift,以及鼠标按键的状态,1 a  M: p1 i& k
常常用在键盘或鼠标的事件处理程序之中。1 C) G3 ~  c- b& _! _( q. B
: X) z, ?; b, @6 H. i3 V7 _0 S
DCU文件(编译的库单元)的重用
0 ^; Q4 C* O2 R* v) s' X(1)在interface里的uses子句中引用。如Windows,Dialogs,' [2 ?( u: g0 c- @) ]$ z, d
等等,要求被引用的DCU一定要放在Delphi 3\Lib子目录中。5 R3 B* j* g1 c% Y  ?2 X2 k- [
(2)在implementation里的uses子句中引用。如果是自行编写的
) D- [6 w, f: D9 M$ J& s! P. p7 ~7 KDCU文件,应采用这一方式,并将被引用的DCU文件放入当前- m' j( H' D6 _$ O& D4 z5 z8 t
工程所在的子目录中。
8 W* m) d! B% @3 A8 [3 Mexecutefile函数(在FmxUtils.DCU中定义)不能用在FormCreate8 H' a6 N% m/ ~) m2 a- K
事件中。真奇怪……1 X9 ^7 \( j- n9 a

  {) [( }0 X" l4 l内置的版本号控制功能$ R$ j' L0 |& {2 [* G% f. }6 j, A5 R
在Project Options中的VersionInfo项里,有版本信息的定制,7 G0 K# n$ i, ?
包括一个有趣的版本号自动增加功能(Auto-increment build& O0 V. {4 r  j" E
number),即每Build一次,版本号中的Build Number加1。选中1 Q3 ^* ?! r! u4 k2 \
Include version information in project,编译,用资源管
* d, E) i+ x7 d! H) ?% ^理器里找到生成的.exe文件,点右键,查看“属性”一项,就
& F. |( e8 R' i会看到在属性中多了一页“版本”,里面就是你刚才输入的各4 H$ [. N; A: b* S
项内容。6 n4 n; S% N/ m# }$ E- m

6 R# o% f" o* o9 a1 H' P: [) A0 S# t
定制Speedbar$ l' p2 e& V8 A8 r0 [; ^  _
右键点击左上角的加速键条(speedbar),选中Properties,; p+ \. [" ?# i: s1 [
在列表框中找到你想要加入speedbar的命令按钮,将它拖到0 b, T! C. x9 x* d- @5 F9 a" S4 }
speedbar上的合适位置即可。如果speedbar上没有多余的空间
2 M' ^6 U2 I& J3 [  z2 N来容纳新的按钮,可把鼠标在speedbar右框处变为双向箭头的* q0 i5 s3 k+ k0 p9 _0 @2 N
形状,向右拖动一段距离,就可腾出空间。如想删除speedbar
8 I: U3 k% k1 B5 A上的某个按钮,可简单地把它拖出speedbar的范围,就能删除。$ p# Z+ B% c' J( C& L
& R- }4 v, ]6 k5 m, y: c3 f

4 ^7 P' T9 \. M$ x# ]! x计算出的字段. U7 R9 a6 _& D/ A2 r3 _1 c1 }
在写一个程序时,我要在DBGrid中显示出一个memo的部分信息,当我把那个
* I" J0 Y: j. h- O, L' V; i1 G; Rmemo字段放进去后,运行时只能显示出“(memo)”字样。从书上找到计算字  Z) @4 @( I0 i2 g7 j& |4 S
段的用法后,我在TTable中增加一个计算字段MemoHeader,宽度为40,在此
: ], T0 O6 [  n1 lTTable的OnCalcFields事件中输入:) e! m: ]! d  }* Z: v& O$ U+ B& S
with MyTable do
  C; d- x4 U7 F7 nFieldByName(‘memoheader’).asstring:=FieldByName(‘memo’).asstring;
+ s1 c5 {$ q+ g( b% a; K. r在DBGrid中放入MemoHeader,运行,OK!
3 V& S/ r  _2 l/ H, n6 t
* S4 h1 q2 Z' [; t  \; l( W& g$ j, W) v' O: F/ \% k
字段编辑器$ r. g3 r+ O. e
解决了上面的问题后,我继续学习字段编辑器的作用。原来,DELPHI通过字* r0 V! L  x& t4 \: W3 @$ Q0 V+ X
段编辑器,近乎完美地实现了数据库的字段级的控制,这包括:8 G8 t: g3 G# [( ?/ c
1)字段在DBGrid中标题、宽度、能否可见;
! N3 c/ p% ^: t! v0 Q* [8 c2)字段的显示格式和编辑时输入的过滤条件;* Q( Y1 h! r5 o  ?* w
3)字段是否只读;" ?. E, o, L; V7 h2 _
4)字段的类型:数据字段/计算字段/查询字段/内部计算字段;# t' j- z' R( [' m( ?5 C2 M, ]$ l- C
5)字段的显示/赋值/修改等事件的定制。
: r! o  Q2 X$ S% ?8 `* ^; r  |
- f) _0 A! J8 z+ u$ e6 i" D/ v6 i
4 E  s( s' K  @1 ^+ H+ @设计Form时的快捷键
) o! ?) ?5 y) A8 J6 O6 u) bDel 删除所选组件
, n2 e/ s0 k5 e" }+ C; _3 \7 n* iEsc 选择当前组件的容器(通常是Panel,Group或Form)
$ Z% u' H5 p- J4 R, ~: VF11 在Form或Unit和对象检查器之间切换& y0 J8 o" o- o+ d
F12 在Form和代码编辑器间切换
* \* g, {) b" i, d& v3 NCtrl-F12 显示“查看Unit”对话框. [8 L/ z* t- q- E' h) e. a
Shift-F12 显示“查看Form”对话框
2 I3 l/ C  {1 m. G4 \TAB 下一个组件8 M9 r' `2 r( C5 c6 G" X, G/ u9 |
Shift-TAB 上一个组件
# R8 q3 ?. A+ t方向键 选中此方向上最近的组件9 p% b( A! x) ^9 y0 z
Ctrl-方向键 将所选组件移动一个点
/ B5 B/ a" w( x: W8 \Shift-方向键 将所选组件改变一个点的大小
/ n1 y4 D: ]0 x# pCtrl-Shift-方向键 将所选组件移动一个格% S- Q- H4 m) `
Shift-click 按住Shift键再用鼠标点击组件,可以选择多个组件。' z* a# {/ B1 M6 x
–= 下面这条是我摸索出来的 =–
, m) m! w- E8 @, j, @% u" oCtrl-drag 按住Ctrl键在一个容器组件(如Panel,QReport,Groupbox等)5 [# Z1 s9 i1 [6 q: I: l
里拖动鼠标,可强制选择鼠标拖过的矩形框中的所有属于此容) d) L1 R/ Q6 O6 o) k& G* }5 {2 W
器的可视组件但不包括该容器组件。2 ]3 q7 b  J. D3 e$ ]8 O9 e5 R

: `0 d5 j" c$ s$ T$ `& T' {
. q5 B* P& n+ G- ^! P+ _1 h使用QReport的若干经验
9 A, x$ g* J: u0 ?% A3 `  L1)QuickRep1.DataSet:=query1
& E* d+ L- v0 o$ I& m! G不然无输出结果
# T/ t3 ?" U5 [; H  ?" M0 f* Y2)从qrpt2man.doc中查知,格式化输出结果的方法是:- t: A/ h: a4 b5 A( r1 y
在QRDBText.Mask中设为.00;0,将使输出带两位小数。; _6 b+ K2 X0 E% R! L
3)设置Group时,先加入一个QGroup,再加入一个QRBand,将QGroup的
) E4 J6 ?' s  W8 r5 H# i+ yFooterBand设为刚才的QRBand,就可将其联系起来。. h6 n' T: T# @+ J9 `( Y  H; ?
4)在Group中打印的合计数,其ResetAfterPrint设为True,可实现分组合
8 C5 b$ w4 c: V# f; ?( Y% L$ K* R3 d+ h
format(‘%*.*f’,[8,2,123.456]); //等价于format(‘%*8.2f’,[123.456]), h9 {$ Z& @  ]
format(‘%d %d %0:d %d’[10,20]);$ r2 P! H) m" b" o- r. p

3 i1 [5 g8 P; P8 n, J. ]" b2 B  x" ]6 v" i) J
: g  m6 l8 i* p! E1 f
播放一个wav文件" c$ j& r2 I- T7 X- E0 K/ y+ n
use mmsystem;
, }* i8 `& e7 t) ]" C; uSndPlaySound(‘hello.wav’,SND_FILENAME or SND_SYNC)" Q# U" k) U7 f; \' C4 r
6 c* I+ [( o, Y8 _0 A& S# X4 y
使你的form适应不同的显示分辨率
* d- m% B: q8 o( [2 h1 l假设你在800*600的分辨率下设计的form,第一步:8 @' B6 @0 T. ]. \. M$ t7 g8 W
inplementation
7 h, k7 F* _$ o# Y! H$ ]4 r1 bconst
! g" _+ `7 }& ^. m0 A+ jScreenWidth: LongInt = 800; {I designed my form in 800×600 mode.}* G: y& h' T8 K
ScreenHeight: LongInt = 600;5 J/ b5 {. @* I8 l% q. s9 x, T- o5 P
& g8 p' B. @1 _9 K2 x- v
{$R *.DFM}1 s& z7 P, _( K) v$ e) B

2 i" A  R) t% v  Kprocedure TForm1.FormCreate(Sender: TObject);
% K  }3 u7 i8 N( V! l5 X7 xbegin4 C) n; W$ F  J$ o. w2 t1 @
scaled := true;" s" G/ z2 Y) L5 O  C  l1 O+ p% s
if (screen.width <> ScreenWidth) then
  F  o% r" g  w# A( Rbegin
0 M8 V  a. J0 ]1 H- H$ qheight := longint(height) * longint(screen.height) div ScreenHeight;
6 x' R. ~2 Q+ C: o6 Qwidth := longint(width) * longint(screen.width) div ScreenWidth;6 |& N& m& T2 \& J2 f% y& i( M
scaleBy(screen.width, ScreenWidth);
3 g+ V! w2 R* {( o+ v7 B/ cend;
- ^. o: K+ q- d& H, P0 C# @end;
. t( n! e( ^& e9 j
( s" _4 j. Z' N# B+ ^下一步,要让每个子控制的字体改变到合适的大小:) i$ p1 Q% o2 e- S
type
! z+ N  t- }4 ~  }3 V, z: o! w/ RTFooClass = class(TControl); { needed to get at protected }
( I2 P" h5 g. H  c. F7 Q5 r$ D6 H{ font property }
3 i& X( l4 |: m. {
* S* f0 X3 }. `0 C, h( V5 S2 b; nvar
. C$ u* b. q5 k- V* B$ z+ [i: integer;
- x; ^  j$ w" u: B0 q" gbegin
6 q! w2 `+ n3 c1 dfor i := ControlCount – 1 downto 0 do
: J8 z& C7 {4 J# A# NTFooClass(Controls).Font.Size :=# c+ T/ M3 t' p/ l1 Z( Y* A  K
(NewFormWidth div OldFormWidth) *
  ~5 Z) c) h# m2 TTFooClass(Controls).Font.Size;
; f) @% n0 M+ }( u; T# Tend;
4 T9 G2 y& J2 C. R# f7 k* g( [- |# b: h3 c
用raise引发一个错误处理例程/ j5 B/ k& J! |2 C% _4 t& ~! V
示例:先给出下面的定义. x2 \1 R. h" }# C/ D
type EPasswordInvalid=class(Exception);
$ {$ l& a( w. ?  t这样你就可以随时引发一个”password invalid”的例外:
/ W# |+ [# b/ T- G! dif Password<>CorrectPassword then  V& D* g/ b4 T. N( ~; q4 F
raise EPasswordInvalid.Create(‘Increect Password entered’);3 z* q- L) j, m  U! A
运行后,出现信息框
( `1 p5 t2 w  g/ b8 KProject Project1.exe raise exception class EPasswordInvalid
; q0 {- {8 P) o! Mwith message ‘Incorrect Password entered’. Process stopped.' {9 C/ N" i" p9 h4 N0 K
Use step or run to continue.) H5 B, ?" b2 O+ z+ v$ U8 p  g
再按Run按钮,出现一个信息框:
; Z0 U3 L! s6 d7 |+ D5 _& MIncorrect Password entered.
- v5 s* M" b! c; B
7 U; t' P* H$ R  M1 J
9 e' R: T  q: ?  @从DEMO例程中学到的若干小技巧
6 K' w. ~( s" ?4 H在demo\internet\http\webbrows\main.pas中,% `& j8 u0 e/ Q+ j6 w
procedure TForm1.DocumentSourceClick(Sender:Tobject);7 Y% |) l9 x4 j" \' l% J  \
begin
" n* i2 L# F' i/ ^4 A: Ywith DocSourceForm do
/ j( ]  y5 U& D% M5 }begin+ N( v* `; k4 Y; m( v9 F
show; // 显示HTML源码的FORM
/ H; Y) ^9 P6 u: wMemo1.lines.clear; // 清空memo1中内容# M( A, l, {9 A0 O3 W2 K
Memo1.lines.add(HTML1.SourceText); // 植入源码( a5 Q$ B6 U' [* ^' j# h+ ^
Memo1.SelStart:=0 // ***$ h( M/ X. H8 L" a0 o, `
SendMessage(Memo1.Handle, // Memo1的窗口句柄
, F- I0 `0 `' a" rEM_ScrollCaret //将Edit Control中的caret光标滚动到视野中
& ^& E3 h7 _' J  n# d0,0 //这两个参数暂不使用; [. [' _8 d5 p
end;
6 I- U5 [9 s0 o, Aend;6 a. W5 `8 Y5 A
(此SendMessage系一WinAPI调用,给一个或一组窗口发送消息,直到. ]8 }" {/ j- V5 C' k- g
相应窗口处理此消息后才有返回值。相似的另一函数为PostMessage,
7 @, f- y6 h+ R+ {# y. L它将消息放入消息队列中后立即返回。)
3 O7 m3 r6 Q; |2 O; R*** 清空当前选择并将光标移动到指定字符(0代表第一个字符)。如同时
3 ~" h! K" q  N+ S; d2 T% G8 {3 r设memo1.sellength为一非0值,可选择一段文本。9 w6 r7 a  G6 ]5 W; Q& ^
7 G3 U0 O# M' U: S- z

6 _; ?2 P1 y& x; D* [* V( Z0 r奇怪的I/O error — 我在开发过程中发现下面这两条语句
! R4 c4 A+ n8 N1 yassignfile(fDesc,CDDatadir+describefile);
7 `- N1 L3 o% X# K# Rreset(fDesc);   C  X# y, N" [
每当我第一次运行到这里时,总会出现 I/O Error 183 的错误.$ q6 J$ z. A. T3 q1 r: l" Z$ f9 `
最后我想这也有可能是没有清除 ioresult 的原因.在两句之间加入
- u. \* i2 w2 u: V9 `6 Sif ioresult<>0: j- N  {. F( q, O: M: O! ^
then; + ~9 v6 d0 M9 g) a; X: K# B* @: U
oooook! 可以了.
& |+ s# q; c) H& R$ Q% C+ H
" x) r' j3 x7 P0 g2 U' k! A" l, s/ c. ?: r' S. f. W6 d$ q
值得注意的I/O error3 i  g- f; F' m
AssignFile(F, fname);
# }9 g9 }3 x0 k9 e1 N' H1 q6 FRewrite(F);$ c1 Y, m/ _3 n6 c, {" n0 @2 n
当文件 F 经 Reset(F)打开的情况下, Rewrite(F)会引发一个异常: I/O error 32
" u1 a% k$ b$ ]反之,经 Rewrite(F)打开, Reset(F)也会引发同一个异常.2 l" s8 a5 R' G+ J: c
Reset(F)两次,closefile(F),再Rewrite(F),或反之,也会引发同样异常.+ c3 Z: U4 h7 p0 e
; Y. G! {1 W6 `

2 }$ |& f9 Q# T) ~0 |; i7 {0 H0 F  Z7 u4 ?$ i* l9 S/ ]
string和pchar的相互转换:. h; V# o) W6 D/ a3 r: C
string –> pchar: pchar(s
+ A* P$ K+ x9 X" Z; e/ v0 S: ^tr:string);
# G# T4 z# m6 Q0 q$ ppchar –> string: strpas(p:pchar);+ P( t, v" a& D: [2 x
. ]4 p8 N  H+ D; R4 F. k

4 D7 k( u" r: f7 n5 B6 C. l( G7 e! Y
在Delphi代码中定义数据库
$ a) V: P2 |1 gprocedure tform1.create_tbl;
$ p+ |6 w/ w$ Rvar tbl:ttable;
  F2 C" i3 a0 [4 }begin6 d9 T* Y6 n2 Q) H0 G
tbl:=ttable.create(self); // 如没有声明中的”tform1.”,Delphi不认这个self# T+ f# S8 d  w6 B' D
with tbl do9 `# H) q6 F% r' ?7 O
begin- T; k- j) X7 \" d' q) H
datebasename:=;dbdemos’;
* b2 c3 d/ P: e' utablename:=’my_tbl’;) C) I4 k% o  j8 l% c) v. G
with fielddefs do0 \5 @9 b; J2 i& V! u% R0 u. y
begin$ a# y% |: Z4 R9 Z7 h3 U
clear;& L. }7 i2 o' s: @* |: D: [/ V
add(‘No’,ftInteger,0,false);
/ l- i+ H, i; W! }add(‘Name’,ftString,0,false);
/ e  H; o* B. p" Y5 G# ]8 k+ p% \$ y7 Y9 v6 D+ o3 t
end;
6 |: U2 R% a3 v9 c8 [with indexdefs do
: K& Y# V+ p4 t7 I: ~5 V& Ebegin
1 s$ B5 L9 z& q  \clear;' {. ~7 w  z# b; _+ c/ H
add(‘primary’,'no’,[ixPrimary,ixUnique]);! _& I& h# c9 Z  u2 ^
0 P5 S. C% a6 T
end;7 h2 |7 r# t: A7 J9 t( }7 o3 k: a
CreateTable;' ~" i' e6 T$ c9 }
end;1 a& _2 e# u, W* X5 [/ E
end;9 T& p% L4 D5 {6 }

9 L( U9 a$ `8 e" F, D9 x+ o+ u  M% Q* \2 {2 F
string、TStrings、pchar的相互转换(这里是我的个人经验)) `  _8 \: \, g7 b* r$ Z6 Y; z% Q
假设有如下定义:
7 Y0 a  ?( z. b% _/ U) Fvar
( e, V$ Q: y2 Q, Hp:pchar;# _0 j0 S* q" ?9 a
s:string;
, c5 y" y( X* Z8 _ss:tstrings;) @4 L% F- Z3 w6 c: B
begin
- \/ r6 b0 a' b0 qss:=tstringlist.create; // 开始时一定不要忘记创建ss
5 u& e& [  M/ Z/ h6 y* vss.text:=s; // string –> tstrings
2 P2 R3 W; H- W: d0 S& is:=ss.text; // tstrings –> string2 `% R4 f' @' P/ S
p:=pchar(s); // string –> pchar2 y+ l: Z7 [8 Q  g+ i2 P6 O
s:=p; // pchar –> string! m& z( l5 k; V* \& Y+ a( c
showmessage(s); // 合法语句
( j6 g/ R/ X. P! L) _showmessage(p); // 合法语句/ j' Y: V3 G* B) r
… …
2 n" S! J6 y8 T* k/ @ss.free; // 最后还要记着释放ss占用的资源
0 b, }/ S, \9 D  Jend;
1 \( J# P( w& _4 _/ ]" F# o( g6 D- Y# e0 |/ j

8 p" v9 g# W( m
- W% s- ~# g8 [7 c" }在设计Menu时,常用的ShortCut可从下拉菜单中选取。但我发现可选的ShortCut有些不在列表中,如ESC,Ctrl-Shift-A等。我试着在ShortCut项的右边输入:ESC,竟然成功了。再试Ctrl-Shift-A,这回Delphi自动把它变为Shift-Ctrl-A

TOP

發新話題