Board logo

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

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

INI文件的操作要点
) v% w* C0 R6 \" t! x- ?(1)在interface关键字后的uses子句中加入
1 J9 O+ S! d7 W" [; P2 Vuses …,inifiles;7 Q7 N, |2 G# M! t, w/ t5 H
(2)设置变量:var inifile:=TIniFile;% t! o3 ]0 w$ v
(3)使用前,一定要先做:; @" d8 t$ T" W6 g$ ]
inifile:=TIniFile.Create(inifilename);/ N. ^8 \% B, m2 t
我在这里绕了个弯子,写成+ E) {4 h. t" h' W" z" [! W
inifile.Create(inifilename);
3 w2 g! U0 C; _# A
' k% \- v0 B9 j6 S$ t/ CTShiftState用来检测CTRL,ALT,Shift,以及鼠标按键的状态,
. L2 }) B7 W/ j" j) S# P) S常常用在键盘或鼠标的事件处理程序之中。! v6 m5 @7 n. B

) N% t7 j( [7 nDCU文件(编译的库单元)的重用
! G) |9 j* h$ ?8 M. W(1)在interface里的uses子句中引用。如Windows,Dialogs,9 @! ?$ j2 B2 {; l3 U
等等,要求被引用的DCU一定要放在Delphi 3\Lib子目录中。# l- b6 ~3 W' C
(2)在implementation里的uses子句中引用。如果是自行编写的
- \& ?$ U/ V3 p) K" d" I) tDCU文件,应采用这一方式,并将被引用的DCU文件放入当前
5 l& i  U0 ?  i% w8 n3 g工程所在的子目录中。
2 J' j) |: D' L, c% c7 Q+ \executefile函数(在FmxUtils.DCU中定义)不能用在FormCreate5 Z: ?# u- m5 F
事件中。真奇怪……, c( P6 W. r- v/ \" G: ]0 t

' E  V2 X+ ~' r9 }内置的版本号控制功能
! i, P8 c# w8 K0 t9 D在Project Options中的VersionInfo项里,有版本信息的定制,! L' ~: q7 o6 u' y% z' `
包括一个有趣的版本号自动增加功能(Auto-increment build' E- T; p0 ?1 T" m8 y2 Y, X8 D  H( Y
number),即每Build一次,版本号中的Build Number加1。选中
( ~  u1 O+ m6 |! [& _Include version information in project,编译,用资源管, n5 G! T1 d! O5 B
理器里找到生成的.exe文件,点右键,查看“属性”一项,就
4 V- M/ p6 ]6 B! o  J0 c+ ^会看到在属性中多了一页“版本”,里面就是你刚才输入的各
6 P/ j* u6 V) `2 R/ [) Y* I项内容。/ a# O5 {0 Q% n+ p* a3 G7 _

  m7 R" h$ }5 X7 w/ N  Y% o( s  ?5 F8 V/ N$ Y; o
定制Speedbar
3 W9 `0 l+ `/ R5 C1 F6 C+ J* p6 q右键点击左上角的加速键条(speedbar),选中Properties,
! x" O2 f$ j* x( h, h" ?在列表框中找到你想要加入speedbar的命令按钮,将它拖到
/ h, S' s8 [) H$ `5 pspeedbar上的合适位置即可。如果speedbar上没有多余的空间; y1 g: f5 w) U( T
来容纳新的按钮,可把鼠标在speedbar右框处变为双向箭头的8 W, y0 x: w8 `5 {
形状,向右拖动一段距离,就可腾出空间。如想删除speedbar
1 }; k0 H% k; i+ j1 N上的某个按钮,可简单地把它拖出speedbar的范围,就能删除。  Y! M# f- F* f" t0 Z$ e

! ?4 @0 c; |; I; M3 Q( X  H
8 p4 Z+ _; u: O( P8 |) \8 f计算出的字段1 C* v4 @, K5 p
在写一个程序时,我要在DBGrid中显示出一个memo的部分信息,当我把那个/ F8 T4 T) ^$ U% w& G$ {8 L9 Y
memo字段放进去后,运行时只能显示出“(memo)”字样。从书上找到计算字( ~: O+ p. e3 G. S) X
段的用法后,我在TTable中增加一个计算字段MemoHeader,宽度为40,在此; n1 }* @' f- g, x! [* }8 U5 I" k
TTable的OnCalcFields事件中输入:
* c  z/ s) p3 ]with MyTable do
- h6 v# w& ^: U& qFieldByName(‘memoheader’).asstring:=FieldByName(‘memo’).asstring;1 j. o2 ]) F! B
在DBGrid中放入MemoHeader,运行,OK!
8 j& o7 v3 `4 L2 y* e
6 x" h7 a6 }* Z2 J) d# R6 f7 V$ o* ?! I$ R) i- Q  O) M& d$ j. r
字段编辑器
: c! L$ k; |" Z8 T解决了上面的问题后,我继续学习字段编辑器的作用。原来,DELPHI通过字" Q" b$ s2 ]. f2 u, Q, h
段编辑器,近乎完美地实现了数据库的字段级的控制,这包括:
2 }; a, R$ ?' A9 l5 e1)字段在DBGrid中标题、宽度、能否可见;
& R7 N  }' D6 r# u: T3 n2)字段的显示格式和编辑时输入的过滤条件;7 s, h8 M3 m, U2 k% _
3)字段是否只读;1 ?. q+ P# B; l% y4 C
4)字段的类型:数据字段/计算字段/查询字段/内部计算字段;
. d2 o+ @4 C7 S/ T7 T4 b7 l( J5)字段的显示/赋值/修改等事件的定制。
3 ^/ Z. S6 d9 _2 x, `& I
. R$ Z4 P, c9 s. n& h4 X) G" c7 t
5 S8 |* }! M% S: d0 S2 x, e设计Form时的快捷键
" t  d2 _, T7 h( F1 `" s0 G3 e# ]2 }: ?Del 删除所选组件
* r) H  R9 w+ ~: [$ w! ^  M; TEsc 选择当前组件的容器(通常是Panel,Group或Form)8 M( p5 P/ u8 V
F11 在Form或Unit和对象检查器之间切换
7 |2 Y6 ?! l) P: J2 mF12 在Form和代码编辑器间切换# \6 _7 C, ~& t1 i
Ctrl-F12 显示“查看Unit”对话框
1 Y, ?; @5 ~+ [+ V3 cShift-F12 显示“查看Form”对话框
- l! J* a1 o- I% Z# L: A9 a! f! YTAB 下一个组件! |! E$ r* W  z+ Q" \0 [, U
Shift-TAB 上一个组件
8 b1 w% o  ^7 M# R# E方向键 选中此方向上最近的组件6 s- D, ?2 l  `0 V
Ctrl-方向键 将所选组件移动一个点
- @* x% r. d2 T, @- GShift-方向键 将所选组件改变一个点的大小
" c( o3 X1 Y9 ^- o! F6 A$ \) c# [) @Ctrl-Shift-方向键 将所选组件移动一个格$ n3 i) u- S4 O3 S# E% _- s
Shift-click 按住Shift键再用鼠标点击组件,可以选择多个组件。
- |/ w  e5 E) ^# E–= 下面这条是我摸索出来的 =–
8 m+ e6 v' V) S3 hCtrl-drag 按住Ctrl键在一个容器组件(如Panel,QReport,Groupbox等)3 c# Q( i* Q0 [) d6 e- r
里拖动鼠标,可强制选择鼠标拖过的矩形框中的所有属于此容/ _/ c+ D  _. N# x
器的可视组件但不包括该容器组件。
8 f6 @9 r- V9 @9 ~( z6 u" ~# A! |1 ?# e$ m- P$ V& ^( o
! l7 P% g  v9 D6 [0 E! x: ]
使用QReport的若干经验
" J" O7 X* E' n* l+ ]- ~( w+ }1)QuickRep1.DataSet:=query1$ e2 l% w! H6 O, `! d/ ^1 L
不然无输出结果
: _/ H1 U9 L; l0 @) v2)从qrpt2man.doc中查知,格式化输出结果的方法是:
* y) c( V3 ?7 n( A" y在QRDBText.Mask中设为.00;0,将使输出带两位小数。0 r' a7 T8 Z! u4 N7 v% h( W
3)设置Group时,先加入一个QGroup,再加入一个QRBand,将QGroup的
; X4 I+ e" w( Y" C8 Q* j( WFooterBand设为刚才的QRBand,就可将其联系起来。# C6 G; L9 h7 F9 a
4)在Group中打印的合计数,其ResetAfterPrint设为True,可实现分组合1 G8 |( p1 C& `# s% N* U% C% V+ z

9 \" f# A& i$ o, b  rformat(‘%*.*f’,[8,2,123.456]); //等价于format(‘%*8.2f’,[123.456])
: g* S. B) O1 t6 r: Qformat(‘%d %d %0:d %d’[10,20]);# u7 J. J" G" G" N* d: f" Z
- F$ D; X& S4 M) W$ W
/ d+ t3 E+ U. K7 d0 Z8 [
  h4 |0 a3 k, n  U
播放一个wav文件
: W! l$ P5 O. [use mmsystem;/ P3 m- `0 G$ X
SndPlaySound(‘hello.wav’,SND_FILENAME or SND_SYNC). J, A2 w( u+ t4 j1 D% `

* h# X. q* W% T) y% v' K' l9 W使你的form适应不同的显示分辨率4 l4 F) z  T# \4 P: ?8 v/ A, b
假设你在800*600的分辨率下设计的form,第一步:1 @' q% f# ^% J# o" d
inplementation
% {8 l5 n3 [$ Bconst4 R' j! Z2 o  R5 I1 \" L  J
ScreenWidth: LongInt = 800; {I designed my form in 800×600 mode.}6 p* X( ^" w5 L: l2 E3 o
ScreenHeight: LongInt = 600;1 B( _' {% Y+ k/ b  \' i' ?# y
7 O) w* `$ @# l8 O: Q. D, l
{$R *.DFM}
  K/ C" r; p  D1 m+ N7 [% ?! e: t0 C! f4 }8 Z( `& y
procedure TForm1.FormCreate(Sender: TObject);
7 r3 a6 T3 A* @: i+ I. Bbegin
5 B: ]" u7 B7 w! s3 P2 S* Escaled := true;& Y8 x" _$ ^5 N5 E( b
if (screen.width <> ScreenWidth) then
$ u1 @% F4 Z" J1 I1 ybegin" l9 ]0 q  k9 R/ r
height := longint(height) * longint(screen.height) div ScreenHeight;
. U1 m. B# O8 iwidth := longint(width) * longint(screen.width) div ScreenWidth;
, h& Q- W/ }4 O$ yscaleBy(screen.width, ScreenWidth);
; z/ L6 v4 |8 b$ f, O* c+ ~( s; q" |end;
% E9 O0 h. R5 p" F- o9 aend;( M+ s+ q4 @! E% Z5 K, U& B6 X1 Z
- C% w3 g: c) ^/ ^/ _$ n; v0 r
下一步,要让每个子控制的字体改变到合适的大小:
. N& d7 b# A+ m& L0 y9 E5 S0 \$ ltype
) `- ]; ^/ I, g. c3 UTFooClass = class(TControl); { needed to get at protected }
0 q: D& o3 c" q0 Y% O. H3 e{ font property }* D, d: V: t5 i, m& c

9 l& I, `7 C2 x  ~/ pvar
& ~: ]0 u: o3 Y) t# }; P+ ei: integer;
  ~7 U) x- y5 Y9 D/ S) bbegin
