打印

delphi 技巧合輯

delphi 技巧合輯

INI文件的操作要点
$ m$ e8 V- H" t' N* Q(1)在interface关键字后的uses子句中加入4 ~9 r. y, ^7 j0 W) c0 a
uses …,inifiles;
0 d- z& a6 ]3 M6 y7 }(2)设置变量:var inifile:=TIniFile;
2 q' {* s" p/ V& B; f# y! U(3)使用前,一定要先做:5 d* L0 E+ P( J2 [. d
inifile:=TIniFile.Create(inifilename);
  W. K$ w- t  P我在这里绕了个弯子,写成
* o( p: b/ [6 P( r* g$ w6 q8 dinifile.Create(inifilename);
7 j/ i* Z. T% c( \3 l- [! o$ d% Z, F$ k" u2 F  Y2 n8 V2 f2 N! G" {1 Q
TShiftState用来检测CTRL,ALT,Shift,以及鼠标按键的状态,
. }" ~; j$ ?7 y* d6 a常常用在键盘或鼠标的事件处理程序之中。
  K" t* B1 f) c5 X2 C% i" C- E8 @- j* Q3 \( [4 [, ?0 }4 [& L+ F
DCU文件(编译的库单元)的重用
0 A8 A" p9 m- q: l, w- |(1)在interface里的uses子句中引用。如Windows,Dialogs,) F, p; \9 F9 M9 q5 A
等等,要求被引用的DCU一定要放在Delphi 3\Lib子目录中。
& }/ o; \0 U# p% o/ `(2)在implementation里的uses子句中引用。如果是自行编写的
! f9 b; u/ b8 x( {DCU文件,应采用这一方式,并将被引用的DCU文件放入当前
+ E$ g) ]" R  C% O$ D: m  n, C4 @工程所在的子目录中。4 g" y; W, C0 a% W1 w( ]
executefile函数(在FmxUtils.DCU中定义)不能用在FormCreate
( v1 S+ n! ]' x# {5 C8 z4 U* s事件中。真奇怪……
% o% `! g" I7 P4 I. f5 c8 J6 j
: [0 C# t4 O* O4 t+ l3 W# p0 U5 y内置的版本号控制功能
, }, f/ J6 [8 A+ d# x; c2 z; a6 p在Project Options中的VersionInfo项里,有版本信息的定制,* I0 |7 J# x- b# W
包括一个有趣的版本号自动增加功能(Auto-increment build
  L0 W; l# H3 c  }0 D! ?number),即每Build一次,版本号中的Build Number加1。选中. `& c" r& T. o% ]
Include version information in project,编译,用资源管2 c: ?: @/ F6 D2 n. e
理器里找到生成的.exe文件,点右键,查看“属性”一项,就' @; D" Q7 S( ]
会看到在属性中多了一页“版本”,里面就是你刚才输入的各
9 U  p' I: `7 e! u: t2 A1 j9 ]项内容。0 c, f$ i. }& G1 h. x5 M1 q- }
* T/ j; E" y' N" N( I. ]
" c  _! T6 ?, E$ X5 z
定制Speedbar4 ]2 o# I# }& u2 y+ ~
右键点击左上角的加速键条(speedbar),选中Properties,
3 ?$ p( t: C9 Y在列表框中找到你想要加入speedbar的命令按钮,将它拖到5 @+ b& c- x2 N# K# x
speedbar上的合适位置即可。如果speedbar上没有多余的空间$ H4 H3 K* h" e0 o# u" N
来容纳新的按钮,可把鼠标在speedbar右框处变为双向箭头的- Z  D6 k$ f$ M! K( q/ T. x/ h
形状,向右拖动一段距离,就可腾出空间。如想删除speedbar+ J5 ?: G9 Q+ P$ p5 r; T
上的某个按钮,可简单地把它拖出speedbar的范围,就能删除。& H  X# Y7 J" b9 }

( D* m8 }- C  |, r* f% ~4 f3 s5 t. i; c' Y' R# `1 y
计算出的字段9 j4 |3 X: f0 T+ R  r* G
在写一个程序时,我要在DBGrid中显示出一个memo的部分信息,当我把那个9 u( b6 j) Q% l5 C4 b  C
memo字段放进去后,运行时只能显示出“(memo)”字样。从书上找到计算字
# @( t9 g: z+ t& A4 i段的用法后,我在TTable中增加一个计算字段MemoHeader,宽度为40,在此2 D: J* n. }' I3 a7 M# G
TTable的OnCalcFields事件中输入:4 ^) S4 ^$ I( o9 t0 I- \  e
with MyTable do
3 W; B+ T+ Y* S9 U7 VFieldByName(‘memoheader’).asstring:=FieldByName(‘memo’).asstring;! |+ m0 W* |' T1 R9 S
在DBGrid中放入MemoHeader,运行,OK!- Z* K; b1 _2 k  x& f4 _! _- q! J

& c$ [: s, h; d8 C. ^  N" r- i5 D1 o# g7 V$ a
字段编辑器
3 k. e0 A9 ]3 E% z" s7 A解决了上面的问题后,我继续学习字段编辑器的作用。原来,DELPHI通过字, J7 P9 {1 i' L
段编辑器,近乎完美地实现了数据库的字段级的控制,这包括:
  T, l, u  Q: n: N3 C+ K1)字段在DBGrid中标题、宽度、能否可见;4 G* B/ ~" G3 r7 t
2)字段的显示格式和编辑时输入的过滤条件;
- M  x& k# j' M+ ^5 `% R, d2 K3)字段是否只读;
! K7 m% o3 R/ D* e) W4)字段的类型:数据字段/计算字段/查询字段/内部计算字段;6 G% ^4 j9 n2 F% l* ^
5)字段的显示/赋值/修改等事件的定制。
& r9 `- ?* @" w  @% `3 I% K: z& A' J6 d: Q$ S* @

5 J! p% V! L6 v0 o( k设计Form时的快捷键
- n% K! z! H3 NDel 删除所选组件9 w1 I& U4 f$ @* K" z9 k7 ?7 M; B/ D
Esc 选择当前组件的容器(通常是Panel,Group或Form)
6 F( E* ^; v. c- i4 ^F11 在Form或Unit和对象检查器之间切换/ P+ \9 u- G3 l+ ~( ^5 ^
F12 在Form和代码编辑器间切换8 F! n4 v( l$ R, S
Ctrl-F12 显示“查看Unit”对话框
; Q1 e! Z2 _! I3 v0 yShift-F12 显示“查看Form”对话框
8 S6 h( T) x+ X1 l# N$ hTAB 下一个组件8 Q' A4 l- I6 {8 }7 M
Shift-TAB 上一个组件
! w) r6 p: q! J" b0 M  \# x方向键 选中此方向上最近的组件3 C# K; R/ @' p& F
Ctrl-方向键 将所选组件移动一个点% V; Q8 c+ @. d! l+ G. b
Shift-方向键 将所选组件改变一个点的大小
2 A. ~' ]# U/ t! k& R0 I( Y, e# B) ]Ctrl-Shift-方向键 将所选组件移动一个格! h( L8 [7 ^! J" q! Y. r9 A
Shift-click 按住Shift键再用鼠标点击组件,可以选择多个组件。
0 L* w$ O7 @+ R) K. M: ?–= 下面这条是我摸索出来的 =–
3 a# M  b9 ?$ DCtrl-drag 按住Ctrl键在一个容器组件(如Panel,QReport,Groupbox等)& O7 K% _5 b8 h+ K# o9 y/ d
里拖动鼠标,可强制选择鼠标拖过的矩形框中的所有属于此容
1 O- y! K4 p9 R0 E2 J( s器的可视组件但不包括该容器组件。
& `) r; c, U# z& d* D4 L
. p- Q+ i$ b* `* G# Z; i: c, q2 f
0 |& R* J# P* u% @4 x) I- m使用QReport的若干经验
" A1 j# ]5 T1 v1 o* G  g4 V1)QuickRep1.DataSet:=query1
1 ]4 C) ]5 O& y5 g8 L不然无输出结果
0 V+ c0 O! @: M2 Y2)从qrpt2man.doc中查知,格式化输出结果的方法是:
8 l* I' s+ ^- d( \( x在QRDBText.Mask中设为.00;0,将使输出带两位小数。+ n+ g8 d& d1 W" j/ ^  a
3)设置Group时,先加入一个QGroup,再加入一个QRBand,将QGroup的
0 b2 @3 l0 W) `6 Y* S0 A0 t6 G6 }FooterBand设为刚才的QRBand,就可将其联系起来。
9 S1 S4 {2 r: ]5 C. D4)在Group中打印的合计数,其ResetAfterPrint设为True,可实现分组合
8 V7 c7 A- K4 _: @! o# x) o/ J. U2 S! T( J# e& O7 K7 `
format(‘%*.*f’,[8,2,123.456]); //等价于format(‘%*8.2f’,[123.456]). X# r$ a' ?; i- e0 S
format(‘%d %d %0:d %d’[10,20]);7 ~8 N% j0 [) _* T9 g
5 r, V2 a5 q8 q8 t

