打印

delphi 技巧合輯

delphi 技巧合輯

INI文件的操作要点
7 }! L! {2 X2 ~' N: ~- {(1)在interface关键字后的uses子句中加入
8 k) S3 P7 [" l* _8 E5 u" Luses …,inifiles;
, `1 _4 i  l" d(2)设置变量:var inifile:=TIniFile;) d$ P- A3 E2 m& W0 `% {7 I/ o
(3)使用前,一定要先做:( F& ?& @4 ^7 h; t6 C. O
inifile:=TIniFile.Create(inifilename);! ]$ C. \0 N7 h+ ~" [+ |3 m
我在这里绕了个弯子,写成5 K$ l. W* ?. r! }
inifile.Create(inifilename);
: S; Y, f& K! C5 f9 s( @, q3 `9 g' ~5 M  _1 ^+ ^
TShiftState用来检测CTRL,ALT,Shift,以及鼠标按键的状态,
! E( p; p/ T: _& p, E$ R, X常常用在键盘或鼠标的事件处理程序之中。/ r; Q; _, K* [5 t7 P
. g6 \" v! L7 C+ p
DCU文件(编译的库单元)的重用
7 U+ r1 S$ k6 B  }(1)在interface里的uses子句中引用。如Windows,Dialogs,. i* T8 o3 A/ c& o. @* a
等等,要求被引用的DCU一定要放在Delphi 3\Lib子目录中。
+ B( N- c4 |8 W2 B4 |0 Q(2)在implementation里的uses子句中引用。如果是自行编写的
" p+ q1 ~3 V  N. X6 WDCU文件,应采用这一方式,并将被引用的DCU文件放入当前8 S) n( n/ j* Y6 d: Y! J; x9 j
工程所在的子目录中。
6 ~$ e7 |6 H$ `& V7 T  Dexecutefile函数(在FmxUtils.DCU中定义)不能用在FormCreate
" t8 q4 B3 s& S/ _- J事件中。真奇怪……/ S3 j' }; Z+ X' T- g$ G" a

. Z: Q7 s% F! _0 J& L内置的版本号控制功能
0 S) `6 M1 w% b& o. R) [* ?在Project Options中的VersionInfo项里,有版本信息的定制,
: S& z6 l" C) ~7 o* t2 f包括一个有趣的版本号自动增加功能(Auto-increment build4 f( ]9 d; [( T, S
number),即每Build一次,版本号中的Build Number加1。选中4 w7 k4 j- H  \( Y& @# Q' U
Include version information in project,编译,用资源管
8 G' b8 i' u6 S7 u5 t- t理器里找到生成的.exe文件,点右键,查看“属性”一项,就" w6 M4 V+ _3 F% \' Q
会看到在属性中多了一页“版本”,里面就是你刚才输入的各
( L: l. F) c# w' E& c$ k4 t! e, R( C8 ]项内容。1 S  U' F0 w% D- V

+ t! [4 o- g5 E% @9 d0 c$ |
) X) G- T8 r4 p3 w! g定制Speedbar, W* B; V$ o% `" @% k
右键点击左上角的加速键条(speedbar),选中Properties,
' ]* J) Y; [4 T( c' s在列表框中找到你想要加入speedbar的命令按钮,将它拖到2 F/ k- Q+ s" W% A& I& I; y
speedbar上的合适位置即可。如果speedbar上没有多余的空间
; I! X! `- B, @" C3 J来容纳新的按钮,可把鼠标在speedbar右框处变为双向箭头的
' `7 j  O# K7 ^8 s& F, Z9 S形状,向右拖动一段距离,就可腾出空间。如想删除speedbar
4 m5 x7 g  B+ ^, Y" ?; F上的某个按钮,可简单地把它拖出speedbar的范围,就能删除。* f2 f/ q0 ^2 C# }/ M$ y

$ `5 ]; a5 r8 ~4 ?6 K: i3 i6 [1 i+ ~- W5 Y6 S7 D) U
计算出的字段, k0 Q- x; ?1 r8 u
在写一个程序时,我要在DBGrid中显示出一个memo的部分信息,当我把那个
2 ^3 X: k; n) G7 `  z. L$ @; {memo字段放进去后,运行时只能显示出“(memo)”字样。从书上找到计算字9 O" |1 N, N2 `1 V5 p  M8 I) W
段的用法后,我在TTable中增加一个计算字段MemoHeader,宽度为40,在此" C0 H) Q; y8 d4 y  P, s- k  g  |
TTable的OnCalcFields事件中输入:  U- a& A9 j7 u& ?2 y# @2 C
with MyTable do
  f3 X3 G" q! G2 A5 f; t! _! H3 kFieldByName(‘memoheader’).asstring:=FieldByName(‘memo’).asstring;# ]5 E+ ^8 ?8 [; W' e3 B
在DBGrid中放入MemoHeader,运行,OK!
% M# V' [6 E- f2 V2 i( x& l& _4 N
# ^) L( L4 [. S+ B! Y
字段编辑器
0 j# B/ T. O' g3 m# Y4 I解决了上面的问题后,我继续学习字段编辑器的作用。原来,DELPHI通过字
4 J9 J! }  V) ~; B' J" A段编辑器,近乎完美地实现了数据库的字段级的控制,这包括:& i# u0 a& q2 A
1)字段在DBGrid中标题、宽度、能否可见;. ^+ }; X3 ?, c* v3 k, }" n
2)字段的显示格式和编辑时输入的过滤条件;
( R8 }3 U/ C1 ]' H) p, y3)字段是否只读;
% t+ c* p& |! d$ ~) i4)字段的类型:数据字段/计算字段/查询字段/内部计算字段;/ K- {! M  z1 a
5)字段的显示/赋值/修改等事件的定制。
: }8 z7 P3 J! [  w6 h/ d% g9 G1 Z5 h4 k/ m3 W

. ?9 Q  x4 D. v设计Form时的快捷键. w( o: |1 e- H
Del 删除所选组件. b2 V4 T+ Y. s( r
Esc 选择当前组件的容器(通常是Panel,Group或Form)! ^% Y* S% l* @3 f2 \
F11 在Form或Unit和对象检查器之间切换
8 O  I& ?% I: v) |F12 在Form和代码编辑器间切换
8 P6 O+ V  |  t: Z& r0 aCtrl-F12 显示“查看Unit”对话框
3 A! G3 y$ T0 R! V3 z$ x% y1 \Shift-F12 显示“查看Form”对话框
2 B: B, h, _  M  OTAB 下一个组件  h# i% v0 W6 e& `9 X; ^
Shift-TAB 上一个组件
/ e0 ?5 Z) E8 t6 {. v% K; G方向键 选中此方向上最近的组件
  t4 s: W, `; T# {/ hCtrl-方向键 将所选组件移动一个点! h4 \! J2 S4 E' w, Z4 x
Shift-方向键 将所选组件改变一个点的大小' E7 o9 E# X9 B/ V8 ]/ b
Ctrl-Shift-方向键 将所选组件移动一个格
7 \. j% ^% U. ^3 F* ]; k0 a) pShift-click 按住Shift键再用鼠标点击组件,可以选择多个组件。
; [* A  I# b* j  s–= 下面这条是我摸索出来的 =–
! B# N1 x  ?) R8 q) RCtrl-drag 按住Ctrl键在一个容器组件(如Panel,QReport,Groupbox等)( O* m# v! W* K% v
里拖动鼠标,可强制选择鼠标拖过的矩形框中的所有属于此容9 @0 L: X! Q2 y2 i; P7 L
器的可视组件但不包括该容器组件。8 g, P! x5 v+ i' T

6 v, c* i) y3 E; C5 `4 K9 \, v5 f5 u& K; `7 W
使用QReport的若干经验: ?. Y) P9 l4 {# D5 V
1)QuickRep1.DataSet:=query1
. K1 Z! b- f+ |不然无输出结果
+ Q' z" `7 g7 M2)从qrpt2man.doc中查知,格式化输出结果的方法是:
( d# r- S# V7 e在QRDBText.Mask中设为.00;0,将使输出带两位小数。
; l$ h" I) k1 T9 m. @( k3)设置Group时,先加入一个QGroup,再加入一个QRBand,将QGroup的1 v7 J; e, r! J# S4 ]  d
FooterBand设为刚才的QRBand,就可将其联系起来。
8 C" ^1 D3 F5 J1 x4)在Group中打印的合计数,其ResetAfterPrint设为True,可实现分组合+ ]( C4 L$ ^/ W8 |

- E0 u2 [: B) k  @9 K9 p$ vformat(‘%*.*f’,[8,2,123.456]); //等价于format(‘%*8.2f’,[123.456])9 S9 Z4 a- M6 {& u3 y% @
format(‘%d %d %0:d %d’[10,20]);
: @9 q$ J8 E' Q: H
# H; W# A8 L  V6 o( H8 V3 ]! Y( a* n8 R: t
* w1 S8 \3 N6 I, [% X4 b. {# v5 d5 V5 }; C& p! {8 ~* q5 ?
播放一个wav文件
0 g6 f7 w) O- ~, |! ouse mmsystem;
" W$ B. A/ s  ]3 u' n' ESndPlaySound(‘hello.wav’,SND_FILENAME or SND_SYNC)8 P* m) _" l3 Y$ O: Q4 |# {/ h
/ S& G7 h4 W9 r  [0 _2 `
使你的form适应不同的显示分辨率
3 ]* L! {' v* Y) N$ c9 T) O5 O假设你在800*600的分辨率下设计的form,第一步:8 e" i! _' ?1 ~8 y0 g
inplementation7 }4 E0 R, B6 u, w0 y5 P
const
" F$ v) `9 u: h2 `ScreenWidth: LongInt = 800; {I designed my form in 800×600 mode.}
6 Q4 \( H" f) N  [ScreenHeight: LongInt = 600;6 d  J4 Z1 C# |, ~% l: B
: @* @. t7 u" i5 C. ^
{$R *.DFM}/ y) L0 P3 l+ B$ H" S8 b+ c% }

" O: j/ t# n, _! k0 K# yprocedure TForm1.FormCreate(Sender: TObject);& Y( ]. I# E5 v% n
begin
8 [) w, U! O: q' O2 kscaled := true;8 S+ C) s2 i# i  s2 p4 P
if (screen.width <> ScreenWidth) then
' |" Z- A4 n9 S* l- _. Y+ ^3 ]begin( }$ k7 f$ l! k+ S: N7 O
height := longint(height) * longint(screen.height) div ScreenHeight;
5 ?3 s  Z  b8 w7 `/ k# O1 kwidth := longint(width) * longint(screen.width) div ScreenWidth;# {2 ^8 G5 y: `$ j/ y- D
scaleBy(screen.width, ScreenWidth);
7 K% _6 }, c, M. ^) U, Dend;
5 m4 _8 _! I, p5 Send;
1 l% R8 W- ]1 E( L/ y& k+ t( `
9 @; D  l" T6 a1 J3 H; G下一步,要让每个子控制的字体改变到合适的大小:
% F! p5 g, I3 d- a# Ltype3 Z) k8 D, f: U
TFooClass = class(TControl); { needed to get at protected }: ?1 z1 u& N- J; f
{ font property }
9 t/ Y! [& ~- P8 N7 h6 u5 B
+ w, _9 e( O* ?* U: d6 yvar) W1 l' @' U4 X/ ?) `7 z
i: integer;* K, Z8 F, K% U4 n1 i& c
begin& y. ^: y6 L; q: \% D
for i := ControlCount – 1 downto 0 do
. ], G  H3 u1 y- PTFooClass(Controls).Font.Size :=
% }( G( b% r+ A% b(NewFormWidth div OldFormWidth) *, T# }2 p1 z5 [3 e+ ^
TFooClass(Controls).Font.Size;
5 \% M+ s8 @0 r: w# B1 \( x9 lend;# g& J7 `; W4 R0 R6 o2 T% A

+ Q9 o: m! {9 k% \+ |) }: n用raise引发一个错误处理例程
/ N4 |9 A) u6 o8 z示例:先给出下面的定义
( X& s; \  I3 j7 N2 Ptype EPasswordInvalid=class(Exception);
8 H6 ~! m7 X3 r" @7 C, E, z. c这样你就可以随时引发一个”password invalid”的例外:
1 b% g$ Z7 G5 Y& {* Wif Password<>CorrectPassword then! D# g8 E7 |- d
raise EPasswordInvalid.Create(‘Increect Password entered’);
& H* I3 D8 @2 P8 ?2 z2 N3 m3 b2 @运行后,出现信息框. W2 c' ^0 s9 ^  a5 L
Project Project1.exe raise exception class EPasswordInvalid5 I5 i. u, G9 Y! I
with message ‘Incorrect Password entered’. Process stopped.
! ?. O% K, O2 ^+ I. X. z! H) T( C2 uUse step or run to continue.% ^: c  x: B! W% Z- U' v" s) _
再按Run按钮,出现一个信息框:7 v6 T; r6 l# G0 z# i
Incorrect Password entered.3 ^& h/ `3 f. [  d4 w2 [( U4 w& f# O
! u! }" Y' T  j& \2 v

- l7 }% E( K6 N从DEMO例程中学到的若干小技巧, s" p! y& p# s
在demo\internet\http\webbrows\main.pas中,' ]% `* J+ U+ h+ C: F/ W
procedure TForm1.DocumentSourceClick(Sender:Tobject);6 G8 o' F2 g  v
begin
" G% p2 f; y8 Xwith DocSourceForm do
: P' H/ X1 o9 q% pbegin- I) X/ h$ h$ B1 f% q# s
show; // 显示HTML源码的FORM
2 `! T1 d& ~3 R! A4 SMemo1.lines.clear; // 清空memo1中内容
) V, f9 S; r1 o/ uMemo1.lines.add(HTML1.SourceText); // 植入源码
( S5 u% q+ H2 bMemo1.SelStart:=0 // ***/ ^5 d2 X, Y8 |
SendMessage(Memo1.Handle, // Memo1的窗口句柄) s5 v$ |3 }+ B) k* y/ m' Y
EM_ScrollCaret //将Edit Control中的caret光标滚动到视野中% }+ w: g3 A" ~
0,0 //这两个参数暂不使用
/ f  j1 _; P( {( C; Uend;, c, o4 w% }+ M4 x8 A
end;
# K% N/ I6 @( g+ g) ](此SendMessage系一WinAPI调用,给一个或一组窗口发送消息,直到) ]8 t2 ?$ @, w* c6 }% l% T: N
相应窗口处理此消息后才有返回值。相似的另一函数为PostMessage,
( F" u, h* N* }它将消息放入消息队列中后立即返回。)
: B" Z6 w! K2 M" ~/ d- D3 J*** 清空当前选择并将光标移动到指定字符(0代表第一个字符)。如同时7 }3 @2 D/ Z- K* B3 x. k0 M
设memo1.sellength为一非0值,可选择一段文本。
5 L( P! X% P7 G) z0 b8 ?! }1 o$ I6 _& v, i* e/ A- ?

# }  T  J' \0 w* Q- ^奇怪的I/O error — 我在开发过程中发现下面这两条语句
" H! q, Y; X! o4 qassignfile(fDesc,CDDatadir+describefile);
# x7 j* L/ x7 ]  hreset(fDesc); - x7 i) I* u4 r8 F7 @( [; r
每当我第一次运行到这里时,总会出现 I/O Error 183 的错误.9 \( S( C9 }. f& I/ ~! Y
最后我想这也有可能是没有清除 ioresult 的原因.在两句之间加入
9 e+ W& u0 i( A, Z8 c# l% mif ioresult<>0& c1 L6 n: M3 q: |) G' b& P
then;
0 W" q8 ?( Q* @oooook! 可以了.! r  V! u, R. W+ j
2 D6 d. u6 Z/ S5 r. M

) n* \% R9 e+ k. V2 X值得注意的I/O error4 p% r* h& `! m9 B" h4 N0 Y
AssignFile(F, fname);
. {1 ^# R/ q3 p& U" A& uRewrite(F);. L. J5 G6 O  N/ s2 f
当文件 F 经 Reset(F)打开的情况下, Rewrite(F)会引发一个异常: I/O error 32  `% k. w$ y- K' Z8 h2 c
反之,经 Rewrite(F)打开, Reset(F)也会引发同一个异常.
& W& S, {, G. F4 ^Reset(F)两次,closefile(F),再Rewrite(F),或反之,也会引发同样异常." V- [0 C7 ^0 C; i" k3 r

- f0 G' p" r: y& C; D2 H
5 n0 v6 N' A7 ]3 O  ]0 P( S
* b5 ?2 q9 C  g& estring和pchar的相互转换:) p: x7 w2 Y& N& B2 Q8 w. E# `' ^
string –> pchar: pchar(s
0 y* `* [/ M' O4 F" K& \7 h7 Ntr:string);; H& V& Y0 _5 p6 o& p8 w- Z5 P
pchar –> string: strpas(p:pchar);6 ~3 Y  S7 P8 P6 r1 p- J  K

7 Q: S9 |8 B! u1 e/ v) V: _. \; v0 M+ A7 I
& `' n1 i/ E- u$ d6 ]
在Delphi代码中定义数据库& M& u- T2 I. k+ Q( B, W
procedure tform1.create_tbl;/ F1 ]5 o. K2 n9 g$ Q# s. y
var tbl:ttable;9 q6 H2 z' p# W2 a
begin7 l! |8 M/ k( B. c
tbl:=ttable.create(self); // 如没有声明中的”tform1.”,Delphi不认这个self9 P2 d6 }# k2 H+ h0 W4 \
with tbl do
: A; q9 \- c$ [, M# h9 |  E' w$ hbegin
. a- b2 }; q7 ]5 @6 X7 Pdatebasename:=;dbdemos’;
8 q5 k8 b" i# t+ I7 x9 N" `) _( d- Utablename:=’my_tbl’;! r% \0 q3 ~( w3 V% v
with fielddefs do
! J! a/ g% U! X% j; ?, dbegin1 F7 r, }( y2 `6 T( T% c
clear;
8 n5 @( \- ^4 G( q4 s$ g# f: ^+ yadd(‘No’,ftInteger,0,false);: ^$ m& [, w. K% k2 Q
add(‘Name’,ftString,0,false);
7 c) b! _8 t+ b2 c1 r
$ K7 G/ X7 }" y) H( Fend;6 ~* d" L$ ?/ C: Y
with indexdefs do
! D5 p+ u( A/ T3 }$ X8 ?. N: fbegin
  p9 M) y4 @  S: M5 }clear;1 s# i) w5 y- G  C% [. N
add(‘primary’,'no’,[ixPrimary,ixUnique]);
7 p" m* S; z5 X& `6 N. E7 j8 S) b  h6 C% E- p" c$ p2 u" |9 _
end;  }6 G- r- D: k/ t( {
CreateTable;1 H3 C  z; }5 n
end;5 {  \4 ~) d8 o9 w# Q3 K: B8 t& {
end;) y$ A' p; G/ t, g! f1 R9 t0 ]
( i6 e% n+ u" P" k  Y, [) G

# b. ?% R  H# I( wstring、TStrings、pchar的相互转换(这里是我的个人经验)
7 ]  m# E4 C7 B! U1 u, X  O假设有如下定义:7 q9 [& Z2 h$ a% }
var+ p6 V. V3 P! F2 X% q6 B, [
p:pchar;
- a) k: J7 E# i5 X2 b  Ss:string;# {) X$ t  a  a0 c8 ]+ D: g1 A
ss:tstrings;
, ^) D9 ]9 L8 Abegin
+ ^" m! Y# ^0 V% {7 l/ Z# Dss:=tstringlist.create; // 开始时一定不要忘记创建ss
; ?) y0 d$ [3 l& L- L2 E6 ?) {5 dss.text:=s; // string –> tstrings9 \, E! W) @' U; h8 J; k
s:=ss.text; // tstrings –> string
2 S, h* [: }4 F6 G- f* R0 \p:=pchar(s); // string –> pchar2 s" q0 x! E) W- Q; b1 L
s:=p; // pchar –> string9 s6 K- `1 s% M0 m' o7 J
showmessage(s); // 合法语句
' z6 K: c4 b- k7 ~$ \showmessage(p); // 合法语句6 P$ G2 \5 _! i( H2 q; R
… …# f: |2 e2 W$ J4 k
ss.free; // 最后还要记着释放ss占用的资源) i! z, M* M+ u; A
end;3 W: U+ a: W$ K4 F4 Z
6 o2 q" }7 Y- H+ H" U0 t

8 j  G6 c* |7 E3 O! t4 n6 t' e
$ L( j( t; u: p& n4 K) }' H, n( m在设计Menu时,常用的ShortCut可从下拉菜单中选取。但我发现可选的ShortCut有些不在列表中,如ESC,Ctrl-Shift-A等。我试着在ShortCut项的右边输入:ESC,竟然成功了。再试Ctrl-Shift-A,这回Delphi自动把它变为Shift-Ctrl-A

TOP

發新話題