1 K  {! l4 Y: B- g# [+ l. jfor i := ControlCount – 1 downto 0 do) z  F3 j* W4 ?! I7 I4 r
TFooClass(Controls).Font.Size :=
$ R. M9 ~: Z2 P# G( |(NewFormWidth div OldFormWidth) *! N. {) }5 i! }# W
TFooClass(Controls).Font.Size;
3 v$ ~9 e. ~  H  l  lend;) P( c2 v6 c0 m8 N! B
1 @- O5 d- t; P0 E) W
用raise引发一个错误处理例程2 m0 |1 Z  |$ f7 H" J, s
示例:先给出下面的定义  |- w6 _* t" m5 Y3 j
type EPasswordInvalid=class(Exception);
* u0 e( K; @; v! a  `8 h7 n+ i这样你就可以随时引发一个”password invalid”的例外:" o" F! p6 S& K* Z& F
if Password<>CorrectPassword then
7 G' w' j3 r7 l6 G& Iraise EPasswordInvalid.Create(‘Increect Password entered’);
, N2 a: B* v4 _1 r7 |运行后,出现信息框2 V+ y1 d: w% @* G3 k: \
Project Project1.exe raise exception class EPasswordInvalid
+ t- q. g- ~8 l* B7 |5 M  g$ Wwith message ‘Incorrect Password entered’. Process stopped.: V' x. o( ?8 m
Use step or run to continue.
( ~6 q: `* G: A再按Run按钮,出现一个信息框:
" L" a9 A( d) f/ V. P; cIncorrect Password entered.
# J3 B" f$ c; K0 }- q
& `( |& ^, I4 {; F& a/ x& P0 u2 E8 ~# h+ c1 l
从DEMO例程中学到的若干小技巧0 N6 z' h4 {- `2 q6 D- c
在demo\internet\http\webbrows\main.pas中,0 {$ a% p! [( ~# A' O7 x& Z
procedure TForm1.DocumentSourceClick(Sender:Tobject);8 q! o4 x/ C% [. H
begin
- Z$ {/ w& E6 Awith DocSourceForm do
" }2 E/ d  z! C, f# V# tbegin
3 n$ o# I. X. H8 L% Gshow; // 显示HTML源码的FORM" ?! q3 N1 O6 S1 @
Memo1.lines.clear; // 清空memo1中内容. ]6 l4 O! L1 O, c
Memo1.lines.add(HTML1.SourceText); // 植入源码9 [2 X4 J; [( \
Memo1.SelStart:=0 // ***) G+ y0 C9 u( e) @1 |
SendMessage(Memo1.Handle, // Memo1的窗口句柄9 n9 j2 K9 l% @) S
EM_ScrollCaret //将Edit Control中的caret光标滚动到视野中
6 P% I0 w  W' M# b* V+ K" y0,0 //这两个参数暂不使用( L) ]& i) l5 ]/ [
end;
1 h% x0 [1 b# K0 Y* m( xend;
  i8 n4 l- ^, U2 Q! m0 K(此SendMessage系一WinAPI调用,给一个或一组窗口发送消息,直到
1 a" P( f3 P7 F" {" K* l相应窗口处理此消息后才有返回值。相似的另一函数为PostMessage,% i$ ~7 N, _+ e
它将消息放入消息队列中后立即返回。)2 U4 \: G# [& _7 l
*** 清空当前选择并将光标移动到指定字符(0代表第一个字符)。如同时
6 l$ C" h# y2 x5 _( H2 D9 ]" x设memo1.sellength为一非0值,可选择一段文本。; p1 [- F/ F5 }/ @# J! H

: O: v: _" F5 Q; j9 L. T; y" ~# @5 B6 c+ M0 a8 o5 G6 t) F9 s4 A
奇怪的I/O error — 我在开发过程中发现下面这两条语句4 _/ `/ P5 D# H( J
assignfile(fDesc,CDDatadir+describefile);3 Q. {1 }: ?1 S; @: z3 q- {
reset(fDesc);
  G. D4 E7 g/ Z$ {4 A每当我第一次运行到这里时,总会出现 I/O Error 183 的错误.1 w' q) U8 e& f8 P
最后我想这也有可能是没有清除 ioresult 的原因.在两句之间加入. o% o6 G8 F3 N6 d% }5 F9 e
if ioresult<>0
/ {* ]; @! D  _1 zthen; ! J9 v5 Y* Q4 y) x! i3 b: o
oooook! 可以了.; b+ P/ l5 B, g; p. ?/ x  C

- g& ?( w% j( @) O3 \! j" k* W# V' k8 j: @3 Y
值得注意的I/O error1 q# v4 U3 N; D( U
AssignFile(F, fname);
' S" W  [$ u4 g% l8 O- j2 PRewrite(F);) {) ^$ j4 H- i$ l
当文件 F 经 Reset(F)打开的情况下, Rewrite(F)会引发一个异常: I/O error 325 B- X! ?5 D& Q. W
反之,经 Rewrite(F)打开, Reset(F)也会引发同一个异常.
* Y& y( ~: N5 s% G3 dReset(F)两次,closefile(F),再Rewrite(F),或反之,也会引发同样异常.
# ]2 i$ u  B# q7 }: d) Y$ r
+ @; ~+ V* C: Q( m; h  @
9 i& i& u/ T( m7 m3 }' _, O' b/ s2 S; _  R: V
string和pchar的相互转换:
3 R8 U+ d: J4 S% X# J% e8 Kstring –> pchar: pchar(s
0 Y  [9 [5 x, S. c, C# i2 ~  ftr:string);
0 K/ N9 U: e8 {pchar –> string: strpas(p:pchar);! l9 G+ b! }2 J' M( Y' P
" c2 A' g8 ?, V, [) m4 {; V

* F4 V  ?- [; W9 j: H, d; [
7 D: k  X% V5 k8 N7 Q) B在Delphi代码中定义数据库6 _) @0 o  P1 I- ]2 T8 J: V- z) i
procedure tform1.create_tbl;" s( N4 W# }+ {: [! s) P* a1 D5 R7 A
var tbl:ttable;# _, q8 T0 X5 p; \7 g
begin
# ^- u; T# F; H6 q( v/ }5 Gtbl:=ttable.create(self); // 如没有声明中的”tform1.”,Delphi不认这个self2 F% v4 ], W- h. J
with tbl do
# Y4 ]& b7 m, Bbegin9 [2 g3 J. F3 l" w
datebasename:=;dbdemos’;
' G* w( H$ M3 v+ Atablename:=’my_tbl’;1 l% s9 @6 Z( |) ]' Q! a& E
with fielddefs do
$ X% D8 W% C, K: N/ C0 Gbegin$ Q7 w; {9 R* z3 ~
clear;
2 p- w% L% z% Wadd(‘No’,ftInteger,0,false);
) g4 {6 i- O9 K7 padd(‘Name’,ftString,0,false);
! J; r( M  {* {. y' w6 Y0 W1 ^+ y8 s, Q4 M. _4 s
end;. c3 Y" }- u+ R/ u+ N# ^! C
with indexdefs do/ ]/ P! g/ z+ h; X  Z
begin9 S6 s+ K4 j' n. i4 [( ~
clear;- ~- H- y, i0 m2 ~* g) e
add(‘primary’,'no’,[ixPrimary,ixUnique]);* u$ `+ m3 M: t+ m. l# `% B

# u2 ~& ?/ z" \6 ^end;
+ R2 Z+ ^$ F& t6 R* r8 F2 G- }; YCreateTable;
, g' Y9 ]: a$ b6 {9 jend;
! q* k, _9 |/ J$ {! M" P- t- pend;4 j4 O: Y, r& W1 L6 k" t! _
' B9 u: y0 S& p

9 ]% k3 Y6 ?8 a, d2 ^. |& gstring、TStrings、pchar的相互转换(这里是我的个人经验)
0 r) _# |- s8 P假设有如下定义:9 q4 x5 N' `) M7 \9 Q* r- n/ g' V3 p+ }
var8 Z0 m1 F9 w: W+ h2 G! T: z
p:pchar;
' q8 M2 g7 m+ |' S& S9 F' H" Ws:string;
4 T6 D* A/ s; t1 ass:tstrings;
7 T4 E! t4 g8 x" U# Wbegin5 O. }* M  w) N+ [
ss:=tstringlist.create; // 开始时一定不要忘记创建ss
8 F$ n. f. J) Y, H2 L. U# S4 xss.text:=s; // string –> tstrings
" V0 g2 _2 @, ~$ H- M5 Ys:=ss.text; // tstrings –> string
2 m$ p$ f% R1 ?; D  Q  c! E" I! Up:=pchar(s); // string –> pchar
5 k3 A; x( Z5 e* k7 es:=p; // pchar –> string
( i/ D0 z2 g5 [showmessage(s); // 合法语句9 K: [! ~! B9 {, ]8 @6 a* |
showmessage(p); // 合法语句
1 P/ v# R6 A3 o… …/ v4 d/ i) \  |
ss.free; // 最后还要记着释放ss占用的资源
# I  t8 j# O$ S, @3 Lend;
  F3 D' F* t- Z
% B/ Z' F& b9 W2 z8 _8 f4 N' H' T- i' s# L

) C5 _& W! d5 o, R0 T) ?% w在设计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