% q1 T) s& R! C; y' u/ H; I) J8 W" J; ?
播放一个wav文件) e% |+ q  B" n4 F: q: |
use mmsystem;
2 @1 e6 n, ~: ~+ H5 VSndPlaySound(‘hello.wav’,SND_FILENAME or SND_SYNC)
; ^" [) _/ h7 u  j* e; H; x4 M- E# G9 |" @: H. o
使你的form适应不同的显示分辨率2 _5 R  Q5 y2 I4 V% ?. k2 f
假设你在800*600的分辨率下设计的form,第一步:
+ c; b: i, L8 s% e/ F& zinplementation/ D) r- r% [( ?9 C' l
const2 f  Y/ P" `0 w# M( q& R" l
ScreenWidth: LongInt = 800; {I designed my form in 800×600 mode.}3 p( P) l7 @6 t& [4 j
ScreenHeight: LongInt = 600;) N" {/ p% a" _8 j& `3 Q3 `

; J2 H; P* d# f. s- O{$R *.DFM}7 B; w& n& \! H' Q  \
& n8 q6 J; R" n, E5 U( H7 d/ o
procedure TForm1.FormCreate(Sender: TObject);: O: j4 }8 _9 G3 V" T7 v
begin" F7 f# o  M9 t: ^
scaled := true;
0 I+ H5 @* r) Z5 U# `! |if (screen.width <> ScreenWidth) then
1 k. ^5 d$ m. D- l5 Y3 Zbegin. m$ s  E! W5 f% K  l
height := longint(height) * longint(screen.height) div ScreenHeight;
; V2 j( F) a* o3 L- C3 p9 ^width := longint(width) * longint(screen.width) div ScreenWidth;
7 Z# \. k' T: j3 n  PscaleBy(screen.width, ScreenWidth);2 r( d6 [$ E$ j$ }
end;
: r% X( ~3 J! b6 C: `* F+ vend;
: U( x. f/ ?3 e( y  [) i( e9 H6 E# ~% d) g, H. J6 |
下一步,要让每个子控制的字体改变到合适的大小:0 [1 G/ K# N4 y
type
5 ?6 w% W$ z( E) f6 l. wTFooClass = class(TControl); { needed to get at protected }
% Q' `' Y% c/ o6 }{ font property }5 O$ B* I5 i! j% f# c- R

( t9 x+ J/ k7 o9 z' svar+ m! J  @% h3 t! h4 ?; h
i: integer;
, `  `- @* z. ^' Ybegin
6 k, p8 o6 Y, F5 C. S$ O; o) \; K+ }for i := ControlCount – 1 downto 0 do
1 C9 Q# z2 E  y. M3 m! j9 oTFooClass(Controls).Font.Size :=
. L. C- p3 p/ o0 [$ N% n& X(NewFormWidth div OldFormWidth) *9 J# V, R! O+ V& c- X  O5 \3 @4 t
TFooClass(Controls).Font.Size;3 l' c! |8 G& I( T1 R# K
end;! q, I2 P  |3 p0 G7 F! [+ j* J/ T
* z& |8 F. n9 W8 Y& j: S' D
用raise引发一个错误处理例程; C' P9 J9 ^2 @
示例:先给出下面的定义8 B& I/ d; k* |
type EPasswordInvalid=class(Exception);, A# Y$ V7 C8 s5 C; L2 C
这样你就可以随时引发一个”password invalid”的例外:
7 R" I( @1 ^. w/ lif Password<>CorrectPassword then
& y- x1 b. r6 i# [& E6 p3 V1 R9 }7 Rraise EPasswordInvalid.Create(‘Increect Password entered’);
( M* F- I; E; ?1 f运行后,出现信息框
: l& O9 @1 q9 _# k+ gProject Project1.exe raise exception class EPasswordInvalid( \" c2 d" h& J4 l# `
with message ‘Incorrect Password entered’. Process stopped.
+ b  \% I+ E3 A4 W+ x4 m( z3 n* m" ^/ N$ RUse step or run to continue., l' ?* Z& o9 k' f4 ?3 p8 \3 W/ t
再按Run按钮,出现一个信息框:, q8 J% F* [6 t, Q  ~4 j1 l0 T0 W, c( a
Incorrect Password entered.! j( z: g. a# A9 E

: u7 [4 Z' N/ u* Q3 ~" z' \% J. \$ @
从DEMO例程中学到的若干小技巧
$ o' p+ M9 |& p, a& c在demo\internet\http\webbrows\main.pas中,
( x- N8 f# F3 _; A0 v$ Yprocedure TForm1.DocumentSourceClick(Sender:Tobject);
: l! M( }  w& g! ]3 L% O  ^/ b- {begin) x; i6 T4 h$ P+ c3 Y  `6 u
with DocSourceForm do
5 ]9 @3 s4 G  j) v" U: obegin7 Y' k$ ]/ h5 @: _7 J5 z
show; // 显示HTML源码的FORM
; P* M# w7 S6 HMemo1.lines.clear; // 清空memo1中内容  x' M: L3 B. z8 X6 p5 ?
Memo1.lines.add(HTML1.SourceText); // 植入源码
1 T0 f3 u3 Y  Z/ Q  N3 TMemo1.SelStart:=0 // ***9 q  e( a: D* r2 e
SendMessage(Memo1.Handle, // Memo1的窗口句柄
" [7 x( |. K, r% Z: }EM_ScrollCaret //将Edit Control中的caret光标滚动到视野中
3 }+ r' L( z  k' Z7 k0,0 //这两个参数暂不使用
$ H+ k6 l" }7 L. D! aend;
. N1 z  h. e* T# }# k; E; F" j6 ^- rend;
6 m: i$ k" J+ L(此SendMessage系一WinAPI调用,给一个或一组窗口发送消息,直到
, t" @) C! `2 S( |" C) K相应窗口处理此消息后才有返回值。相似的另一函数为PostMessage,
, v5 J! R2 L! ]7 h它将消息放入消息队列中后立即返回。)
* ?! g' Y/ \' K. L. i4 U3 W) ^*** 清空当前选择并将光标移动到指定字符(0代表第一个字符)。如同时6 b. v7 w' J/ B. X4 m( S
设memo1.sellength为一非0值,可选择一段文本。
/ `3 [, r3 T( n) u$ V1 J( B' w
* n" C8 x6 ~. I  m
+ S" H3 t& L! F# U奇怪的I/O error — 我在开发过程中发现下面这两条语句0 a% I5 A8 O) a/ P. G0 y
assignfile(fDesc,CDDatadir+describefile);
# W- F- V. m$ t9 K# C0 w; c" Lreset(fDesc); ! q6 j$ j8 V, L& J! _9 s6 ?/ _
每当我第一次运行到这里时,总会出现 I/O Error 183 的错误.
- [( d, ~; ^3 W9 S) D: F) r最后我想这也有可能是没有清除 ioresult 的原因.在两句之间加入
8 M$ t. R  F4 D8 mif ioresult<>0# |, B! t2 u' P3 q! i9 ?
then;
, U$ l- p! m0 F9 k: foooook! 可以了.1 t& o* P. j/ G9 S8 ^$ R  `- O
( @$ m/ r; w. l2 F
6 \( E8 q0 i7 o3 [0 ^& Z4 Q- Q
值得注意的I/O error
/ t3 S3 [2 b& v8 z2 R+ {AssignFile(F, fname);
5 c$ i9 z! S" gRewrite(F);9 D, [$ w* _% q! w# o( ~. t
当文件 F 经 Reset(F)打开的情况下, Rewrite(F)会引发一个异常: I/O error 32
/ [. u! f* H& F: L! M3 m反之,经 Rewrite(F)打开, Reset(F)也会引发同一个异常.1 ~3 q& V, D/ I& {9 X
Reset(F)两次,closefile(F),再Rewrite(F),或反之,也会引发同样异常.6 Q+ C2 T5 h- i0 m* ?

4 X: i3 T3 u; o- v2 d: s) `& C* _
3 Q3 y/ \3 q! T2 w$ S$ N6 J. I+ I' x/ E- g9 F5 A6 E
string和pchar的相互转换:& x, l. i0 U# R, d' t* I9 t+ d8 Z
string –> pchar: pchar(s/ ?: n( N" v6 A; u: G  q  W: @8 x
tr:string);
3 d3 u+ ^8 Q! K& X) f! xpchar –> string: strpas(p:pchar);
- P! y: r9 Z- g" H1 a0 W! w# Z* W7 o( x$ A
  q% Y$ z; |/ ?' s, B* N! B

) {$ h4 g7 P: l, ?: k在Delphi代码中定义数据库
7 d) O' j* f+ S% \procedure tform1.create_tbl;. X6 x, ~. T4 s  C6 H/ j0 @
var tbl:ttable;
( d! P$ j+ s& Z6 n3 h. ]2 b5 }6 bbegin
/ B- W  [; x$ z) ]. I5 i3 rtbl:=ttable.create(self); // 如没有声明中的”tform1.”,Delphi不认这个self4 ]" U$ C8 }* G' D, W& Z; p
with tbl do& l  h2 M, A& [3 y: n' V
begin
' N% D# C6 u6 F+ {% w0 D- @datebasename:=;dbdemos’;3 E: V( C( F3 s; o, ^7 l. q
tablename:=’my_tbl’;
7 Y' w  n. x; v4 ^3 x' M3 E% hwith fielddefs do
. {5 R* y  B  h9 i' {6 _6 ]begin
3 G( M7 g4 n/ n% s/ Bclear;  E+ O) V! ]" S9 ^1 I3 \5 @# x/ k
add(‘No’,ftInteger,0,false);; g  U% H  ^1 N
add(‘Name’,ftString,0,false);* r7 Z5 |5 A8 m5 O2 X9 \$ U. S# \
& u( K: O& n! F; B% v+ i8 _
end;
, e! l' F' X1 Y% [with indexdefs do" {4 \% ^" I' \
begin( f" R5 r7 Y; P7 `' U6 f) ^4 |
clear;
, Y' E9 A3 h& h2 T7 E& f9 {add(‘primary’,'no’,[ixPrimary,ixUnique]);" W1 `% m2 _  v' ?/ d1 j7 @
& I9 d2 n% z8 L: b3 m. o6 B) I
end;3 U7 |) q# _# ^
CreateTable;% n7 a+ D0 z  _5 K. t( B& t; T
end;) d1 @+ G7 t( `, j* [) y8 L
end;- ]$ D& s* l+ e3 ^# f/ T7 ~# U
/ R1 r  q; u# S  O
3 r1 C- z% Z& L4 y% ^
string、TStrings、pchar的相互转换(这里是我的个人经验)
7 P! E+ d- U; k假设有如下定义:# P- J( k- a# T7 S
var
9 h; y6 c0 M' ~/ D# wp:pchar;
8 Z9 S3 m6 \- t. l  h: |s:string;
% t7 V) H9 Q) n: V. g. Q( c. c9 r4 Oss:tstrings;' W1 W! X& s6 d+ B% P
begin: |5 c2 P. ]* N/ |
ss:=tstringlist.create; // 开始时一定不要忘记创建ss
* j$ _7 Q8 ^# D( M* Y9 e; ]/ U4 `- Fss.text:=s; // string –> tstrings, f* m$ |# g) ~; X/ @( W5 E
s:=ss.text; // tstrings –> string5 w2 Y" j* f5 X2 u) \" }
p:=pchar(s); // string –> pchar0 P8 }. ~# h  r4 Y/ `% l
s:=p; // pchar –> string
5 w- v$ Y7 E% Hshowmessage(s); // 合法语句5 T/ g4 `7 u5 i$ n
showmessage(p); // 合法语句, f0 m5 k! }* B. [4 p
… …0 X: Y$ A; G3 c2 n1 z
ss.free; // 最后还要记着释放ss占用的资源+ u( o; r  M3 r8 L. w
end;
# Q7 o" {7 s8 j7 H& v8 O; G9 S
, K# i( O* P& ~- j( F' D5 E+ z4 _& @( n' G
: o1 l  D$ R% n; q
在设计Menu时,常用的ShortCut可从下拉菜单中选取。但我发现可选的ShortCut有些不在列表中,如ESC,Ctrl-Shift-A等。我试着在ShortCut项的右边输入:ESC,竟然成功了。再试Ctrl-Shift-A,这回Delphi自动把它变为Shift-Ctrl-A

TOP

發新話題