打印

delphi 技巧合輯

delphi 技巧合輯

INI文件的操作要点: M4 s0 n/ w+ m% z, _
(1)在interface关键字后的uses子句中加入0 E: U$ b! |5 F7 X, Z3 E
uses …,inifiles;( t5 O, |$ a0 J9 {
(2)设置变量:var inifile:=TIniFile;
4 C: J% ^- Q! E! ]( `! |(3)使用前,一定要先做:
6 I; U/ Z6 R4 r0 vinifile:=TIniFile.Create(inifilename);8 C6 d+ i0 P( a
我在这里绕了个弯子,写成+ E- o! B( v; O) ]3 b: L' X, S# @  g
inifile.Create(inifilename);2 L6 U6 h. o* W# b0 o( R3 J

( E( D; h9 z! T" pTShiftState用来检测CTRL,ALT,Shift,以及鼠标按键的状态,
' v& m# m7 o; ~2 y8 ^9 a常常用在键盘或鼠标的事件处理程序之中。
9 h! t) i4 g! u" A: M% v
' Q  ~( [; G5 S5 |DCU文件(编译的库单元)的重用
  [. X" [% A8 o) E5 o# n(1)在interface里的uses子句中引用。如Windows,Dialogs,
2 K. X' c( D4 l  [" i等等,要求被引用的DCU一定要放在Delphi 3\Lib子目录中。+ ~: z/ t. ]7 W# a. _& U6 f
(2)在implementation里的uses子句中引用。如果是自行编写的
0 e" J# V- u, t$ `& j" t* j! oDCU文件,应采用这一方式,并将被引用的DCU文件放入当前
' @- ?4 t+ K: x  U工程所在的子目录中。9 o0 [: i  B4 R0 s3 y
executefile函数(在FmxUtils.DCU中定义)不能用在FormCreate
) T: j; J1 ]0 i" e9 q7 f事件中。真奇怪……
7 {8 ]* P( l6 G, |; h6 w' S3 S
; ^! @) T% q% r6 o8 t! r内置的版本号控制功能
; c9 g3 |2 p( r8 ]5 W3 f3 k在Project Options中的VersionInfo项里,有版本信息的定制,
2 y8 }* S& H! E7 V: }; V包括一个有趣的版本号自动增加功能(Auto-increment build
) h* _. Z9 c' k! knumber),即每Build一次,版本号中的Build Number加1。选中
0 q; h* W- ^9 o/ I( @Include version information in project,编译,用资源管
8 J- p/ C0 V2 I6 S; D理器里找到生成的.exe文件,点右键,查看“属性”一项,就4 D( t) \# F& C. h, @: V
会看到在属性中多了一页“版本”,里面就是你刚才输入的各2 [5 w3 q7 B" P
项内容。2 d/ A, I) J, V  q( ~, w; B  E

5 O6 ?6 |: C8 h. }7 P; d# e7 \6 H( ^4 ^$ q
定制Speedbar! t2 }0 p; R- ]: i/ L5 {
右键点击左上角的加速键条(speedbar),选中Properties,
6 x. j. M" o: Q) W4 Y; ]) b在列表框中找到你想要加入speedbar的命令按钮,将它拖到
. \" l( Z  G) J$ k& S. f( }  n1 lspeedbar上的合适位置即可。如果speedbar上没有多余的空间% e8 _1 M& P: A$ {9 s
来容纳新的按钮,可把鼠标在speedbar右框处变为双向箭头的) d; S9 o# s7 p  R4 b
形状,向右拖动一段距离,就可腾出空间。如想删除speedbar0 P) h# J) C- F3 m5 f8 f' u! d
上的某个按钮,可简单地把它拖出speedbar的范围,就能删除。
: R- ?; ~& j  R  A) M2 h& d4 b2 g" y6 D% I- g" k
1 S- d  {* Z2 r! L4 @4 h  f! e
计算出的字段
1 z6 s1 d) H9 I/ {4 F4 c# l/ G在写一个程序时,我要在DBGrid中显示出一个memo的部分信息,当我把那个5 V# E& K0 ^" ]1 j
memo字段放进去后,运行时只能显示出“(memo)”字样。从书上找到计算字3 f  \! c' j6 L) b/ i$ {
段的用法后,我在TTable中增加一个计算字段MemoHeader,宽度为40,在此$ ?5 d' v3 e3 r+ b
TTable的OnCalcFields事件中输入:
" _; e- M7 U9 `# Y1 }+ Pwith MyTable do" C: ?0 h. W2 U/ V
FieldByName(‘memoheader’).asstring:=FieldByName(‘memo’).asstring;
1 }( P2 z) R  x* m: S- G: H' u- |在DBGrid中放入MemoHeader,运行,OK!
( F! B) O& l) w* L- Y# U+ i2 L% e" K% s3 ^# A6 j# u1 p" B! ]
7 n' z, H0 S* Y* Y7 x5 K
字段编辑器1 R) m) K8 N$ q5 A
解决了上面的问题后,我继续学习字段编辑器的作用。原来,DELPHI通过字+ @" o4 y) Q8 ?) @9 r, L) j
段编辑器,近乎完美地实现了数据库的字段级的控制,这包括:, {, p0 F) M( J5 G
1)字段在DBGrid中标题、宽度、能否可见;% c# T  [* f) x' e
2)字段的显示格式和编辑时输入的过滤条件;* {3 P, B/ ?; b' d  ]7 D
3)字段是否只读;1 R! d7 {# Y& o2 w0 e
4)字段的类型:数据字段/计算字段/查询字段/内部计算字段;
3 a1 X0 {+ O, K- N9 g5)字段的显示/赋值/修改等事件的定制。
( C3 J- `9 z; O4 E; S2 p) W" p$ l0 @" d" k3 g7 v

2 f% z8 R" V( [, _设计Form时的快捷键5 [0 o% C& ~! B' n; q
Del 删除所选组件
9 y  a/ Y; }9 ?& K- SEsc 选择当前组件的容器(通常是Panel,Group或Form). Z3 E2 [/ p, {5 V4 c; x
F11 在Form或Unit和对象检查器之间切换
- h2 ^& h! W) R  {3 B/ TF12 在Form和代码编辑器间切换
1 q* v4 |& e- X1 B) d' g7 a6 cCtrl-F12 显示“查看Unit”对话框' j3 f4 u6 f% _3 w# I" P
Shift-F12 显示“查看Form”对话框
& e& v+ t! M' ?! CTAB 下一个组件( J  ~0 S$ W, Q3 R* X! W
Shift-TAB 上一个组件  o9 R2 q. h- L  T& q8 J# I4 v$ s3 j  `
方向键 选中此方向上最近的组件
; Z' `+ I3 U( |% q% N3 U5 g; k, cCtrl-方向键 将所选组件移动一个点
- C" [4 o! e6 M( j' UShift-方向键 将所选组件改变一个点的大小( I- g) s+ O( y' c' C0 o6 j) N
Ctrl-Shift-方向键 将所选组件移动一个格
9 S" n; t3 E+ {$ `  E7 JShift-click 按住Shift键再用鼠标点击组件,可以选择多个组件。" K" W2 p- _( x+ O) ~) @
–= 下面这条是我摸索出来的 =–
" c, H2 R. C3 L- B. t+ Z6 b! XCtrl-drag 按住Ctrl键在一个容器组件(如Panel,QReport,Groupbox等)
" O+ C0 i+ n/ v& \" h  Q3 w里拖动鼠标,可强制选择鼠标拖过的矩形框中的所有属于此容0 E; f" R+ `2 h
器的可视组件但不包括该容器组件。
& }9 V' S) k: l9 [
% e( v7 z. P/ ]8 o2 h
+ _# S3 k8 S5 X: a3 U使用QReport的若干经验; A+ d2 Y3 g* g5 E" C0 \
1)QuickRep1.DataSet:=query19 L; K( A* g/ j: l
不然无输出结果
' @0 T) R! r1 @' |2)从qrpt2man.doc中查知,格式化输出结果的方法是:, K8 t6 g& R. K( [' J3 }) k; `# p
在QRDBText.Mask中设为.00;0,将使输出带两位小数。0 V0 M& u. u: p$ o# L4 U( B
3)设置Group时,先加入一个QGroup,再加入一个QRBand,将QGroup的. s  y' w! ?1 N8 c! G1 J3 Z' z, n# c
FooterBand设为刚才的QRBand,就可将其联系起来。
" t5 R- T. A9 @* c  l* q4)在Group中打印的合计数,其ResetAfterPrint设为True,可实现分组合# j+ p) h" w( i+ a7 R: [

& B6 x/ G' u' U& d+ i& }: a$ Sformat(‘%*.*f’,[8,2,123.456]); //等价于format(‘%*8.2f’,[123.456])
# H; |/ m+ {- d% l: T6 [4 iformat(‘%d %d %0:d %d’[10,20]);4 ^" S! C# q. @2 c' k% a( v

! E5 S9 [, f/ l. b/ H) g
/ B% ~- g$ ]# h, B2 S6 [; i9 P9 O8 r1 S; |( ]8 _
播放一个wav文件1 G2 Q1 v3 n* y. y
use mmsystem;
  ?0 E. R; o# O+ D  R. vSndPlaySound(‘hello.wav’,SND_FILENAME or SND_SYNC)% y1 Q. ^% t# o) V8 U+ f% X

