Board logo

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

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

INI文件的操作要点* q! q! }  a2 t6 K% r4 _  f+ o
(1)在interface关键字后的uses子句中加入
1 T* C2 ~$ c0 ?- f7 {! g1 g- P8 luses …,inifiles;
! G0 h( Q! E3 b/ \& l8 [(2)设置变量:var inifile:=TIniFile;
! B9 s; j, ^3 q- f9 A(3)使用前,一定要先做:
" t9 J/ k1 _  z+ cinifile:=TIniFile.Create(inifilename);
7 D5 {/ @$ {. D我在这里绕了个弯子,写成4 ^) b$ E, v0 i/ O" f1 y( ?/ q
inifile.Create(inifilename);
, Y. p. _) Y1 y8 w7 Q( H+ p; }& o; n" i5 m& q2 |5 ?- |
TShiftState用来检测CTRL,ALT,Shift,以及鼠标按键的状态,
: A5 j) z  ]0 X3 Z4 A% F常常用在键盘或鼠标的事件处理程序之中。
  P9 W$ J- x; ~6 c5 n! r- \! j1 _: R: E* L
DCU文件(编译的库单元)的重用
, X8 S, k* R! |0 l' z* }0 F, b(1)在interface里的uses子句中引用。如Windows,Dialogs,
2 }* E: t7 x2 P, @等等,要求被引用的DCU一定要放在Delphi 3\Lib子目录中。
' @7 O3 E/ |; g(2)在implementation里的uses子句中引用。如果是自行编写的
1 {7 }. T) O' r' X8 }8 kDCU文件,应采用这一方式,并将被引用的DCU文件放入当前
2 r2 p2 d6 K# t+ i4 ~3 ~) l. O* z3 i工程所在的子目录中。
( Z" h' @: [- ]executefile函数(在FmxUtils.DCU中定义)不能用在FormCreate
; h7 H3 n0 _2 M5 ]/ f1 W事件中。真奇怪……" ~; N: r# \2 A0 G
5 S2 M) N% P9 ]
内置的版本号控制功能
. f& f0 \8 `: P; ]在Project Options中的VersionInfo项里,有版本信息的定制,
' m; k* S. d, u& P/ ^% P包括一个有趣的版本号自动增加功能(Auto-increment build
3 H1 c$ b, g, Dnumber),即每Build一次,版本号中的Build Number加1。选中" g- q4 b1 q. W8 ~
Include version information in project,编译,用资源管
- M; D# F# u' r9 Z$ y理器里找到生成的.exe文件,点右键,查看“属性”一项,就' @5 C9 }& ?) u. A0 f" ^/ U. c
会看到在属性中多了一页“版本”,里面就是你刚才输入的各( {+ r% J% o  J
项内容。  D( _6 C6 \* g
* ]( G$ R$ V6 v! Q8 S( J: C

: y& Z, c. L, H& Y+ y& C* }5 i定制Speedbar& j0 i8 O4 {" ~
右键点击左上角的加速键条(speedbar),选中Properties,& _+ n: B" w9 y! D; ~% L: \
在列表框中找到你想要加入speedbar的命令按钮,将它拖到5 ^7 E  U& J" N
speedbar上的合适位置即可。如果speedbar上没有多余的空间
$ U4 X0 S  k% U  R) H. |来容纳新的按钮,可把鼠标在speedbar右框处变为双向箭头的
( E5 Q2 L# M4 U& m( \, {形状,向右拖动一段距离,就可腾出空间。如想删除speedbar
6 G5 N, `* f- c' h( J6 w) t4 D上的某个按钮,可简单地把它拖出speedbar的范围,就能删除。
3 w; v2 l$ c7 ]& \/ v8 D8 M) h9 Y( ^' U" i) C

8 X& a+ O- ~1 j. ~计算出的字段( M' d* o1 s+ _* J  b+ Z0 f. D( G
在写一个程序时,我要在DBGrid中显示出一个memo的部分信息,当我把那个9 e+ E2 w& E6 U" Z/ o  R0 _0 }" _3 N
memo字段放进去后,运行时只能显示出“(memo)”字样。从书上找到计算字
+ S; r: _/ M$ \9 |' @0 z8 U. d段的用法后,我在TTable中增加一个计算字段MemoHeader,宽度为40,在此
: {2 O& g! I( d) kTTable的OnCalcFields事件中输入:- I* D) z, j. W" y; C6 N- p
with MyTable do  C( M' p. g) A
FieldByName(‘memoheader’).asstring:=FieldByName(‘memo’).asstring;
+ W; W" q6 e8 P" Q8 y1 j在DBGrid中放入MemoHeader,运行,OK!
5 b+ @) }8 Z: F" v8 `! d, Q9 c8 i7 q2 A# j
2 C5 C# _/ K7 \! M  z1 ~; B
字段编辑器8 t  u9 ?1 F" Y4 R# w
解决了上面的问题后,我继续学习字段编辑器的作用。原来,DELPHI通过字
- |+ G# X9 I( Q* Q' ~* R段编辑器,近乎完美地实现了数据库的字段级的控制,这包括:
/ o0 G, h& B; d1)字段在DBGrid中标题、宽度、能否可见;! s9 l- t0 x* y9 x! S: [0 p& l
2)字段的显示格式和编辑时输入的过滤条件;
2 F7 {3 @0 F% d& E% D, W3)字段是否只读;, V) @6 i/ q' M1 p# O+ _- @6 Y
4)字段的类型:数据字段/计算字段/查询字段/内部计算字段;
8 p4 e3 a( b- F# Q) y1 J5)字段的显示/赋值/修改等事件的定制。
3 r0 j& v( _1 u$ T6 p7 T4 o; b; p5 G
: h  q7 p, L+ u" ]! c) Z
* @, K+ K' B1 ^/ F设计Form时的快捷键
  D7 w# \0 ]3 Z. f! R7 m0 rDel 删除所选组件
5 M% y1 ?, i+ \Esc 选择当前组件的容器(通常是Panel,Group或Form)
7 E+ H- F7 T+ `F11 在Form或Unit和对象检查器之间切换; p! |9 D& \! o% b3 Y5 o9 t4 A) ?
F12 在Form和代码编辑器间切换
( r; @+ z% u: n/ ]+ ^2 |Ctrl-F12 显示“查看Unit”对话框
5 T" I: ^* Y0 E& ]Shift-F12 显示“查看Form”对话框" U9 b2 p2 C1 w6 X% S
TAB 下一个组件- U: \! k* n0 o) P& F
Shift-TAB 上一个组件
/ j  Q% m' v! |: n) ^- g方向键 选中此方向上最近的组件% |" P! @- N3 e! X1 ~( B( V5 h
Ctrl-方向键 将所选组件移动一个点: q7 u$ x3 e) {- Z( U# K
Shift-方向键 将所选组件改变一个点的大小
& e. [% k2 A% D( l# z9 d4 eCtrl-Shift-方向键 将所选组件移动一个格
. o0 [2 N( B& ]1 `4 oShift-click 按住Shift键再用鼠标点击组件,可以选择多个组件。0 @( b7 U' q+ o" m; Z5 N9 G1 S: W5 B
–= 下面这条是我摸索出来的 =–5 k4 u7 T- e2 {
Ctrl-drag 按住Ctrl键在一个容器组件(如Panel,QReport,Groupbox等)5 f  e5 J/ n/ }9 X6 f- S
里拖动鼠标,可强制选择鼠标拖过的矩形框中的所有属于此容! B9 C" h( D* f( Q7 x, {
器的可视组件但不包括该容器组件。! i: ~+ j% y$ [6 Q% M7 z

; h/ e# ?/ f( C- L1 `1 L/ o4 M; n% Y
使用QReport的若干经验
, ]6 o  R7 d2 F8 |: H7 s0 V1)QuickRep1.DataSet:=query19 L) b6 }$ s0 r% I1 n, ^
不然无输出结果. o* n( x- b* t
2)从qrpt2man.doc中查知,格式化输出结果的方法是:% e& b! X# V9 g3 c
在QRDBText.Mask中设为.00;0,将使输出带两位小数。* y3 l- e' O4 M4 _# F/ I, y
3)设置Group时,先加入一个QGroup,再加入一个QRBand,将QGroup的& u, W3 w+ w$ P
FooterBand设为刚才的QRBand,就可将其联系起来。5 W5 m, [& R% e# C8 _5 a( Y! P
4)在Group中打印的合计数,其ResetAfterPrint设为True,可实现分组合, S, Z* n) ?) ?2 O+ I! b' y
; A$ [0 q% h- ?0 N
format(‘%*.*f’,[8,2,123.456]); //等价于format(‘%*8.2f’,[123.456])
6 [2 a6 Z  W" I: b4 Vformat(‘%d %d %0:d %d’[10,20]);% m) b. c/ r; d/ H! ]
7 d+ U. O  ], h& L1 _3 N4 ]
; k; B7 ^( f) V! v7 O  M4 D

