打印

delphi 技巧合輯

delphi 技巧合輯

INI文件的操作要点  Z! R" L8 x- \7 M& U
(1)在interface关键字后的uses子句中加入1 o# j! d0 {3 y  N+ L. c. S+ ^% Q
uses …,inifiles;$ p  a  M/ w' @1 x+ M+ I
(2)设置变量:var inifile:=TIniFile;: E' }1 N9 j" F- D" C
(3)使用前,一定要先做:+ V+ Q* Y4 e' M
inifile:=TIniFile.Create(inifilename);( o) _- t$ q7 C7 a
我在这里绕了个弯子,写成
, |- K5 p! s2 @, }inifile.Create(inifilename);
5 j  G/ h+ ^: f* C) F
; L( N" c5 M4 y# e/ c2 |4 Z3 nTShiftState用来检测CTRL,ALT,Shift,以及鼠标按键的状态,9 v( w2 r" _: ~- c' m
常常用在键盘或鼠标的事件处理程序之中。
5 K# V" M: t% y) G0 n- f2 s% L5 L, L. T  K% r
DCU文件(编译的库单元)的重用/ `( n- w; _0 p! N& O
(1)在interface里的uses子句中引用。如Windows,Dialogs,
* ?" C' S$ X+ w( O% A等等,要求被引用的DCU一定要放在Delphi 3\Lib子目录中。
4 d. ~: Y  }+ _(2)在implementation里的uses子句中引用。如果是自行编写的% D* I4 x" s$ G0 _9 _* ?1 X6 J# M
DCU文件,应采用这一方式,并将被引用的DCU文件放入当前9 p3 T1 c5 M7 ?! A# e! G
工程所在的子目录中。" D$ z/ v! k+ F/ I$ Y
executefile函数(在FmxUtils.DCU中定义)不能用在FormCreate
4 z/ ~) Q4 @( k3 a1 E# Z: V事件中。真奇怪……
# `) I; {" k* k% s4 G. |  a/ ?
* h9 y- H% `# u' w+ s0 o" l内置的版本号控制功能
; |( j! i& T5 v+ Z" ^  V/ s在Project Options中的VersionInfo项里,有版本信息的定制,
3 X0 K, S) H1 c. o" C' Q包括一个有趣的版本号自动增加功能(Auto-increment build
6 P" S; U  g# z) znumber),即每Build一次,版本号中的Build Number加1。选中
. ]9 I) Y1 I, l; fInclude version information in project,编译,用资源管
  I" m  H: B# U4 Y8 M( v理器里找到生成的.exe文件,点右键,查看“属性”一项,就' d2 D1 O( b% R6 v8 t0 K
会看到在属性中多了一页“版本”,里面就是你刚才输入的各& R1 A+ i3 W$ i6 p
项内容。
0 O( @4 o" A; C& D* E' j8 @- Q
# z: {  e$ `- S$ J
0 \. x& H5 `# I$ V  K定制Speedbar
0 M8 s0 C# Y3 p( I+ _. \右键点击左上角的加速键条(speedbar),选中Properties,6 P3 ]( u5 y$ K9 P
在列表框中找到你想要加入speedbar的命令按钮,将它拖到
; r; D+ w% ?5 F5 W* Xspeedbar上的合适位置即可。如果speedbar上没有多余的空间  R* I# C6 H# v4 [
来容纳新的按钮,可把鼠标在speedbar右框处变为双向箭头的
% P! K$ R8 ]7 F, H- e2 t形状,向右拖动一段距离,就可腾出空间。如想删除speedbar
$ P* q7 m' `7 w1 H上的某个按钮,可简单地把它拖出speedbar的范围,就能删除。' r0 |1 w. }- O% X7 s' {7 r

" A4 f. n, M8 z5 L
; L3 h* d  B6 C; f$ l  W计算出的字段
% q/ E9 q4 B' v4 y. L6 n7 e在写一个程序时,我要在DBGrid中显示出一个memo的部分信息,当我把那个0 _( ]6 P0 v- e% c; t7 I. D: C
memo字段放进去后,运行时只能显示出“(memo)”字样。从书上找到计算字' K- a1 ^2 J3 Z4 U4 v
段的用法后,我在TTable中增加一个计算字段MemoHeader,宽度为40,在此$ N2 `6 @: h, A( n5 u1 h" U& [) `
TTable的OnCalcFields事件中输入:
  b0 i6 M& U, ?! Z  P, {5 I7 Jwith MyTable do
/ X7 D' M2 [# B( t* m4 B& ^FieldByName(‘memoheader’).asstring:=FieldByName(‘memo’).asstring;
7 C9 A4 _- O% Y& M) y; r7 Y在DBGrid中放入MemoHeader,运行,OK!6 ]" C6 q6 i2 X  O

$ h; |5 X7 d6 T" q$ w( n. Y' Z
. P! |. `! Z; o* t# Y/ ]7 B8 o% b7 k字段编辑器+ g7 S- J* s  P; m
解决了上面的问题后,我继续学习字段编辑器的作用。原来,DELPHI通过字
6 W( [8 h4 h8 t% B段编辑器,近乎完美地实现了数据库的字段级的控制,这包括:. q% v# ]( O; d' I4 t8 u& o
1)字段在DBGrid中标题、宽度、能否可见;
0 T# u" g7 e4 U5 h7 q0 ?2)字段的显示格式和编辑时输入的过滤条件;
% E! d1 _* a, m0 i7 @# W$ \/ q3)字段是否只读;# f* M5 C! Y; o$ X
4)字段的类型:数据字段/计算字段/查询字段/内部计算字段;
$ W7 w/ C8 R- d8 Y! Q6 c( r5)字段的显示/赋值/修改等事件的定制。
, j& k7 Z" i5 w+ U% \9 l7 x, X& U9 o* J& N0 H+ q5 W- k

' ]1 H+ [  x3 ~5 {设计Form时的快捷键6 @- P5 H$ T& }) x
Del 删除所选组件
* J  M3 g# ]+ i0 ^. \& _; VEsc 选择当前组件的容器(通常是Panel,Group或Form)# v3 G1 |' S% e; a' o" I- v2 @
F11 在Form或Unit和对象检查器之间切换! E6 P/ \! l7 S! u* n; `6 k
F12 在Form和代码编辑器间切换1 M- h1 V5 O6 U6 W* Q0 ~" ~# `
Ctrl-F12 显示“查看Unit”对话框7 ~# I% q: S* p4 ]; \: e, L5 D
Shift-F12 显示“查看Form”对话框  W5 M8 f1 _) M- g1 j6 x; D7 D, i3 ]
TAB 下一个组件. X0 N( h7 o# X( R) ?/ B3 q# Q' ]
Shift-TAB 上一个组件% p. q& a4 }- h# j+ Q
方向键 选中此方向上最近的组件! C. U9 X9 P& t
Ctrl-方向键 将所选组件移动一个点
0 b0 j! P) S- O, G7 ?5 sShift-方向键 将所选组件改变一个点的大小
4 l/ k2 P1 {0 m% l6 aCtrl-Shift-方向键 将所选组件移动一个格/ Z# ^4 ?- x3 @1 X
Shift-click 按住Shift键再用鼠标点击组件,可以选择多个组件。
$ T2 @- v$ M  p" ?$ T3 t: ?' n$ q; B, Y/ U–= 下面这条是我摸索出来的 =–  T6 g4 A% ~( i2 |
Ctrl-drag 按住Ctrl键在一个容器组件(如Panel,QReport,Groupbox等)
: M2 w7 ?7 _* N1 E& v( W里拖动鼠标,可强制选择鼠标拖过的矩形框中的所有属于此容; F5 a/ C4 k7 Z- _, b1 h( z+ S+ a
器的可视组件但不包括该容器组件。, l2 X. {, {# d, c

6 z0 q. X. u, p/ |: \. H9 F9 p& [, N5 g* X+ C
使用QReport的若干经验4 J* N1 G7 d, q* C) G% i
1)QuickRep1.DataSet:=query1/ X6 i9 J: j- f
不然无输出结果
, h/ ]7 y! ]+ j6 ?9 T2)从qrpt2man.doc中查知,格式化输出结果的方法是:+ \+ L. F$ U) N! {' i$ f
在QRDBText.Mask中设为.00;0,将使输出带两位小数。- c: D5 i/ p, ?5 Q  b
3)设置Group时,先加入一个QGroup,再加入一个QRBand,将QGroup的* x" z0 y5 v. n5 y1 y7 s
FooterBand设为刚才的QRBand,就可将其联系起来。
2 L  K' L4 E0 l5 p  T2 F4)在Group中打印的合计数,其ResetAfterPrint设为True,可实现分组合1 b( h6 @: c, ?9 k) S0 Q; X

