Board logo

標題: delphi 技巧合輯 [打印本頁]

作者: segaa    時間: 2010-3-10 04:40 PM     標題: delphi 技巧合輯

INI文件的操作要点
5 O5 X6 a9 I) n0 R(1)在interface关键字后的uses子句中加入
9 q7 F& R" N- P8 ?8 J* s- duses …,inifiles;
4 d% J! `& F/ Q- m; c; g, l(2)设置变量:var inifile:=TIniFile;5 `; A; k2 v9 n+ o6 N4 i) q8 k
(3)使用前,一定要先做:
  G4 l* O. t$ c. q4 ]& Winifile:=TIniFile.Create(inifilename);
+ n7 ]- J8 T9 h+ n我在这里绕了个弯子,写成6 s8 M# r: q  ?+ Q. V3 w
inifile.Create(inifilename);' U0 h- D5 x; Z
6 {5 P1 M6 y  s. S: R" h
TShiftState用来检测CTRL,ALT,Shift,以及鼠标按键的状态,
6 Q9 A+ }+ o0 a* [( T常常用在键盘或鼠标的事件处理程序之中。, h- U/ U" e1 }8 Y  @+ f/ W
9 N6 o# q: J# H1 b( k1 E) U& b
DCU文件(编译的库单元)的重用
3 n; K4 y0 |- Y* ^(1)在interface里的uses子句中引用。如Windows,Dialogs,
9 {! T* B( \  @7 M  s等等,要求被引用的DCU一定要放在Delphi 3\Lib子目录中。
) @( S/ \, {0 `# D# h(2)在implementation里的uses子句中引用。如果是自行编写的9 `8 F0 ^% y/ @: I9 E: g
DCU文件,应采用这一方式,并将被引用的DCU文件放入当前- h" k2 Y9 w  |. |4 F
工程所在的子目录中。! h4 u3 n! ?4 t2 P( ]- w$ u
executefile函数(在FmxUtils.DCU中定义)不能用在FormCreate9 a4 Q* M; I8 @
事件中。真奇怪……
# ]6 ^3 {: ^& x6 A' a/ H
! M; S. u* ]+ j8 I8 l内置的版本号控制功能
- w; E( t, x8 C( K. y5 ~: \3 a4 a在Project Options中的VersionInfo项里,有版本信息的定制,
6 [& E% r: N0 ^; y7 J包括一个有趣的版本号自动增加功能(Auto-increment build
; W# M1 C, R# ?0 Q7 \& Bnumber),即每Build一次,版本号中的Build Number加1。选中$ i8 i) Q% |8 L$ N* m
Include version information in project,编译,用资源管
5 o, p8 W+ G  Z( }理器里找到生成的.exe文件,点右键,查看“属性”一项,就
1 W7 d" Q/ e1 D$ g3 E; x. A2 _( f会看到在属性中多了一页“版本”,里面就是你刚才输入的各
( ^- H8 Y" f' R6 q, J; m9 [: {# c; n项内容。
3 v* O; H- e3 R% F' \
  r9 U; F: T$ Z8 U( X- d' I  H+ F
( c/ [0 A& S7 x9 a定制Speedbar
/ x7 g1 c: [7 }$ Z% V" g右键点击左上角的加速键条(speedbar),选中Properties,6 M( s) D) l) B
在列表框中找到你想要加入speedbar的命令按钮,将它拖到: D9 P+ s  K% b' t- O: R) t
speedbar上的合适位置即可。如果speedbar上没有多余的空间0 m, G- p) l- I( B/ M: H# ?
来容纳新的按钮,可把鼠标在speedbar右框处变为双向箭头的. M9 H. m8 R+ r3 ?
形状,向右拖动一段距离,就可腾出空间。如想删除speedbar# K0 ~7 ?1 \0 D  ?1 f6 Q$ z# q
上的某个按钮,可简单地把它拖出speedbar的范围,就能删除。
5 G7 X' u4 f- F3 b7 i1 ^) N% p2 G$ l5 {" U: q6 }" i

9 P( E& I9 t- @" U' }* R计算出的字段
$ s( Q6 O) P4 H在写一个程序时,我要在DBGrid中显示出一个memo的部分信息,当我把那个
* z( O) _* Q  _5 j: W' \0 bmemo字段放进去后,运行时只能显示出“(memo)”字样。从书上找到计算字( E8 E2 d* K2 F) q
段的用法后,我在TTable中增加一个计算字段MemoHeader,宽度为40,在此/ E; n3 s; [- A; Z
TTable的OnCalcFields事件中输入:) U$ l5 O2 j1 T+ I
with MyTable do
1 h. s1 H  `4 `8 G1 {FieldByName(‘memoheader’).asstring:=FieldByName(‘memo’).asstring;* m+ }9 F, }& d  ~
在DBGrid中放入MemoHeader,运行,OK!3 C, w8 Z& e; H6 ~( F
# F& l7 Q* |. i, h
9 j; d$ K) {+ C* I& Q
字段编辑器% B% Q1 s& n1 Y0 ]4 v
解决了上面的问题后,我继续学习字段编辑器的作用。原来,DELPHI通过字
* X3 w: E1 [/ `9 W! Y2 ^7 ?- C+ Y/ q段编辑器,近乎完美地实现了数据库的字段级的控制,这包括:7 k$ m: S5 M. T7 \( @
1)字段在DBGrid中标题、宽度、能否可见;
" N& P1 m  n% e5 \  U2)字段的显示格式和编辑时输入的过滤条件;5 a1 U2 r/ Q( L# Y9 I. i
3)字段是否只读;
# v* s. P$ K0 u; |0 `4)字段的类型:数据字段/计算字段/查询字段/内部计算字段;% u" k! k( B8 ~. D
5)字段的显示/赋值/修改等事件的定制。
$ B" y9 Q( O6 D2 _4 l7 Z* T8 h6 n1 D' M7 H

  B, P' k" \- ]" Q" A6 `% F设计Form时的快捷键
+ N2 \- @# T" }( D7 w8 {Del 删除所选组件3 B) k$ _/ J, S
Esc 选择当前组件的容器(通常是Panel,Group或Form)+ N* _& S; j9 j4 M0 Z1 S
F11 在Form或Unit和对象检查器之间切换/ |1 B- Q) v! f4 j8 Z1 ]# F7 j
F12 在Form和代码编辑器间切换
( \' [* \: k, |% ]Ctrl-F12 显示“查看Unit”对话框, M, |1 S5 M- Q; Q
Shift-F12 显示“查看Form”对话框! U# |4 {+ B+ k' E5 [% _$ U3 V: S' ^
TAB 下一个组件
# }0 Q- M4 ~/ U8 U5 n; J( y% OShift-TAB 上一个组件# q5 g3 b/ O2 t7 X9 u+ _
方向键 选中此方向上最近的组件
: Y' G6 F2 ^8 pCtrl-方向键 将所选组件移动一个点8 v/ l% _, D/ i; b6 i' W5 ]+ {
Shift-方向键 将所选组件改变一个点的大小; k5 `4 \3 x3 X/ @$ u
Ctrl-Shift-方向键 将所选组件移动一个格7 X% ?; d; R$ J6 b8 @! \
Shift-click 按住Shift键再用鼠标点击组件,可以选择多个组件。
- P0 r$ T! C% Y! p7 {7 z5 }( J–= 下面这条是我摸索出来的 =–
8 P% }7 i  K9 L$ A1 XCtrl-drag 按住Ctrl键在一个容器组件(如Panel,QReport,Groupbox等)1 X- C7 @  z* K) S, I
里拖动鼠标,可强制选择鼠标拖过的矩形框中的所有属于此容1 S" X( `6 h- r+ F0 F- a. k
器的可视组件但不包括该容器组件。
0 ~: W1 K2 P0 N+ Y" J1 ?+ ?/ K
& S2 q7 @$ X( l1 u- k) W& [
9 U7 F+ K/ [! r* C使用QReport的若干经验
2 _2 A5 Q7 \& W5 f+ A% Q7 ?1)QuickRep1.DataSet:=query1
' w' }: {; ^% V不然无输出结果
$ x$ d/ V. ^* |; t4 ]2)从qrpt2man.doc中查知,格式化输出结果的方法是:. u1 ?8 t* `* @5 s
在QRDBText.Mask中设为.00;0,将使输出带两位小数。9 L- n& U" K+ F4 U) r
3)设置Group时,先加入一个QGroup,再加入一个QRBand,将QGroup的
0 J  Z4 \4 |: Q  z) ]FooterBand设为刚才的QRBand,就可将其联系起来。1 H4 Q3 e5 g! Y) d! r+ K/ O
4)在Group中打印的合计数,其ResetAfterPrint设为True,可实现分组合) Y9 w2 _' ~8 j" E2 ^

$ i( Q8 Q! o( l- r$ d. `format(‘%*.*f’,[8,2,123.456]); //等价于format(‘%*8.2f’,[123.456])
# C! z$ Q% D; o" r5 n0 @format(‘%d %d %0:d %d’[10,20]);
5 f- R: P# G  j  I, u; |5 n1 F4 X7 ?& {( |9 S

+ m4 |) T* l4 V4 ~; B! O2 f, Z
! ^2 ^) v# Z: y  v播放一个wav文件8 E* n$ `% t. [/ e
use mmsystem;
  T$ q5 d% U7 Q$ [) `  f& PSndPlaySound(‘hello.wav’,SND_FILENAME or SND_SYNC)8 Y4 Z5 r: m& K4 y7 s& f; K

& I8 O0 L+ @0 f( M使你的form适应不同的显示分辨率
9 m" y6 @$ N) L; R3 }0 s! T+ o假设你在800*600的分辨率下设计的form,第一步:/ }- c4 u( [8 t0 G' x' P
inplementation, E5 j: k8 M! t2 H' h
const0 B3 l2 e) c+ s7 M
ScreenWidth: LongInt = 800; {I designed my form in 800×600 mode.}
8 e2 Y) D7 Q% |, G8 wScreenHeight: LongInt = 600;
: Z$ ?9 y3 ]1 K3 c0 Z0 y5 P4 f$ v! J, W
1 N* n" Z1 d1 J$ Z( I4 a8 f{$R *.DFM}
2 Z' q, W$ u/ K6 d
$ I6 X& g  z' w; Y8 F' zprocedure TForm1.FormCreate(Sender: TObject);( @: n8 w% s; b: ^# M( k7 _
begin
! {6 ?  W- Q5 n* l1 o# P3 Tscaled := true;; |4 |% ^: H' a
if (screen.width <> ScreenWidth) then
! g" M- w. h" ^3 i. nbegin
; L! s: N# N% S( hheight := longint(height) * longint(screen.height) div ScreenHeight;: F( W& O( E3 M1 q
width := longint(width) * longint(screen.width) div ScreenWidth;+ w+ O" N0 f7 V- m5 a
scaleBy(screen.width, ScreenWidth);
7 E( w- O/ x) b" Iend;
# j! H6 v/ W( O" Oend;
0 C3 @5 P5 ^# p# D
0 @' l# N3 o! R. G* H8 S下一步,要让每个子控制的字体改变到合适的大小:( R1 M/ f8 Z/ Z8 O, c
type! z7 Z' V5 [5 W
TFooClass = class(TControl); { needed to get at protected }
) Q  j' ^( V: F4 @{ font property }
$ L' `, E* Q& W* {
  |/ L- j. d! i/ w" Gvar
) ~; G6 \& o0 Si: integer;
: v: ~. D/ c/ i! Qbegin
$ ?2 ?) i6 o" _9 u  [" `0 ifor i := ControlCount – 1 downto 0 do
1 O7 V. x; V- y' s9 Y- h! k0 KTFooClass(Controls).Font.Size :=# j) h3 A! X! H
(NewFormWidth div OldFormWidth) *
$ `) |$ p4 G4 g& g7 [: i5 ITFooClass(Controls).Font.Size;' v. W9 w2 v7 k# Z! P; W
end;
6 Y8 n1 X' u* V
( [& g1 n8 V7 u9 \' f8 m3 O用raise引发一个错误处理例程
4 t* p! d' D! W- G( r示例:先给出下面的定义* x7 @5 {  u/ D9 e+ ?
type EPasswordInvalid=class(Exception);; u0 g4 }/ y% D! }4 t2 o
这样你就可以随时引发一个”password invalid”的例外:
& W) Y1 R( X3 E' M  Fif Password<>CorrectPassword then1 {8 O  j# B" s5 l' p6 B! v, O2 |
raise EPasswordInvalid.Create(‘Increect Password entered’);0 ]2 k! p$ k: B" L. [- E6 a
运行后,出现信息框$ |5 Y6 @7 e6 y
Project Project1.exe raise exception class EPasswordInvalid
$ H5 M7 Z) Q6 g" s1 _with message ‘Incorrect Password entered’. Process stopped.
+ n4 x2 q/ O, @# |: _Use step or run to continue.
1 P! Z- m7 x0 G% a' V1 m: k: V0 Z3 ~再按Run按钮,出现一个信息框:
& v  x8 J4 B2 ~# m# u# rIncorrect Password entered.( d1 G) [- S' ^' J

& {) ^/ W4 Q5 e# Y6 R1 `$ h) b" B3 V
从DEMO例程中学到的若干小技巧
9 L: o4 @/ R' C7 w8 O9 m在demo\internet\http\webbrows\main.pas中,/ w* j  v, k7 \" h& Y/ L
procedure TForm1.DocumentSourceClick(Sender:Tobject);
% W# @; y# Q- z( pbegin
6 b, T1 M/ E9 V( @with DocSourceForm do$ O5 G: M& h8 r! e
begin
+ O* U( I# i4 K1 [  ?" @: E5 Rshow; // 显示HTML源码的FORM  Y2 Z3 _, m3 L5 C* K  N
Memo1.lines.clear; // 清空memo1中内容
8 i+ ^1 X5 [$ x3 c+ E2 X, NMemo1.lines.add(HTML1.SourceText); // 植入源码
; X4 O" y1 K) B! [2 m5 \0 {+ r1 a8 _Memo1.SelStart:=0 // ***; x5 f) h5 f2 o) [, R
SendMessage(Memo1.Handle, // Memo1的窗口句柄
, c/ [, w8 ], [: jEM_ScrollCaret //将Edit Control中的caret光标滚动到视野中
+ v( R. q2 y) a1 n2 g0,0 //这两个参数暂不使用
% c7 T1 j, t& A/ Qend;: p3 v) F2 `- q7 f% ~4 K, S
end;7 a- E! c7 |+ Y* M9 B2 I
(此SendMessage系一WinAPI调用,给一个或一组窗口发送消息,直到# ^5 n( z8 v. X% P0 D
相应窗口处理此消息后才有返回值。相似的另一函数为PostMessage,% b" v3 r2 p0 i- H( [
它将消息放入消息队列中后立即返回。)
* C! J; K: g4 p9 y, [5 ^0 L( i# ]*** 清空当前选择并将光标移动到指定字符(0代表第一个字符)。如同时( K+ k& Y8 |7 o2 o' E
设memo1.sellength为一非0值,可选择一段文本。- r3 T. e1 X' n( S& k9 I" s

+ ^0 ^+ _$ n5 C- M5 b! t/ w' _! q  \
奇怪的I/O error — 我在开发过程中发现下面这两条语句# o$ m: s& l' o8 ]5 b
assignfile(fDesc,CDDatadir+describefile);
3 {* c2 K4 f1 j3 nreset(fDesc); ; i1 H8 `4 a2 c& D! h% \* R7 j& A
每当我第一次运行到这里时,总会出现 I/O Error 183 的错误.+ `1 @6 j" u8 z6 `2 Z
最后我想这也有可能是没有清除 ioresult 的原因.在两句之间加入
' H7 N9 }+ a5 Rif ioresult<>0* ?# ?# ]& x- @/ m: d( ?0 k
then; 9 V4 U. A' W3 W0 H) U7 {
oooook! 可以了.8 h4 y- x7 c1 D' ~6 f" w! d
) i8 t6 D6 T- z: o

0 t+ C2 w; w$ `7 f! [- u9 V值得注意的I/O error6 A% |1 Y3 p5 @# P/ C
AssignFile(F, fname);
. E  `' o& O5 ~: [7 u7 I6 X1 rRewrite(F);
9 r& n3 x' O4 J当文件 F 经 Reset(F)打开的情况下, Rewrite(F)会引发一个异常: I/O error 32
* Y5 y. g, V+ F反之,经 Rewrite(F)打开, Reset(F)也会引发同一个异常.
6 Y' w  w+ c( m# M- d+ z$ `Reset(F)两次,closefile(F),再Rewrite(F),或反之,也会引发同样异常.# Y' }# e/ o6 o+ f. |) }

8 L8 L. b% p2 C8 k% ~& P/ W( |" B/ I- U, B2 T

9 |2 L7 ]( m7 Q3 i- Gstring和pchar的相互转换:) v1 G* G5 T* |# o( w4 Z- V
string –> pchar: pchar(s! `' k  W& q& H9 H; p
tr:string);9 h7 i) Q  m9 z3 }8 g$ C
pchar –> string: strpas(p:pchar);; l, i  A3 A* U

5 h  b  R) t) O+ V' D2 F5 I  k8 I* c  t  R5 r1 ]1 O( D+ [
8 t6 P1 S8 t8 S. ~8 A/ b
在Delphi代码中定义数据库
# H3 g; A, _. Pprocedure tform1.create_tbl;% z$ v$ k. B: s7 k
var tbl:ttable;
1 X4 X$ ~* c- W) N4 Sbegin' l" o5 n% g4 I1 j
tbl:=ttable.create(self); // 如没有声明中的”tform1.”,Delphi不认这个self9 T- Y5 \5 H$ ?" f/ P1 m
with tbl do9 L7 E6 T0 ^0 x# x) E6 s: e
begin5 c1 y& n; M& p" X
datebasename:=;dbdemos’;, O3 j3 A; [  E9 f: _6 J* d: ?* ]
tablename:=’my_tbl’;6 \. b. W0 @, u/ X; Q* W- o& i
with fielddefs do/ [: V5 W) R: q" l* N) _
begin
, o2 K- X* }3 S9 J7 j) F0 B+ sclear;
% V- I7 a5 Z6 _# s4 \add(‘No’,ftInteger,0,false);/ a* C" s9 C. q* G
add(‘Name’,ftString,0,false);, w# z5 p: M' D, n5 ?
+ }4 D# E+ N8 ?* `- H* `7 X5 `3 s
end;
6 ^; ^3 l3 i% P2 owith indexdefs do  n5 o5 A" s% k1 E7 s
begin8 ?6 q! r$ s4 e
clear;  _: v( c. Z0 g2 D) |
add(‘primary’,'no’,[ixPrimary,ixUnique]);
% t8 p- o- U' @- a+ F6 X: D# _, C( s9 U% p
end;
6 q4 }( ?* c9 z5 ^: TCreateTable;
5 Y4 N0 a* w$ l5 k  m' M6 L0 Wend;, R; `1 t" v4 S/ {
end;) r) h# G) W+ r$ v8 x

" h/ g( O8 l$ t9 G1 h6 m" ^
+ J/ H/ }; v  c7 }, d/ F1 m+ f9 Gstring、TStrings、pchar的相互转换(这里是我的个人经验)8 j) X! a+ p3 L7 Z0 u
假设有如下定义:$ b- M# ]5 V  ]4 x( G% q# F3 h# K2 M
var7 ?; K" `+ w1 a4 @- r5 U5 _
p:pchar;( x9 H; i! l1 _. v* U
s:string;
5 Q% L- O: R- ^/ Kss:tstrings;
% C) d3 l: y" C# M$ S. X4 J- {  x$ vbegin; O  s/ C% e! k4 m
ss:=tstringlist.create; // 开始时一定不要忘记创建ss2 h$ S. D6 X% a4 i4 y& m
ss.text:=s; // string –> tstrings
# }, v, p! P. \) C9 K8 g" C. ]s:=ss.text; // tstrings –> string! }7 A; M& _7 S* i, J  I
p:=pchar(s); // string –> pchar
/ ^% V: l  B4 v; hs:=p; // pchar –> string
8 `& @/ R) O* F% a$ ]/ Wshowmessage(s); // 合法语句9 n+ R/ i& B- ^; y
showmessage(p); // 合法语句
5 q8 k! H0 k* B- }- o… …
6 q* a0 i& c- |1 n& s* Q- Yss.free; // 最后还要记着释放ss占用的资源
4 S$ C) t( t0 S3 y' pend;
( e, o* o5 H+ t
+ U- y/ j6 |$ V2 `; b
: Y0 h9 F3 o/ f* ]+ m. W' }# J" e; ]
在设计Menu时,常用的ShortCut可从下拉菜单中选取。但我发现可选的ShortCut有些不在列表中,如ESC,Ctrl-Shift-A等。我试着在ShortCut项的右边输入:ESC,竟然成功了。再试Ctrl-Shift-A,这回Delphi自动把它变为Shift-Ctrl-A




歡迎光臨 幸運草之戀 (http://discuz.segaa.net/) Powered by Discuz! 6.0.0