; j) W0 m* I" B+ h0 [6 D播放一个wav文件
5 ]9 F" Z1 U- S2 l0 b( {/ Ause mmsystem;" `$ i# d) H; X# W0 f
SndPlaySound(‘hello.wav’,SND_FILENAME or SND_SYNC)
" ]" u0 |6 [2 @7 j) Z- H+ p  L: \$ }1 H8 d
使你的form适应不同的显示分辨率
4 D, {4 U  z9 k7 i9 I/ L假设你在800*600的分辨率下设计的form,第一步:" R8 S' `# {/ v: @. W/ ~- h
inplementation
/ b1 U5 o& [5 x; Econst% R' X$ t8 ?/ ?9 K8 L% _2 ~& |
ScreenWidth: LongInt = 800; {I designed my form in 800×600 mode.}
) Z7 ~& d  P% z$ P- jScreenHeight: LongInt = 600;
7 o" A- b: @3 _6 q! q% R7 @4 k
3 `6 R; g& b6 w! U* A{$R *.DFM}
0 a; o$ z- Q! v: Q! g
; h% ?! x) D% {procedure TForm1.FormCreate(Sender: TObject);
2 `1 U& ^# h- U0 Bbegin
$ w  Y4 ?. U! Q3 }  iscaled := true;
# U7 m6 Y( m( y0 Tif (screen.width <> ScreenWidth) then( _' m. d: T4 Y- X8 O6 S' q
begin
1 O* \' t( v3 k) i9 r) K/ d, [$ Lheight := longint(height) * longint(screen.height) div ScreenHeight;
7 [& E, I6 ^4 \# t8 Mwidth := longint(width) * longint(screen.width) div ScreenWidth;
6 Y% S  f9 ~8 C. l2 V+ a% M3 c3 e8 ^( {scaleBy(screen.width, ScreenWidth);& O  A. t; y) i9 S6 \
end;8 l. _. Y, F% S% [( Q: W" k
end;( V$ G9 W8 l' r) C' x' M

) {% f0 i- w2 \5 G下一步,要让每个子控制的字体改变到合适的大小:
# M' \2 O) _2 T3 v2 l: d  ftype: t/ q8 r1 c+ T! b* ]
TFooClass = class(TControl); { needed to get at protected }% x0 y6 _1 o, s2 Y, G0 v
{ font property }
! C. E7 |7 N0 Y7 x# i* `3 |. k6 j% b  `4 w! g
var
8 F& K8 l- b7 m3 J( K0 C$ p* ni: integer;( E8 I8 l9 ]) ]) n0 W
begin6 d- I9 x1 g. h6 i7 Q* S
for i := ControlCount – 1 downto 0 do
' M" f2 A4 C9 \2 v: \% YTFooClass(Controls).Font.Size :=
0 d# l! s$ U( P9 I0 {(NewFormWidth div OldFormWidth) *3 ?7 L6 x. D0 ?2 A* H2 S/ q
TFooClass(Controls).Font.Size;/ j5 Y. ?" ], f8 {1 |
end;
/ ~$ r0 D7 H% w* }, V$ l' M3 S, i! {
用raise引发一个错误处理例程- V9 h" _  O! j! D+ _8 ?
示例:先给出下面的定义$ [( F3 V7 q3 ~# c" q# J
type EPasswordInvalid=class(Exception);
, y+ Y& X( P6 c' c: S这样你就可以随时引发一个”password invalid”的例外:
2 R# o+ j1 b0 C. Q/ g3 Q( T* J! _if Password<>CorrectPassword then' r$ k! H, A6 V! b, K
raise EPasswordInvalid.Create(‘Increect Password entered’);$ A5 Z* J  T; U6 z4 ]; S) F7 J/ i
运行后,出现信息框
6 I* p8 _* j9 a( b+ E1 g4 kProject Project1.exe raise exception class EPasswordInvalid! Q" T* A# {+ g& S3 o
with message ‘Incorrect Password entered’. Process stopped.( a9 t6 o0 q- i
Use step or run to continue.
3 s+ _# I; N7 j- k5 P( ]再按Run按钮,出现一个信息框:# L! H* R" p+ \2 w. c! d' |
Incorrect Password entered.
9 @, C$ r  F5 L. j& T  ^* E  t  O3 }2 X4 r( K
3 C5 l. }; T6 q* U3 R
从DEMO例程中学到的若干小技巧
% U2 K7 D$ l& f在demo\internet\http\webbrows\main.pas中,2 R& E" M) M/ I  Q+ r7 z
procedure TForm1.DocumentSourceClick(Sender:Tobject);
* B$ v9 V# g9 G2 {( k3 j: ubegin' O$ `2 S7 E' V' |
with DocSourceForm do1 B( \5 K' e* Y+ J( s: c$ u* o
begin6 y4 n! J' w* J4 e$ Q1 t* M
show; // 显示HTML源码的FORM( f2 m) E5 Z2 M- ^$ I
Memo1.lines.clear; // 清空memo1中内容
3 _' o+ {5 {  e8 A% I" A& mMemo1.lines.add(HTML1.SourceText); // 植入源码
5 u! V- \7 I# E# ^- E1 uMemo1.SelStart:=0 // ***
: J, N  W6 B0 K- xSendMessage(Memo1.Handle, // Memo1的窗口句柄
5 R- Y+ g% m; m% MEM_ScrollCaret //将Edit Control中的caret光标滚动到视野中, b6 Y! {; {2 s
0,0 //这两个参数暂不使用
4 U7 S9 N: M& ^end;) |9 }- p. I! V+ P1 T9 f) Y
end;. U" m/ Q- {! \  E7 a
(此SendMessage系一WinAPI调用,给一个或一组窗口发送消息,直到
% {7 _9 a3 D5 e; A8 h6 j; _相应窗口处理此消息后才有返回值。相似的另一函数为PostMessage,
( U, E0 A/ b1 h3 O' D它将消息放入消息队列中后立即返回。)* W. C+ A; }3 y" X6 \. p6 p
*** 清空当前选择并将光标移动到指定字符(0代表第一个字符)。如同时' d  L# p" b+ x
设memo1.sellength为一非0值,可选择一段文本。
' I; Y# Y/ D7 ]; W0 I
1 u7 L0 B8 C- \2 K4 v) j3 a+ C5 ?+ y' R$ O( E
奇怪的I/O error — 我在开发过程中发现下面这两条语句
& T% t: O, ~9 o& l; @assignfile(fDesc,CDDatadir+describefile);
/ ]5 @& F9 G9 a) m# Creset(fDesc);
3 L8 ?- m$ R/ K' i: x2 F每当我第一次运行到这里时,总会出现 I/O Error 183 的错误.
: D6 w7 `0 F+ Q  Y/ w2 w最后我想这也有可能是没有清除 ioresult 的原因.在两句之间加入
0 z# K" G7 @! t* G+ ^if ioresult<>0
1 X* b/ J( V# S6 i; [" E* `# Xthen;
7 C& O' X, M& H, @6 h3 Aoooook! 可以了.
" f" |5 e$ e0 u0 w. b  K: C
- O# V0 I" R) G2 Q/ N' w1 N
; K7 g6 m' h7 i) B2 y, L. A" q  X1 f值得注意的I/O error
- y, c( C1 {2 t$ }AssignFile(F, fname);  C9 m. v  w6 Q; c' f5 x: J# z
Rewrite(F);
& D$ L! e& l4 Z2 F- B当文件 F 经 Reset(F)打开的情况下, Rewrite(F)会引发一个异常: I/O error 32- N  @. T9 h) |  e
反之,经 Rewrite(F)打开, Reset(F)也会引发同一个异常.
- Z  A( ]' ?/ o( h/ ?Reset(F)两次,closefile(F),再Rewrite(F),或反之,也会引发同样异常.: N& a. Q& R- w3 j! o; l
- ?( e+ s, ^9 H& g" m2 u; ~. N. I: Z& q

: a0 e$ V5 l1 k: r. m$ F  F$ b; U) m4 M' r. Y
string和pchar的相互转换:2 i3 T* a1 }, u6 U7 h% o/ h% D
string –> pchar: pchar(s
4 s* y" o7 Y5 Z4 H% Itr:string);
5 v9 S. W: A& \. C$ f) f( E: l1 _1 n* Tpchar –> string: strpas(p:pchar);8 i7 w0 _$ d0 D# t2 r; z# L9 Y! X, `
0 F4 q2 r% S, h0 {

4 A. L# m* l$ }9 w1 H* b7 [/ @( G& W
9 a% |1 R, `! E9 _6 i在Delphi代码中定义数据库
% p2 E' H1 d3 c8 bprocedure tform1.create_tbl;/ N! o) [$ Y5 m/ t9 O7 b
var tbl:ttable;" W5 ]$ G9 d  t) e8 P6 ~" t1 G
begin
, \: Y, P. l6 @# n% I# V1 ptbl:=ttable.create(self); // 如没有声明中的”tform1.”,Delphi不认这个self; w: H2 ?/ c' |
with tbl do5 s7 r: a+ v  t. A
begin
7 {2 W$ @( |2 R1 `: g/ T' Gdatebasename:=;dbdemos’;! m5 i) w" m! @9 u3 c6 H: l
tablename:=’my_tbl’;
3 W0 v6 F( {. ]with fielddefs do
/ f" `! X  b2 y- ?5 t. [+ mbegin, V4 X: h& l7 l* {' t
clear;
8 O( u& N$ m% N2 i4 l6 C- Kadd(‘No’,ftInteger,0,false);
+ }9 P+ A: _( l2 Yadd(‘Name’,ftString,0,false);
1 t2 w& w" R9 S% D/ J…0 \4 S0 ^* v0 |: M
end;
6 S" Z" W6 ~- T7 ?- K3 r8 ?with indexdefs do
2 m5 j0 p! _' obegin9 g# ~: f6 a. ~, ^2 l. w6 p- Q
clear;, I5 Y( s/ ]# |' y/ E' A
add(‘primary’,'no’,[ixPrimary,ixUnique]);- C) X: `; C1 J& x% }* v
…
: i) Q3 a+ O( eend;
' `8 [; k# @7 x9 `CreateTable;
+ Y$ a# A/ o! cend;
- J5 P. ^2 y' ]' T& ]end;1 M8 d* l  o# _( E' F% t; y& o! `& a

! O8 T& g! @! x$ v( ]% F
) J  A4 m, `4 G( w6 R2 E# Nstring、TStrings、pchar的相互转换(这里是我的个人经验)4 e* i3 H2 f# {# k6 c
假设有如下定义:
' X% c. `3 t5 B: n8 m4 w" e7 Nvar* p/ E5 P# R# n1 }& a
p:pchar;9 F/ \# f" v& c  v
s:string;1 {8 j! {3 u; x* j' }& ]$ l; a
ss:tstrings;( `, I7 @1 B1 j* y& D
begin
; J( Z. V  m2 \. y, W9 oss:=tstringlist.create; // 开始时一定不要忘记创建ss, o/ ]- d3 l3 r. H) f% z- d' r
ss.text:=s; // string –> tstrings' _  J& ^* A* S# P
s:=ss.text; // tstrings –> string
# c  \7 d$ T4 F2 r9 Vp:=pchar(s); // string –> pchar
( R& q- \* M! @9 Z6 as:=p; // pchar –> string
! k1 `4 i. V0 r' {. w( a) ashowmessage(s); // 合法语句2 S- g3 h$ {4 i
showmessage(p); // 合法语句. Y& v2 i" X+ K" q+ j
… …
  \# C. C' F. Y  K  A# }ss.free; // 最后还要记着释放ss占用的资源5 ^# n/ E, k7 \
end;  P! S+ x3 f+ m: n, y7 t

) _! |7 u% @, p' k. Z  Q, F( t, d8 @0 |. x' f6 {5 |

! b/ A/ K' J* m0 r在设计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