打印

delphi 技巧合輯

delphi 技巧合輯

INI文件的操作要点
7 `& P4 _6 S4 f" q3 R(1)在interface关键字后的uses子句中加入' c. e# B& m5 v. b
uses …,inifiles;7 {7 @- p  p* Q1 [' ]
(2)设置变量:var inifile:=TIniFile;
9 }: H( i4 I. D6 h- ?) i, x(3)使用前,一定要先做:
  x# X, z" O1 W+ q7 H6 I. \9 Uinifile:=TIniFile.Create(inifilename);
7 v- v1 A' m8 w! F. w我在这里绕了个弯子,写成& D3 m3 \! y- i% N( {
inifile.Create(inifilename);
, f. j- u( f; {+ B! P+ z$ s$ q
" ^# ^1 f7 C6 y0 f9 Z8 @TShiftState用来检测CTRL,ALT,Shift,以及鼠标按键的状态,
  s. t" z; T; o; o0 [8 l1 `常常用在键盘或鼠标的事件处理程序之中。
5 x0 S& n+ d) N5 z; B
- O  ]3 s+ o  ]DCU文件(编译的库单元)的重用# V* V5 S% n& W3 ~6 y3 I
(1)在interface里的uses子句中引用。如Windows,Dialogs,
* g( k) t4 G* Y0 e0 \2 h5 D9 G  e9 r等等,要求被引用的DCU一定要放在Delphi 3\Lib子目录中。
; C. C9 @( u9 a$ O9 d0 ~(2)在implementation里的uses子句中引用。如果是自行编写的
) o1 `: X6 E- S0 f* ?; nDCU文件,应采用这一方式,并将被引用的DCU文件放入当前
8 T8 D) L7 N6 s5 z) N* r  l$ E& X% j工程所在的子目录中。
& q1 L% m, A9 O4 ]. qexecutefile函数(在FmxUtils.DCU中定义)不能用在FormCreate
6 p2 E: Y  R4 I$ I( A7 Z! p3 |) J事件中。真奇怪……, R& t/ `! h; Y3 h0 l+ ^$ {
- {+ i9 u' l8 u( Y+ o% g
内置的版本号控制功能
8 U5 y9 s+ s; }, `4 U' k$ `在Project Options中的VersionInfo项里,有版本信息的定制,
$ m% V! n' @6 b4 v包括一个有趣的版本号自动增加功能(Auto-increment build
' |: D6 h: d" b& V* F6 F* `number),即每Build一次,版本号中的Build Number加1。选中& M4 `, @( z! ?2 f  e
Include version information in project,编译,用资源管
' p2 ?- l  h" t理器里找到生成的.exe文件,点右键,查看“属性”一项,就
( w( v: b( r7 J7 j& \. a3 A会看到在属性中多了一页“版本”,里面就是你刚才输入的各
  M5 K# v) Q- R( S7 I项内容。
' E! ]7 T! K$ t
2 f- q# l& x5 F8 X, I' M1 x9 a8 H6 i2 [
定制Speedbar
" m  }; a; M6 @$ [右键点击左上角的加速键条(speedbar),选中Properties,+ }- B. c; U' L5 E. j& Q' J
在列表框中找到你想要加入speedbar的命令按钮,将它拖到
* j" c" u4 V5 H  S3 ^/ B2 kspeedbar上的合适位置即可。如果speedbar上没有多余的空间
  k: a2 b8 d- z8 m$ ~4 ^2 O4 f( }1 e来容纳新的按钮,可把鼠标在speedbar右框处变为双向箭头的* O+ q$ f; U' C' n
形状,向右拖动一段距离,就可腾出空间。如想删除speedbar
" a  t3 K* x8 @( c4 z7 |9 D7 c上的某个按钮,可简单地把它拖出speedbar的范围,就能删除。0 @: x4 f) {8 l

1 |: l5 z' w& D" j2 E! L: y( A3 n" I0 t' e
计算出的字段9 Z5 O) [% s. ~0 n, n
在写一个程序时,我要在DBGrid中显示出一个memo的部分信息,当我把那个0 M' w8 K. {7 E( p# r
memo字段放进去后,运行时只能显示出“(memo)”字样。从书上找到计算字
" C3 M8 k& R6 w0 C. g# k/ c段的用法后,我在TTable中增加一个计算字段MemoHeader,宽度为40,在此
* n' x: K3 N; m0 V+ n! a6 Q# BTTable的OnCalcFields事件中输入:5 X! J5 c1 a+ B3 v6 z8 D
with MyTable do, [, E1 |0 J% m% w: o/ z0 E
FieldByName(‘memoheader’).asstring:=FieldByName(‘memo’).asstring;# H* ], v$ x$ o  O3 d/ O) y6 w
在DBGrid中放入MemoHeader,运行,OK!* C+ }/ w0 j/ K
: U% W4 q7 e. @# s8 C
1 p+ I: F; b& w7 F8 Y7 Q
字段编辑器' H9 K, p/ A) i# m- c7 b% P
解决了上面的问题后,我继续学习字段编辑器的作用。原来,DELPHI通过字
% B2 C7 R# S6 B' d9 _7 K. ?段编辑器,近乎完美地实现了数据库的字段级的控制,这包括:
' g6 ^2 L- l: |1)字段在DBGrid中标题、宽度、能否可见;
+ h% V* Q- ^7 U+ S2)字段的显示格式和编辑时输入的过滤条件;
0 ~+ D2 e0 \' x+ s3 i$ p3)字段是否只读;
5 H5 z& _$ w0 h( A/ ~4)字段的类型:数据字段/计算字段/查询字段/内部计算字段;
- W0 E3 q% h5 e6 j# y! U5)字段的显示/赋值/修改等事件的定制。5 q3 r/ q; k$ m) O5 {
: u) y6 a& a. {; @# u0 o4 a

( d9 w$ G% I6 s  ?# Z; X设计Form时的快捷键4 I1 ~. F# B9 P1 C: Z, ~: M! e
Del 删除所选组件7 m7 @* ], L5 Y3 E
Esc 选择当前组件的容器(通常是Panel,Group或Form): m* o! l- B% R& I- ]0 D3 P: `$ ^% H
F11 在Form或Unit和对象检查器之间切换2 \/ O' d) `  ]" a7 K' q! c. ~# S
F12 在Form和代码编辑器间切换
1 t+ m* [) s3 H# x- jCtrl-F12 显示“查看Unit”对话框
6 a- h) r4 W' h7 o6 F7 U! HShift-F12 显示“查看Form”对话框
# ]1 v- }5 ~! V+ Q' S0 JTAB 下一个组件& r/ y% ~4 y9 R1 j: @
Shift-TAB 上一个组件
7 F: {' ?$ d% E% _* z$ x/ o方向键 选中此方向上最近的组件/ }. S) ^; Y9 U; w; f) L
Ctrl-方向键 将所选组件移动一个点
. C& X* Q2 U1 r) `* |. hShift-方向键 将所选组件改变一个点的大小0 k1 t8 e* v' _. V+ `+ U! F7 Z: `
Ctrl-Shift-方向键 将所选组件移动一个格
: g5 m/ Z2 h. T& p7 V5 OShift-click 按住Shift键再用鼠标点击组件,可以选择多个组件。
6 e  S( p" f2 T" B9 c) V2 r1 }–= 下面这条是我摸索出来的 =–" V% \6 Q$ c6 s: _* {, v
Ctrl-drag 按住Ctrl键在一个容器组件(如Panel,QReport,Groupbox等)8 s; R3 A# }$ c  x1 `- Z
里拖动鼠标,可强制选择鼠标拖过的矩形框中的所有属于此容
* V, A$ e, d% a* Q+ L器的可视组件但不包括该容器组件。% o; _# j% j0 }