3 Q1 ~2 s6 |# p# p; H+ T使你的form适应不同的显示分辨率
7 U% A% @- V8 a$ v( K* k- F2 B假设你在800*600的分辨率下设计的form,第一步:9 K" d6 J" n/ q" X
inplementation7 j; w. ~; y$ \/ k% m" F
const! ~# q% n# p( D
ScreenWidth: LongInt = 800; {I designed my form in 800×600 mode.}
! G* O! U# r  u* B: {ScreenHeight: LongInt = 600;2 r1 s7 J' P/ V* U9 Z) c' |
# o& g* Q7 f/ z  H6 i; j3 z  V
{$R *.DFM}
0 g) s5 C  H, D3 E  R
6 Z  A  `6 N' |) p  R: t$ z2 ?procedure TForm1.FormCreate(Sender: TObject);
# y  k' F( e# Fbegin
2 f5 f4 L+ S+ F/ }  w7 jscaled := true;2 j, L4 @% N; ^$ X' `( Z
if (screen.width <> ScreenWidth) then" N! L6 f3 f! e) |  t; d3 z
begin, b' H, V' y8 s! w. `3 q, j
height := longint(height) * longint(screen.height) div ScreenHeight;' p( _, z; [& j2 @7 n5 w# b! L
width := longint(width) * longint(screen.width) div ScreenWidth;. e+ e5 z) Y& I4 j( Y8 V. }
scaleBy(screen.width, ScreenWidth);
- j0 o1 l; g& N1 D. Rend;
* G' ]+ W, _0 T/ ?9 Pend;
5 p% R! v& \4 r. P6 v/ l$ x/ j
) v# k$ o- c* _1 ~! K- Y下一步,要让每个子控制的字体改变到合适的大小:4 K* a) B( E9 E: _. d8 S3 |
type
- ^( k, U( a! s0 [; ]; M7 YTFooClass = class(TControl); { needed to get at protected }" |! n2 [! R5 g& v
{ font property }+ J" l' c- N1 `% W% Y# e
- i* ~# M7 e: b% ^  h9 P6 N3 `4 W
var+ Y1 U/ n  {0 b2 f# l- ]3 F  T, ?# }3 O1 R
i: integer;
" B4 k0 i# C2 y; P2 N9 ^begin0 S1 g2 a  ~9 o8 d/ x
for i := ControlCount – 1 downto 0 do5 B- h. w- V/ k0 f( h3 l
TFooClass(Controls).Font.Size :=4 L% o" J7 t1 B- D- Z* u9 I2 Q" T
(NewFormWidth div OldFormWidth) *, U6 |& z/ c& o
TFooClass(Controls).Font.Size;* F. E+ x5 E3 H, V" R( z
end;
4 W! P) K1 w$ _! L; b: M
0 t/ T8 R- c3 V" C! \1 q用raise引发一个错误处理例程- u) F/ v' b- I
示例:先给出下面的定义
  o" U7 g8 A1 @4 _type EPasswordInvalid=class(Exception);' H. s$ x3 h/ R) X
这样你就可以随时引发一个”password invalid”的例外:& n0 N% k+ B+ A# {1 a7 v
if Password<>CorrectPassword then
0 J0 D! a2 e- X; s  Praise EPasswordInvalid.Create(‘Increect Password entered’);
- B# h9 ]- T7 a% ?) V2 {: }运行后,出现信息框; o* x! Q1 b1 B$ B% f' u! Q$ F
Project Project1.exe raise exception class EPasswordInvalid  d% T9 J9 }1 t
with message ‘Incorrect Password entered’. Process stopped.% e4 ^* G7 z8 [5 l' k% h3 m, }% X- c
Use step or run to continue., v% `! j' l( [1 {
再按Run按钮,出现一个信息框:
) z/ N& K* q0 `+ r6 i+ JIncorrect Password entered.. P& {+ n- L2 y# B2 C9 c! ^4 V) ^; n
6 ^! M% s+ F6 C, s$ S# A* g
$ q" t  @; H6 [3 ~# w4 X% d5 |2 q) M( `" x
从DEMO例程中学到的若干小技巧
* H3 r2 A3 ]: B% a+ @; c在demo\internet\http\webbrows\main.pas中," M) }2 `3 q+ U3 k# w4 {
procedure TForm1.DocumentSourceClick(Sender:Tobject);
( y' |/ M+ n+ G/ ]7 a7 Jbegin6 R+ M! r+ Q. o" Y: h
with DocSourceForm do
+ C0 F2 K6 n0 w2 L. ~2 Vbegin
, m3 u' |! _1 }! A; D6 dshow; // 显示HTML源码的FORM- h% o9 S1 x* |5 i1 l2 S8 C! ~9 h2 G
Memo1.lines.clear; // 清空memo1中内容
0 C) I6 [: d) S" ~  A) [6 bMemo1.lines.add(HTML1.SourceText); // 植入源码8 p) S% R+ U  W# p
Memo1.SelStart:=0 // ***
9 W0 D# o' l- E. J7 f5 NSendMessage(Memo1.Handle, // Memo1的窗口句柄
' l9 e7 A# Y6 `" @' nEM_ScrollCaret //将Edit Control中的caret光标滚动到视野中! c; W3 i! K- v  M
0,0 //这两个参数暂不使用" o7 N* [+ m' D3 o7 |% {9 h
end;+ C' R6 K+ I1 C$ s  y$ S
end;4 b% I/ j3 s2 o
(此SendMessage系一WinAPI调用,给一个或一组窗口发送消息,直到$ p9 S  A/ z; X) F8 y
相应窗口处理此消息后才有返回值。相似的另一函数为PostMessage,
6 U0 i$ Z+ p/ d4 ~- w+ z$ @5 k它将消息放入消息队列中后立即返回。)* d' N9 c, H* T% Y3 g
*** 清空当前选择并将光标移动到指定字符(0代表第一个字符)。如同时2 v/ F1 L" F9 V) d: k/ H6 f
设memo1.sellength为一非0值,可选择一段文本。
# B0 R' |; W. [  _! a+ F
7 W$ Q- H( r3 k' p/ R1 J
  I3 o2 U" ?9 y  K: i3 B1 W9 ~奇怪的I/O error — 我在开发过程中发现下面这两条语句" B7 M" |1 Y: k1 ]8 K
assignfile(fDesc,CDDatadir+describefile);
& j9 y4 u1 y0 [+ @9 Creset(fDesc); ) e& t$ ]5 ^* x3 Z# b7 a8 C
每当我第一次运行到这里时,总会出现 I/O Error 183 的错误.
/ X! a- u/ e/ F6 S5 I6 j7 ~2 r最后我想这也有可能是没有清除 ioresult 的原因.在两句之间加入
6 u6 t( N* g" e2 R) R2 |/ Bif ioresult<>0
! ^3 P  h# Y2 r. Q, g1 \then; ' A$ K) C& q. }
oooook! 可以了.
- y5 q$ B8 n" H' a- J" J" C/ T$ ]6 ~/ ]2 W0 j$ w) e

& O1 M0 a5 M" B, B% {! b7 N值得注意的I/O error
# \5 k( U# n4 X, C9 m0 W  ]AssignFile(F, fname);
4 n) _  \4 `# Z+ o2 ]Rewrite(F);
5 n. I4 t( b. w2 r% U# |当文件 F 经 Reset(F)打开的情况下, Rewrite(F)会引发一个异常: I/O error 32& j, S% ~, t* l1 R
反之,经 Rewrite(F)打开, Reset(F)也会引发同一个异常.( B  ~; V8 h! e0 |
Reset(F)两次,closefile(F),再Rewrite(F),或反之,也会引发同样异常.  O* L' n& }# f# C1 t2 D( _

2 G7 U1 N6 ?, }& C3 ?% l1 D9 p' C- i: p% R# b5 H8 t& P

) w- r: @8 l: Z: Z$ a% y: ustring和pchar的相互转换:+ H/ e* {. f4 C& v* a' Z
string –> pchar: pchar(s) t6 v; w/ Z8 C# }( v
tr:string);
  S0 \5 m4 G5 [7 u  q7 O* spchar –> string: strpas(p:pchar);
9 @2 I, W  `9 G; h1 O
1 R" N! n* r3 l- a' E7 J6 b4 s- o4 x' _

7 a0 d- z9 ]$ h- L$ K( G在Delphi代码中定义数据库7 D$ X7 t9 R2 R$ M5 P
procedure tform1.create_tbl;9 j2 k6 t4 c' ^# V+ [1 q6 o" B# ~; p
var tbl:ttable;
5 M- K( h6 u* ^- |1 p) r! cbegin
; z3 d% b8 @5 p0 Mtbl:=ttable.create(self); // 如没有声明中的”tform1.”,Delphi不认这个self) z+ Q- D2 ~$ p
with tbl do& b9 R! G5 c* K+ d! b7 t
begin" B: L$ |  U4 H% M& S5 b
datebasename:=;dbdemos’;
" t* y# [% o; c- ltablename:=’my_tbl’;9 ~5 K! p* C. w8 `) `
with fielddefs do2 V! _; ?+ h3 Y( ~1 G# ~
begin. v" F7 X6 Z9 g9 K' o# O% e
clear;
. w0 L- V6 M6 Uadd(‘No’,ftInteger,0,false);6 [- @$ l4 @% c) O) m7 h
add(‘Name’,ftString,0,false);
7 b/ a! T! \6 V% _" k  N, u' a1 \' \2 X, @
end;0 S9 P+ `8 k, c6 B$ T% x  f7 D: I
with indexdefs do
1 U4 a8 y, z# |3 B. P! W. h# Ebegin
4 v# r* G5 ~" Jclear;5 p$ ~+ r1 s3 d. V
add(‘primary’,'no’,[ixPrimary,ixUnique]);$ s' j; f) Y$ N' I9 [
, h# t% k. w7 B2 U7 s) u5 S$ _$ x
end;) E2 t, H2 Y+ J+ v" L
CreateTable;! p) Z7 u* m1 M  D' w
end;
* H7 O4 ?8 T  r" L8 Eend;
7 p6 G- z  I' Y8 ^- P  e, b) r* q1 A, X; n* m9 C, f' v
" `' O( ^# V  E. e- \
string、TStrings、pchar的相互转换(这里是我的个人经验)
! w3 y2 D+ X$ S0 C3 @+ ?* S假设有如下定义:
4 a3 C/ S7 ?; E0 Gvar
) C: y& V7 S$ B* }) ap:pchar;
- c4 D7 q/ _* o+ Cs:string;0 ^( D2 X( K8 w# ?# d
ss:tstrings;  L0 y' \5 W8 S  i
begin
0 ]) f8 _* C3 l  l! d; R! s9 y0 Zss:=tstringlist.create; // 开始时一定不要忘记创建ss; _1 Y7 p) p9 ~! B/ }' a
ss.text:=s; // string –> tstrings
0 D7 `7 i$ e, r# x" e, |$ ^7 Us:=ss.text; // tstrings –> string) E- c. Q& N2 {2 }
p:=pchar(s); // string –> pchar
" U5 G4 m. B0 ^6 V5 |$ [s:=p; // pchar –> string
% j% Z1 I8 I, J: l, B* c1 Gshowmessage(s); // 合法语句/ `  F/ e: v* f. @; W% k
showmessage(p); // 合法语句' G6 E# A8 z6 n3 ]. u0 V0 q+ Y
… …  D8 l# X3 t6 W' q+ N) Q" Z
ss.free; // 最后还要记着释放ss占用的资源
$ V" B+ P7 [" j& s, Vend;
4 ?! z2 e) J4 V( {* v& c1 |% M+ B7 K6 {0 G) d% \

  N2 r0 @1 D# M7 I1 ?( K9 R% x+ {! t/ C/ s9 I% [
在设计Menu时,常用的ShortCut可从下拉菜单中选取。但我发现可选的ShortCut有些不在列表中,如ESC,Ctrl-Shift-A等。我试着在ShortCut项的右边输入:ESC,竟然成功了。再试Ctrl-Shift-A,这回Delphi自动把它变为Shift-Ctrl-A

TOP

發新話題