# C3 y2 u% _2 ]; \  Pformat(‘%*.*f’,[8,2,123.456]); //等价于format(‘%*8.2f’,[123.456])
% P; l+ U- U, {6 a; F" Fformat(‘%d %d %0:d %d’[10,20]);
+ |' s" F! F2 H6 Y; Y- t; L3 B
6 w6 D. f, r* Q: x
9 q' }/ }& k# r- A3 C2 K+ t& Q5 }  f+ B6 O" P1 ]0 T( t1 a1 b! R
播放一个wav文件8 _3 \- H0 `% B0 X* }! {
use mmsystem;
% z! Y  b4 ?, [, F9 l0 t3 C# _SndPlaySound(‘hello.wav’,SND_FILENAME or SND_SYNC)( @, C7 v! {. t; r: v

0 _( Z/ {' H- ^6 C6 ]8 a( R使你的form适应不同的显示分辨率5 `4 X' M# z/ D/ z. A
假设你在800*600的分辨率下设计的form,第一步:
) G- y% F1 d3 z% M" T8 Kinplementation/ L8 r+ n6 v* l3 ~* G4 }
const1 s. c; o: ]% A5 G4 {9 G# ~6 z
ScreenWidth: LongInt = 800; {I designed my form in 800×600 mode.}
6 ~0 A. X) a0 _# H7 E& \ScreenHeight: LongInt = 600;
- R4 W2 ?4 D' n5 n
1 j, ^) F9 R% p# u& q0 N{$R *.DFM}
# `; J7 ~3 Q7 H6 Z4 A9 \3 y) ?0 \( f7 x/ z' l/ }  v/ {) b* T
procedure TForm1.FormCreate(Sender: TObject);& v' `: M) x$ D+ O9 S! H; y
begin
8 n" ^4 v( i# u1 g* nscaled := true;5 O: M( e* _1 M
if (screen.width <> ScreenWidth) then
) a' P; k8 ?5 }& w" nbegin* u& f1 Z; ]: A1 h6 i# d9 X
height := longint(height) * longint(screen.height) div ScreenHeight;
( H& o$ y& e& k0 {7 b- K( {1 v. Pwidth := longint(width) * longint(screen.width) div ScreenWidth;
3 R" K5 J( C: c& ^! ?: e7 K, {scaleBy(screen.width, ScreenWidth);
0 a$ G; C+ G. U: L" F$ ]7 i# g; tend;
: k( _( p5 s9 a, a. [6 w) V4 {end;& j" N5 q6 j0 c9 V9 c

1 t0 W$ @: d0 k# o; t下一步,要让每个子控制的字体改变到合适的大小:
6 h# {4 T4 z/ n8 U3 Q0 dtype
3 R( H$ i* g4 _TFooClass = class(TControl); { needed to get at protected }
/ x( F* X: A  ~! M{ font property }; ~' }% T% J# n
: B- T* {3 n! u: {, L* S
var
2 |5 h6 J/ F/ K/ Q/ |i: integer;
7 _7 `5 d+ J3 t: D7 [begin3 k; I* l' B" V1 j8 q4 ?6 P. q3 p
for i := ControlCount – 1 downto 0 do0 l) n8 C* P: i$ c5 v
TFooClass(Controls).Font.Size :=
6 G/ Q' W$ ~% `/ d: z(NewFormWidth div OldFormWidth) *
! Y0 G0 A) h: a& VTFooClass(Controls).Font.Size;
1 M4 n1 }4 }8 E; {; hend;4 [) Z. Z; B3 e
- m' c& F6 f! m& s  [( P# X+ |
用raise引发一个错误处理例程
- Z1 q. o' a: V1 @, K' {示例:先给出下面的定义; s; E& s* i5 j* I" l+ e' @" F
type EPasswordInvalid=class(Exception);
6 ^9 j3 U, Y. H+ j+ X这样你就可以随时引发一个”password invalid”的例外:
) O( n) Z/ B0 p& Pif Password<>CorrectPassword then8 w$ o; _$ u+ ]9 j3 X0 e) }
raise EPasswordInvalid.Create(‘Increect Password entered’);( _% u( z3 r8 `9 c" {
运行后,出现信息框- c+ |, L' L' A$ L3 N7 e& T6 u2 I
Project Project1.exe raise exception class EPasswordInvalid- }" p9 Y0 g' x1 _7 C  X8 [
with message ‘Incorrect Password entered’. Process stopped.
2 v" T% [% N! ^! ZUse step or run to continue.
; }6 h; t5 J; L2 [再按Run按钮,出现一个信息框:
9 F. Q# I, p" W7 U/ n$ CIncorrect Password entered.
. P/ b5 L3 P: U# l# _9 y! V
6 P9 k. U" H/ R6 r5 y" N$ s: Z2 b
# b. ]  F; L9 ^3 j* [" k3 b- E从DEMO例程中学到的若干小技巧
7 E: ?; }) }4 D- h- {) z0 R3 w, Z在demo\internet\http\webbrows\main.pas中,# K9 b0 _: h" p; h. H! L
procedure TForm1.DocumentSourceClick(Sender:Tobject);3 n: h1 L, ~: {- A
begin! S' G, r2 P9 b4 X0 C8 E2 c6 \
with DocSourceForm do+ b' ?) J% v4 N5 E
begin- ~6 r6 ]2 F+ W7 ^
show; // 显示HTML源码的FORM
5 ^1 ?* @( }% Z6 wMemo1.lines.clear; // 清空memo1中内容
3 W# E, u! N' H' o1 UMemo1.lines.add(HTML1.SourceText); // 植入源码
' y" R' E) C$ W& ~  T8 o& p1 Q' _  r% UMemo1.SelStart:=0 // ***6 W  ^) D, J0 {  i
SendMessage(Memo1.Handle, // Memo1的窗口句柄8 w! }2 Q% w+ |/ u/ U5 j. p
EM_ScrollCaret //将Edit Control中的caret光标滚动到视野中  M5 u2 t5 X, ?9 i
0,0 //这两个参数暂不使用
, ?6 ?/ w' ?* `2 j% @# Z/ bend;
- G. B* c% ?0 c5 pend;2 B- H( u: x: p+ ^$ @0 w  `9 I0 f
(此SendMessage系一WinAPI调用,给一个或一组窗口发送消息,直到! M; |' K! d5 h
相应窗口处理此消息后才有返回值。相似的另一函数为PostMessage,! o: z) ?+ z. C5 u. }6 P8 W  R
它将消息放入消息队列中后立即返回。)
0 ^( H4 `+ n) J8 |5 r0 }9 w*** 清空当前选择并将光标移动到指定字符(0代表第一个字符)。如同时
0 t9 h1 r. a# l/ n. }6 U+ z5 ^设memo1.sellength为一非0值,可选择一段文本。
% z; ?& p0 p6 o! f- {( R* J
5 m( m- n# {0 w: S/ o; c
, X( `5 n; _9 H# K" j% ?7 Z1 F# n奇怪的I/O error — 我在开发过程中发现下面这两条语句
  E' F# ]. I7 A. G" z1 Fassignfile(fDesc,CDDatadir+describefile);& v# X# K* A6 k9 @' }6 F; y- d# F
reset(fDesc); ) X( B9 O. ?5 f0 h$ K4 N7 g  {
每当我第一次运行到这里时,总会出现 I/O Error 183 的错误.. J. z) T* v8 f4 ^" x
最后我想这也有可能是没有清除 ioresult 的原因.在两句之间加入
9 Y/ T$ L3 l) B1 z# e5 }; dif ioresult<>0
3 l) }+ G' _" q( w1 Mthen;
3 O4 L7 M2 C* K' j: v3 @oooook! 可以了.3 O( o6 O& F, A$ N. r

( o2 h" j% Z& }1 E
/ `$ x- E1 [1 `) M7 d值得注意的I/O error
# d! a+ m' x* C6 l% ?9 D9 m& IAssignFile(F, fname);3 L: W! |7 Y1 A: N
Rewrite(F);
; M% D: |* ]- {+ @: k# R* b当文件 F 经 Reset(F)打开的情况下, Rewrite(F)会引发一个异常: I/O error 32
& T% S' u; a4 E4 J' y1 J反之,经 Rewrite(F)打开, Reset(F)也会引发同一个异常.( ^, P: Z8 B: c: d+ l
Reset(F)两次,closefile(F),再Rewrite(F),或反之,也会引发同样异常.
/ o! }4 O( z+ l' f5 n7 [. B( @% J9 H0 w$ G# S: S

- v& `8 {4 R  Z" i/ `) j& ~, w
. w8 [5 D' q3 n# P5 @. B' @string和pchar的相互转换:
7 g/ a' I  }6 T& y1 s+ m  b! `% sstring –> pchar: pchar(s& S6 d5 k* P7 w" o" \* l) X
tr:string);0 m  v$ L0 y( [+ y
pchar –> string: strpas(p:pchar);- v* d! E+ D& E

$ D; K: R4 W8 R# q# e5 W1 z9 h0 n' K: w2 L. P4 W
$ J' @/ h. M1 P" w0 q
在Delphi代码中定义数据库
6 h* z1 T2 w# W& M" f  Y5 ^% mprocedure tform1.create_tbl;
( c; R1 |6 B7 B) E2 Jvar tbl:ttable;8 {  n. F; e4 y( ~
begin+ z7 w' h) C1 r6 V2 r' S
tbl:=ttable.create(self); // 如没有声明中的”tform1.”,Delphi不认这个self
& o& O/ D$ d! s! twith tbl do
, W+ J  K. x+ \2 |& Y1 Tbegin
" K& R  l6 }' ?% g' j8 `1 vdatebasename:=;dbdemos’;
' O' ]" M! n/ ftablename:=’my_tbl’;, ]& ~" S: w  @$ l/ {3 _, Y6 u
with fielddefs do# v( w& Z* n% I( Z5 P
begin
: A7 {6 ?* [5 Qclear;+ z6 v+ D3 B. g1 S
add(‘No’,ftInteger,0,false);+ G) j# F) Z4 h7 Q; A% [
add(‘Name’,ftString,0,false);
' C" P* B' L; l# L+ e; ]* \6 s: S2 ^5 s* U; k! v
end;
; _8 F$ q9 Q3 `* u8 w: l8 ~0 Pwith indexdefs do2 I% P! H' z/ P2 S
begin% ~+ S- B+ S- r; a6 u
clear;
1 u' f, I( A3 p  l6 Padd(‘primary’,'no’,[ixPrimary,ixUnique]);/ d' S9 h- }0 W& ]" @4 W
1 n/ O: {, X) f" D( I
end;
. s# i' c/ p/ F; ]CreateTable;
  R* }% ~$ I- I# v9 rend;% X9 L; p' R( g  g1 r
end;' K5 s. R; [1 n5 r$ n5 R( H: m! n
6 D1 O3 E! l% q! M# O, H
7 [+ G6 Z. U# \5 A& p" l8 P
string、TStrings、pchar的相互转换(这里是我的个人经验)
9 h4 i: X- H' ?) u$ V假设有如下定义:# a) x! V2 |/ x$ Y$ y
var
* x( M9 a6 F* Y, Tp:pchar;
' O, _8 J+ H" o% As:string;& [, w+ S0 q3 Q& F: p6 @( c, t! Y
ss:tstrings;
2 K0 n0 g# O# Xbegin: ^* _' M' ?$ {5 [3 |
ss:=tstringlist.create; // 开始时一定不要忘记创建ss2 \! ?7 N2 E/ j  i% X0 J( s
ss.text:=s; // string –> tstrings
+ a) O3 p' x: L6 Fs:=ss.text; // tstrings –> string! |1 n3 }7 ^  r* Q, q
p:=pchar(s); // string –> pchar
7 O5 P( F! ^. J, Is:=p; // pchar –> string1 c& W% ?+ v, \4 D# E) W- h
showmessage(s); // 合法语句
# q& F, `1 t' jshowmessage(p); // 合法语句
: G7 r/ b. M% s9 V… …' b. Y0 r* Y7 V
ss.free; // 最后还要记着释放ss占用的资源0 \( x8 g) H  E
end;6 ^" [5 z9 M! e  r' y! `0 E. |
, F) U& l+ I- L3 c

( m$ p0 U. u3 z4 G2 G5 S" c) ?9 N0 \( \% z. G& v
在设计Menu时,常用的ShortCut可从下拉菜单中选取。但我发现可选的ShortCut有些不在列表中,如ESC,Ctrl-Shift-A等。我试着在ShortCut项的右边输入:ESC,竟然成功了。再试Ctrl-Shift-A,这回Delphi自动把它变为Shift-Ctrl-A

TOP

發新話題