& N9 p9 H  P; t# K7 q
( ?, ~/ f( P& q1 K, v' W使用QReport的若干经验
6 y" m6 M8 x, i5 V4 m1)QuickRep1.DataSet:=query1
3 A* r4 b; ~( `, Z7 v( B: X+ o不然无输出结果( h& |# d; ?( e# y
2)从qrpt2man.doc中查知,格式化输出结果的方法是:
! E* A' l% x8 C- X6 w0 p1 g7 o在QRDBText.Mask中设为.00;0,将使输出带两位小数。" ~" p' V$ [, |3 N  q! j+ O
3)设置Group时,先加入一个QGroup,再加入一个QRBand,将QGroup的
& V) l& y! f; [; @) k* D3 NFooterBand设为刚才的QRBand,就可将其联系起来。
7 h% P; p) @4 V+ Q3 \4)在Group中打印的合计数,其ResetAfterPrint设为True,可实现分组合& D5 K9 F% H" h0 a# a
# Q1 A) J  I4 \' u  h5 ]1 N8 Q
format(‘%*.*f’,[8,2,123.456]); //等价于format(‘%*8.2f’,[123.456]). [7 U0 r7 w2 R2 \. U6 I0 P
format(‘%d %d %0:d %d’[10,20]);
+ t9 F, k9 ~  F, U
* g' |" J( w0 l( l
8 Y# S1 {. c1 h( H: |- }- T
+ i3 w% G) s$ U+ r% g播放一个wav文件- b2 `0 d" d. T) b3 I. b$ I
use mmsystem;4 `( N  q2 y% K, ~
SndPlaySound(‘hello.wav’,SND_FILENAME or SND_SYNC)
' d  _" m" x2 x
& S: E5 `* Q* _使你的form适应不同的显示分辨率
. ~% n+ w( o$ ^* l  h* N. K4 E/ {假设你在800*600的分辨率下设计的form,第一步:7 W3 v, c9 J4 e) R
inplementation
8 [6 E3 S! e# V2 w8 e. v0 oconst3 q" `9 ?$ S1 Y( p+ P4 p9 c2 ]) f
ScreenWidth: LongInt = 800; {I designed my form in 800×600 mode.}/ }: F8 k$ x! k& }% K) H2 n
ScreenHeight: LongInt = 600;
/ _9 @" {$ Y- h7 W5 i3 d- |6 @9 h7 C( k1 P
{$R *.DFM}' k7 a+ T) F' d+ O
' Y/ t1 w+ I1 Y1 C. |0 ]
procedure TForm1.FormCreate(Sender: TObject);
/ D. M* H) M# ^/ h7 obegin
/ }! x* ]) p9 m8 }scaled := true;% T2 x5 x1 M1 `, e5 R6 l
if (screen.width <> ScreenWidth) then
0 b4 v  Y$ I6 r+ W; bbegin# k- O. M- F% l$ m1 C3 w4 U
height := longint(height) * longint(screen.height) div ScreenHeight;
6 y: S% s' P) w8 O, iwidth := longint(width) * longint(screen.width) div ScreenWidth;
1 H) M* G' l8 v9 X  ?5 ?: N6 {scaleBy(screen.width, ScreenWidth);5 V( D5 g+ l' N3 L' N8 X; C& s: a
end;
  k( X& o; k) y& P- A7 Gend;
7 Y' q# O; ]! [3 P' Z4 a+ K2 x' k6 E; g' k5 q4 k2 w8 h
下一步,要让每个子控制的字体改变到合适的大小:
$ A" m5 s. P/ V) T+ i4 Ftype
: |1 t' D7 B3 Q2 pTFooClass = class(TControl); { needed to get at protected }
& R8 z- Q/ x; V, d" Y, d; S" @{ font property }
5 n9 Z; H, F* V) _  c* X" C# i
+ Y& Q; ^. L+ ovar
  I" G+ `" B" I8 K. S+ a8 [i: integer;0 y; t& M/ n* t
begin
& h, \; Q# p$ Y8 r0 j+ Hfor i := ControlCount – 1 downto 0 do/ t9 ]- {* M) P" `$ L
TFooClass(Controls).Font.Size :=) o& K9 J: `5 ?) n. ~
(NewFormWidth div OldFormWidth) *0 J' q6 g4 u% k7 G9 |1 j$ g
TFooClass(Controls).Font.Size;) d. R$ V$ K9 s3 _3 R  U$ m) Z; U
end;
* @$ K+ d9 H7 j- {2 l$ I
$ l# w% [1 L% S  n1 Y. S6 k4 h( Q8 S用raise引发一个错误处理例程
; {* |$ R6 @9 }: m' }6 I示例:先给出下面的定义
" |* S# _% |4 Q8 [8 r. q& T8 dtype EPasswordInvalid=class(Exception);
$ U# b. {" o" w" k8 p. B: K这样你就可以随时引发一个”password invalid”的例外:6 C4 V9 q0 o$ {
if Password<>CorrectPassword then
3 M+ Y7 a+ I+ M! wraise EPasswordInvalid.Create(‘Increect Password entered’);9 u4 n% w3 H4 P3 H
运行后,出现信息框
/ P" n9 D; C: N. mProject Project1.exe raise exception class EPasswordInvalid
' \6 Y% ~6 j* N9 \) z1 _8 rwith message ‘Incorrect Password entered’. Process stopped.
5 m3 c+ p; _) [* @2 q" e, rUse step or run to continue.
  {0 x) O+ L" x) V3 Y; b再按Run按钮,出现一个信息框:1 L" ^2 l% \" m; U* w* }
Incorrect Password entered.5 ~/ b; `! Y+ s) d: p% Y# y
; i1 x: b( T$ A- U0 i
9 F* W' k0 f# s* {, j$ X
从DEMO例程中学到的若干小技巧
% @% K4 f: `# M+ J0 M在demo\internet\http\webbrows\main.pas中,+ S" z2 X& ?( K5 K  c
procedure TForm1.DocumentSourceClick(Sender:Tobject);, Q5 e+ |  F( k
begin# K. p- I6 X/ ~0 m* a
with DocSourceForm do9 G) f* V% O$ d0 e8 h: P
begin
( s( P9 b/ V, c9 H$ [( fshow; // 显示HTML源码的FORM
% i" D! \  H* W% ]1 `Memo1.lines.clear; // 清空memo1中内容4 A/ h; ]2 w7 c, I. P, H& Y
Memo1.lines.add(HTML1.SourceText); // 植入源码
* J3 p( E8 V1 p% y$ V, Y- FMemo1.SelStart:=0 // ***
) j& O% R! ?0 u1 {SendMessage(Memo1.Handle, // Memo1的窗口句柄
- I# H% V! x' o, N2 j; J- e! eEM_ScrollCaret //将Edit Control中的caret光标滚动到视野中
* f  @- [. R# C8 G) Y5 C2 Y2 \6 U) Y0,0 //这两个参数暂不使用
. E5 [7 ]4 N& P2 D7 o3 Wend;* W: i1 n' Q, M. E0 V! c2 b( N
end;6 V8 n. S% q8 b
(此SendMessage系一WinAPI调用,给一个或一组窗口发送消息,直到# E- a6 \& b7 y' w
相应窗口处理此消息后才有返回值。相似的另一函数为PostMessage,: |; G  m9 j: g
它将消息放入消息队列中后立即返回。)
, K- v8 m" n) F7 K, h+ t$ Q*** 清空当前选择并将光标移动到指定字符(0代表第一个字符)。如同时
3 Y* b( `" c" t设memo1.sellength为一非0值,可选择一段文本。4 _6 b$ Z6 o, |7 B. I' z+ C
" m2 P& h0 t2 X9 r' R

; ]0 d9 _: o# ^奇怪的I/O error — 我在开发过程中发现下面这两条语句9 V6 r" z! e( {7 y. d# K6 }' V: [
assignfile(fDesc,CDDatadir+describefile);
' X# S2 A7 D6 b; T4 u0 z9 Breset(fDesc); 3 O3 X3 x2 F) m1 @
每当我第一次运行到这里时,总会出现 I/O Error 183 的错误.% {& G0 s) V. }
最后我想这也有可能是没有清除 ioresult 的原因.在两句之间加入! B3 j" {4 {$ S& y
if ioresult<>0
* {' z( H8 e- ~1 o: o( s9 _then; 7 x% `1 F4 [1 k; q
oooook! 可以了.5 Q; u7 M7 T% b1 u: @/ V: y. k  U
3 e! U0 I9 _# F8 D; y
7 K/ c9 k& W: r
值得注意的I/O error2 e* t% ]$ ^4 C2 _7 a& ?: t
AssignFile(F, fname);2 ?. d, o- Q5 i; \5 @9 H1 \' J% l
Rewrite(F);  X; q: h. `6 R6 W" Q3 A0 t6 r
当文件 F 经 Reset(F)打开的情况下, Rewrite(F)会引发一个异常: I/O error 32
9 n' ^/ e+ P- _/ |  L反之,经 Rewrite(F)打开, Reset(F)也会引发同一个异常.% S- Z% H: G) v- g
Reset(F)两次,closefile(F),再Rewrite(F),或反之,也会引发同样异常." g2 B8 d  d( w% I4 f: N3 ~8 v+ K
) O" d( ^; {  X; {' b
7 D! I8 Q" k0 \* r3 T

, C8 L; E: p1 N% Vstring和pchar的相互转换:
, x# ~0 \8 `5 z, Y# Pstring –> pchar: pchar(s
% Z0 c% T; J$ v. u& l" xtr:string);
! R! M2 R) c' npchar –> string: strpas(p:pchar);
6 S; E0 f( X  O- \  }3 |& R3 x7 W1 I9 p' E! `
  R- b4 O# F/ I9 f! k- v
6 l/ D( `9 ?7 R" j
在Delphi代码中定义数据库' c9 v& M/ P0 h0 v" ?; S) s' R5 t
procedure tform1.create_tbl;
% x6 ^1 q: v  C8 j0 j0 qvar tbl:ttable;
: S/ K1 s* H  W: n: qbegin! H. f$ ^9 O2 P& i4 A
tbl:=ttable.create(self); // 如没有声明中的”tform1.”,Delphi不认这个self
/ l8 b: J% S% s" O* X( c- v" n  Lwith tbl do
1 ^4 K* A% H2 v9 x3 h4 jbegin; i! S+ q# E7 g' ~# e  I
datebasename:=;dbdemos’;: ~# n, a! N0 [; U/ l2 ?# w3 |
tablename:=’my_tbl’;
; s4 `: V. C! D8 S% i4 F, f  nwith fielddefs do4 ~6 w9 Y3 W; f: \! Z0 F
begin
' m6 `3 c- z& ~! Jclear;
: T1 j; L7 g) N' e& ~$ x, s5 Z/ x" @add(‘No’,ftInteger,0,false);3 c. N1 a" B' K: i0 R
add(‘Name’,ftString,0,false);; |+ L+ T6 p5 j  e- S8 p
…
: t. D( r3 o& h$ h0 m- g$ ?end;4 i& c4 a8 ?. J' C% N
with indexdefs do* u4 Q% X! v3 z4 }
begin
% E2 v8 X; I- `' K4 P( P* eclear;
- H' [3 B* N/ ]( ^/ A' U" f; k" yadd(‘primary’,'no’,[ixPrimary,ixUnique]);
( _5 I6 {4 ~7 z1 g0 _  G' Z…
0 L& Q! y: k. j+ {end;
: r5 O' }! x) c$ R9 l( DCreateTable;
* d# E8 R% R8 n. Uend;
! w# j3 _5 R' r8 w) ^" ?end;; o% s! x+ q+ N& E( u& \

+ W, V1 j$ p/ h' ~0 `3 K. n. I4 ^2 K) |4 M; `9 E+ J
string、TStrings、pchar的相互转换(这里是我的个人经验), b6 }. R  e( s
假设有如下定义:# ^1 W  W/ N, H/ J
var0 x- K3 R9 U$ c! i
p:pchar;; R* [5 I, a, [6 s) w
s:string;
4 Y" t: `, t$ o& Z7 [2 \5 n# Ess:tstrings;: z' K1 W) Z4 @$ g( U3 j% `
begin  o/ n' H) P9 X4 r# ^3 C7 O
ss:=tstringlist.create; // 开始时一定不要忘记创建ss
& V  K- P: I4 `ss.text:=s; // string –> tstrings8 x" D) k! g- J+ n- V. v+ H" H
s:=ss.text; // tstrings –> string! @3 v! o9 a7 y+ [* T! Z
p:=pchar(s); // string –> pchar
; I: S" w) |! s) T/ O  Js:=p; // pchar –> string
: ^6 z5 z* t( l/ nshowmessage(s); // 合法语句$ z. I; r% \) S6 T7 K' T
showmessage(p); // 合法语句
0 ^; J2 O; E4 L2 G& e' ^… …
9 a, Y) c0 y" Z( s3 R) vss.free; // 最后还要记着释放ss占用的资源
9 H# @4 E( @+ m8 m, f, J/ uend;$ j+ H2 {3 |8 Y
* X& t! a$ O$ v( K
7 F! u1 `+ ~8 m) C( R2 @& `: I- R
( @; j7 k( r: g) Y
在设计Menu时,常用的ShortCut可从下拉菜单中选取。但我发现可选的ShortCut有些不在列表中,如ESC,Ctrl-Shift-A等。我试着在ShortCut项的右边输入:ESC,竟然成功了。再试Ctrl-Shift-A,这回Delphi自动把它变为Shift-Ctrl-A

TOP

發新話題