打印

delphi 技巧合輯

delphi 技巧合輯

INI文件的操作要点5 S/ A9 d& K( ?2 J7 a0 ], H! n
(1)在interface关键字后的uses子句中加入
' x( S7 ?  N  D4 s# \; l! Ouses …,inifiles;, r+ |( b0 b2 A1 K1 K% Q# P+ E
(2)设置变量:var inifile:=TIniFile;; ?5 \, i  M) M' X! b
(3)使用前,一定要先做:
9 w6 U, n# P$ h5 Y! b* Q$ A9 b) X* [inifile:=TIniFile.Create(inifilename);1 M( o7 m3 |2 a$ C* w
我在这里绕了个弯子,写成
  h8 i$ T6 `9 C0 m: v+ f7 binifile.Create(inifilename);
0 s: w  l" d7 b1 s. i! f+ z; T: t: `% l* v0 U5 B* j
TShiftState用来检测CTRL,ALT,Shift,以及鼠标按键的状态,
) T0 U; s9 d7 ?0 p! u3 w常常用在键盘或鼠标的事件处理程序之中。
- L$ V  h# {' B& F$ v6 |
; i% U6 l0 G) E6 u. b/ w7 l. W! JDCU文件(编译的库单元)的重用
: R) ~* t- B$ Z6 `- q% K, g3 Z+ X7 Q(1)在interface里的uses子句中引用。如Windows,Dialogs,- m& |! }$ Z( G- P8 H: n
等等,要求被引用的DCU一定要放在Delphi 3\Lib子目录中。
( x8 f" |8 \7 h$ ]5 |(2)在implementation里的uses子句中引用。如果是自行编写的! \+ R$ T6 y$ k- \
DCU文件,应采用这一方式,并将被引用的DCU文件放入当前
; @+ L1 v1 b8 M& ]/ N工程所在的子目录中。
& H/ @3 Q! t) `0 cexecutefile函数(在FmxUtils.DCU中定义)不能用在FormCreate; g1 t  ]- d: ^2 k
事件中。真奇怪……
2 V+ F: l& R8 d  N6 ~0 Z& `1 M1 p' B9 O$ o1 y
内置的版本号控制功能
* P7 I. A4 J9 T5 i1 A在Project Options中的VersionInfo项里,有版本信息的定制,/ r/ Z4 \6 |, S. v4 j0 x4 k
包括一个有趣的版本号自动增加功能(Auto-increment build
% ~3 W1 w. F" S) vnumber),即每Build一次,版本号中的Build Number加1。选中
" D  p; o0 s, \& JInclude version information in project,编译,用资源管" @$ a/ o& b# K# t0 ?
理器里找到生成的.exe文件,点右键,查看“属性”一项,就% C, z" k; |7 G. e  |3 W4 r& z
会看到在属性中多了一页“版本”,里面就是你刚才输入的各' _. J$ t0 W6 K9 Q6 y: @
项内容。6 f& y$ ~4 j$ b, I- p7 K

$ l/ _% u/ f& M" d. t; I
0 M6 j+ Z  [% i# b( z定制Speedbar. v4 Y8 q, K$ Q9 W& i* D6 J
右键点击左上角的加速键条(speedbar),选中Properties,. X$ R0 b! x& O$ d& s
在列表框中找到你想要加入speedbar的命令按钮,将它拖到# s# M; N3 f4 X& D) s8 K+ N- n
speedbar上的合适位置即可。如果speedbar上没有多余的空间
' P5 E2 D- x% C9 |/ K3 S: l+ T! A来容纳新的按钮,可把鼠标在speedbar右框处变为双向箭头的* R# J+ C% x+ E- a- V% P( Z
形状,向右拖动一段距离,就可腾出空间。如想删除speedbar
& y6 x3 t8 _. l上的某个按钮,可简单地把它拖出speedbar的范围,就能删除。
$ q8 I/ l, W! e5 F4 l0 ]8 F2 I* a3 h* v3 z6 n2 t, A* G
0 b! a2 V4 B- I4 F! `/ V/ r% m, H
计算出的字段5 t- N+ B' C4 P5 {1 h9 ]
在写一个程序时,我要在DBGrid中显示出一个memo的部分信息,当我把那个
9 Q& `( i- \5 S9 Rmemo字段放进去后,运行时只能显示出“(memo)”字样。从书上找到计算字
2 c. c, j; j7 ?+ o段的用法后,我在TTable中增加一个计算字段MemoHeader,宽度为40,在此
8 M, z" t- A5 y$ ITTable的OnCalcFields事件中输入:& x& F' N; S1 i3 z
with MyTable do& v/ s. P# k# F2 c# J: D
FieldByName(‘memoheader’).asstring:=FieldByName(‘memo’).asstring;
& w. d" C. L* Z/ y  w( c& A在DBGrid中放入MemoHeader,运行,OK!
" Y+ U" b: v! _  o- U% t4 ]8 s# h7 W  P' Y1 V) X
. D2 Z5 _* Z, L0 ~
字段编辑器
: m* k) F* F5 O# I9 U" D% ^3 i解决了上面的问题后,我继续学习字段编辑器的作用。原来,DELPHI通过字
2 n4 W1 R5 ]( A/ S+ z% J0 G. Z段编辑器,近乎完美地实现了数据库的字段级的控制,这包括:
$ ?/ d# ^: f" x+ m! s3 j1)字段在DBGrid中标题、宽度、能否可见;
- i) a1 H7 a' `: I5 c: [7 W2)字段的显示格式和编辑时输入的过滤条件;% z8 K( N1 [: F: J/ M7 I
3)字段是否只读;0 z( O3 X) ]% `) q
4)字段的类型:数据字段/计算字段/查询字段/内部计算字段;3 T1 S. l8 v0 w- }% K) Y
5)字段的显示/赋值/修改等事件的定制。
7 D% N; x& S3 j3 h
4 n. Y6 i5 e" u$ ~3 e) d6 ]5 d# I5 U
设计Form时的快捷键' o6 B6 n; t0 I4 c
Del 删除所选组件
5 o3 ^, ^6 w4 g) L% YEsc 选择当前组件的容器(通常是Panel,Group或Form)+ B7 A7 N  B, \5 ^% u$ ^
F11 在Form或Unit和对象检查器之间切换
" ]2 f8 t7 }* \7 l8 mF12 在Form和代码编辑器间切换# z9 l" G- [+ p5 e% F% _
Ctrl-F12 显示“查看Unit”对话框
' Q5 w3 _  `: Z! ^" `Shift-F12 显示“查看Form”对话框+ C- I4 u$ L( }; m+ Y
TAB 下一个组件/ `/ @- {5 ~3 v* w9 }' U+ s* U( @+ d
Shift-TAB 上一个组件
- s: \! x) K; i3 J' f方向键 选中此方向上最近的组件
3 v! Z3 n5 r, Z% o( m, U8 C! f6 @( uCtrl-方向键 将所选组件移动一个点, ?+ J6 a; ~7 K! ~5 J: T; B8 A. i1 N2 n
Shift-方向键 将所选组件改变一个点的大小7 Y% i, H7 @8 y3 ?8 D+ r
Ctrl-Shift-方向键 将所选组件移动一个格
& q- ]  L7 N  e# tShift-click 按住Shift键再用鼠标点击组件,可以选择多个组件。6 P2 ~3 R; M, B4 N% q
–= 下面这条是我摸索出来的 =–. f! i+ e+ E- d/ q) x( C. P0 p
Ctrl-drag 按住Ctrl键在一个容器组件(如Panel,QReport,Groupbox等)
, f$ D( h, ^' ?/ c# \2 V里拖动鼠标,可强制选择鼠标拖过的矩形框中的所有属于此容
* O9 U, z6 o# w器的可视组件但不包括该容器组件。
# S: q" h" S: U% i1 u$ f! n( I$ J- s
& N! N5 E) o1 w0 e' V- t$ w' m
使用QReport的若干经验2 n! T5 [8 T0 L. \0 E5 f
1)QuickRep1.DataSet:=query1. ]( V- q$ P/ i. C4 d- n
不然无输出结果
8 N- s+ |# q4 B5 G2)从qrpt2man.doc中查知,格式化输出结果的方法是:
, L8 w& x/ o- G" r- Y2 D8 |在QRDBText.Mask中设为.00;0,将使输出带两位小数。
' X! K) J$ G; m5 {3)设置Group时,先加入一个QGroup,再加入一个QRBand,将QGroup的3 f$ e3 i, M2 `5 S
FooterBand设为刚才的QRBand,就可将其联系起来。+ `. A, ?' Y, {" r# a" W  \
4)在Group中打印的合计数,其ResetAfterPrint设为True,可实现分组合8 e4 N  W" b9 P

" G( |, T2 Y1 e3 Y; fformat(‘%*.*f’,[8,2,123.456]); //等价于format(‘%*8.2f’,[123.456])
: y/ k& F( B. v5 r* ~0 ]  J7 Eformat(‘%d %d %0:d %d’[10,20]);- r, b! n  _8 T( ?
' D2 V  e9 {7 ^  ]9 G. \4 o
  E; m* k2 c0 w- k, R; M

- S" A  X$ P/ o* y- |播放一个wav文件
8 J$ E9 H- O" u; U% Ruse mmsystem;
  B* U5 ^" |% PSndPlaySound(‘hello.wav’,SND_FILENAME or SND_SYNC)& L$ B# Q# U# w0 E
( |  f) ?1 e7 q" t
使你的form适应不同的显示分辨率
+ Y5 T, U$ ]" Z" l9 P9 t; R假设你在800*600的分辨率下设计的form,第一步:
' j; T3 Q7 }0 V$ I: g& K" t4 \inplementation
. b! r3 M0 }( h; X8 Fconst; }: u' D' ^+ _7 H
ScreenWidth: LongInt = 800; {I designed my form in 800×600 mode.}: L6 B% w3 y& e8 A: o6 G+ T# o
ScreenHeight: LongInt = 600;
* I* ?) R% }: b5 e# _; D. R! Y8 b, y8 ~$ i" W
{$R *.DFM}
, m' \! f0 C, w) `
+ ]; K4 x( o7 H* j( _procedure TForm1.FormCreate(Sender: TObject);+ Q$ V0 G; B0 |1 {* ~. f! M" e" t$ X
begin
7 |7 d% _4 \& {' G! Ascaled := true;
9 k- X3 v: q+ X7 ~2 x+ x" b1 |if (screen.width <> ScreenWidth) then" v( v' c2 q. i4 O8 p" g, C+ {& D
begin7 i; k2 |; a5 V
height := longint(height) * longint(screen.height) div ScreenHeight;
5 A: e6 {3 Q/ [6 p, \width := longint(width) * longint(screen.width) div ScreenWidth;+ x6 B, Q$ O* h% f* C
scaleBy(screen.width, ScreenWidth);5 Q7 D) {8 \( ~4 N! c" [0 g/ Z
end;
5 a( I+ `* K- G9 Vend;( X+ y2 _; {. |( l, E- B
% k* V% r- `1 h7 L2 R
下一步,要让每个子控制的字体改变到合适的大小:
' _, c" G" y" p) S" W, t% Btype
3 i' S5 t0 m& Q* i9 B3 ?5 t5 [TFooClass = class(TControl); { needed to get at protected }2 }1 X; A0 a/ ]4 T& @: W) A7 ?2 g
{ font property }
6 O, f5 j# C5 H  L4 A1 @5 y: D7 B7 B4 l/ w, ~* V+ n
var! {# l; N5 V& e) J5 W. i
i: integer;
' b5 s% i5 J0 T& [; y" Ybegin
, G0 d# {' ^5 Y7 E$ i  ffor i := ControlCount – 1 downto 0 do& }( r5 r; Y; A
TFooClass(Controls).Font.Size :=) y# g$ l- J1 N: @: u; S
(NewFormWidth div OldFormWidth) *  ^' f, t$ i7 V% j5 W5 z
TFooClass(Controls).Font.Size;
. s! t8 o/ u" @, ]3 Y, Pend;3 J' J, g% }2 h2 O

& M' g! A9 B. N  q$ L' p用raise引发一个错误处理例程( M6 ^, x9 m) }2 u- [6 G8 H
示例:先给出下面的定义7 D: f* Y+ Q% c1 |
type EPasswordInvalid=class(Exception);
" z; n! l6 R( B- r这样你就可以随时引发一个”password invalid”的例外:
; x" w( X9 h& Y  k8 _/ wif Password<>CorrectPassword then
$ v  d2 g% R- R+ H, K2 _9 yraise EPasswordInvalid.Create(‘Increect Password entered’);
4 [( I' }+ E* w1 d运行后,出现信息框% \5 F/ F9 b% v4 l
Project Project1.exe raise exception class EPasswordInvalid. @7 a  B/ d. x0 M* O+ v
with message ‘Incorrect Password entered’. Process stopped.
: S. f' D3 \0 R0 k3 m8 F; ]: B$ {- nUse step or run to continue.
" V, y/ D7 q; [" w2 c再按Run按钮,出现一个信息框:
1 [+ O, i8 I$ `3 \! n' wIncorrect Password entered.4 Y- b) \* V6 [+ C6 K; W5 l
" w0 O& Q6 X# w/ V7 D! }
2 c8 k# I) q4 q) k* f0 x
从DEMO例程中学到的若干小技巧
/ x& k1 [+ ^: z  g" U4 g( S$ M在demo\internet\http\webbrows\main.pas中,
6 D* J( G1 ?9 M2 r2 uprocedure TForm1.DocumentSourceClick(Sender:Tobject);
+ s5 p- C" P' N: _1 c7 Pbegin6 J2 u3 g3 b/ Y* L
with DocSourceForm do+ O  A. f$ w; C# C# @" `
begin# a, o9 n  @2 c
show; // 显示HTML源码的FORM& d1 G: c0 _! s3 l1 d8 n
Memo1.lines.clear; // 清空memo1中内容0 Z( h5 d  v: r: [0 i, ~) }) N
Memo1.lines.add(HTML1.SourceText); // 植入源码2 E8 E$ w/ Y3 n: H1 ]
Memo1.SelStart:=0 // ***
8 a' Z9 S3 a* M( d( I0 ]SendMessage(Memo1.Handle, // Memo1的窗口句柄
7 `0 n3 C- ~. D9 b5 d  l* B& n9 fEM_ScrollCaret //将Edit Control中的caret光标滚动到视野中6 Z. }. l* r( F4 p0 T) G! u7 v  ^
0,0 //这两个参数暂不使用
3 ^6 c+ _4 Y& O% y# E& Uend;7 }! b1 L& d  c% _
end;
& \8 x$ j' f5 ?, X! T(此SendMessage系一WinAPI调用,给一个或一组窗口发送消息,直到
! w% T5 Q# }: p/ U相应窗口处理此消息后才有返回值。相似的另一函数为PostMessage,& v1 ^. f5 p& f3 `) ?
它将消息放入消息队列中后立即返回。)
; N% q8 P: g  M/ T/ I*** 清空当前选择并将光标移动到指定字符(0代表第一个字符)。如同时& a. [4 ^0 D5 ^2 l; y( V, I
设memo1.sellength为一非0值,可选择一段文本。
8 B2 a" H( \, W. u) e0 q) a! ]: G3 P

3 ?' c1 ~* h, Q$ m# J奇怪的I/O error — 我在开发过程中发现下面这两条语句
! n& {# v2 F7 Y8 d. Passignfile(fDesc,CDDatadir+describefile);
1 ]. K! u0 G5 zreset(fDesc);
5 K7 z" K- h- V( o6 O每当我第一次运行到这里时,总会出现 I/O Error 183 的错误.
# ^2 q0 R3 h  N- f& ?7 P) c7 l最后我想这也有可能是没有清除 ioresult 的原因.在两句之间加入2 }0 q# a  M" @  t0 P9 `
if ioresult<>0; M1 ]* n) h2 j% ^
then;
0 d1 ?: d5 u, Uoooook! 可以了.
" r0 y* Z' r! \5 i1 K" T9 {+ X
. J) P  |  V9 ]- E! h3 Q! D
: @9 i/ _( p) z. e值得注意的I/O error+ X3 \$ S' ?9 Q: f5 b, L
AssignFile(F, fname);7 w9 @$ l; v" V: X. V$ E
Rewrite(F);
3 j% [- N% T- K  Y* p4 Q0 t当文件 F 经 Reset(F)打开的情况下, Rewrite(F)会引发一个异常: I/O error 326 `4 H2 e+ i8 Y
反之,经 Rewrite(F)打开, Reset(F)也会引发同一个异常.
6 ]* U, s2 u* \Reset(F)两次,closefile(F),再Rewrite(F),或反之,也会引发同样异常.
+ W* c3 M8 J9 [4 g0 `  J, V% T" ?* [7 I7 |9 D6 c  D9 g

/ @0 e5 j0 }% j7 N" C
' X: m7 P% B* U7 s3 C! m" X" z' nstring和pchar的相互转换:# W1 N. e; `, e% C
string –> pchar: pchar(s
* s$ n# e. {2 u3 ~& p" }7 H4 e' ]7 r( Gtr:string);
& C+ I2 G( N; dpchar –> string: strpas(p:pchar);
* X- @* x! ~% ?5 w& X- P
/ q8 G2 }  }$ O- b
) b; K' o6 D: g9 q" P* p# D+ R% g4 ~% }( U% F  e) U
在Delphi代码中定义数据库( w) I( t6 ~1 i( ?- ~! t+ e
procedure tform1.create_tbl;
; @( E9 @0 g* K- qvar tbl:ttable;, E+ h! ?: o! Q% p
begin/ z' D4 _3 B$ H2 J# @0 G, g
tbl:=ttable.create(self); // 如没有声明中的”tform1.”,Delphi不认这个self6 Y- q1 p9 N. A) l$ P& \: G
with tbl do- b7 |$ @& t2 n
begin- ~/ O4 h6 ~- \9 a% J% H" x% X
datebasename:=;dbdemos’;" l: j% _. D; m: `- y* Q9 K
tablename:=’my_tbl’;
- U" a, \- _3 `, G. `" Zwith fielddefs do
5 ?4 E3 I" ?. s3 V6 `6 B' K# \begin
/ z: c3 r8 w2 j6 Mclear;* r7 O' y1 L4 E6 L0 g$ x0 a, l
add(‘No’,ftInteger,0,false);+ h$ `9 r4 |2 h3 h: g* ?3 Y
add(‘Name’,ftString,0,false);
8 b! T7 N" R! C  B! F4 z7 X/ @
3 V4 V4 i/ C0 w5 J" W" [$ \end;
! v- K3 X2 Z4 n# A  ~! @4 Gwith indexdefs do
7 d% n" f7 }0 S+ k% kbegin
. J' B& B5 P3 b7 v) b' J& Aclear;
) p; d# n& N& N: {% E' qadd(‘primary’,'no’,[ixPrimary,ixUnique]);- h# \# E/ }7 C
4 ?: _( U6 Q- ~2 r$ b0 m
end;1 _+ X% W& F+ W9 }  O3 j- ~
CreateTable;1 F, P+ ?9 t. o7 @% O( ]
end;
5 X) A  J0 H2 i: i( h6 Xend;0 f( I, \* J+ M

; M2 Y- e% }; G0 `- s9 V- l; E9 @) v$ F$ P7 X" x* d* z+ {
string、TStrings、pchar的相互转换(这里是我的个人经验)
' H: e& P1 n9 L; a5 v$ m假设有如下定义:
  A- Q0 f) E' I0 ]9 t: O/ ~var! q3 {0 i: D: w2 H6 R  t: G* k3 B
p:pchar;
; W2 h, S2 P" B$ Q0 U- D$ Ts:string;
5 c9 D; X4 S" t; \ss:tstrings;
7 X. f, p* U; T9 }% @' Abegin+ @# g5 Y2 j; \+ l, c+ D6 p1 R4 I
ss:=tstringlist.create; // 开始时一定不要忘记创建ss2 V7 x* o6 N% O) \. A8 H
ss.text:=s; // string –> tstrings, r2 _+ t1 e# x" }4 g& ?% ?2 P
s:=ss.text; // tstrings –> string
/ e: {- D& c  C$ L6 w7 Np:=pchar(s); // string –> pchar
; B6 p2 e) {3 Ts:=p; // pchar –> string% y, O5 U7 ^" O5 _& j
showmessage(s); // 合法语句' B5 V+ n/ w+ P; L% [: q5 h
showmessage(p); // 合法语句4 O& \" c% r# R/ N3 R
… …; @4 n; u6 ^; @% l/ h7 [
ss.free; // 最后还要记着释放ss占用的资源. ^. r; m4 ]) T& {! l
end;
6 _0 g$ P9 H4 i: @5 w7 a1 r5 \9 n
7 L7 Z, [1 ]1 E) g+ B
  ?7 _$ `9 z( a* [3 n, t
2 Y; p) L3 V" I在设计Menu时,常用的ShortCut可从下拉菜单中选取。但我发现可选的ShortCut有些不在列表中,如ESC,Ctrl-Shift-A等。我试着在ShortCut项的右边输入:ESC,竟然成功了。再试Ctrl-Shift-A,这回Delphi自动把它变为Shift-Ctrl-A

TOP

發新話題