打印

delphi 技巧合輯

delphi 技巧合輯

INI文件的操作要点
7 z1 ^" J3 [$ ^+ c% T3 q% r(1)在interface关键字后的uses子句中加入6 T* G5 I; }: O. Y
uses …,inifiles;/ G/ a; R0 X2 ]8 L
(2)设置变量:var inifile:=TIniFile;
# E4 [$ \9 H) O8 j$ i; ^(3)使用前,一定要先做:
( k1 b: i0 i/ r0 a  Qinifile:=TIniFile.Create(inifilename);* E+ _: y4 K! P
我在这里绕了个弯子,写成
# w) n1 U$ ^. N3 \inifile.Create(inifilename);
. k* M& m4 D( Q% j1 U# S9 f% Z: J8 h
) i% z1 r3 [: CTShiftState用来检测CTRL,ALT,Shift,以及鼠标按键的状态,, c, Z3 t1 v2 M. R0 u# W' @, x+ c
常常用在键盘或鼠标的事件处理程序之中。! Z* M) n7 d7 B: S  q
6 Y0 }% [+ p% `5 g& p
DCU文件(编译的库单元)的重用1 @4 r+ X  V- j! I$ l5 y. M( [
(1)在interface里的uses子句中引用。如Windows,Dialogs,
9 j! x) a9 d& L5 P( s# B等等,要求被引用的DCU一定要放在Delphi 3\Lib子目录中。
6 I6 m1 `  T* W8 g9 a7 a(2)在implementation里的uses子句中引用。如果是自行编写的1 S: D9 |- V4 G. h9 s- }# z
DCU文件,应采用这一方式,并将被引用的DCU文件放入当前
4 ~: \2 _  [2 ?1 H+ o7 M+ F1 d1 e2 p* w; Y工程所在的子目录中。
- h3 G2 y& E7 A* a0 Dexecutefile函数(在FmxUtils.DCU中定义)不能用在FormCreate7 G1 \8 k# j' P: D, F
事件中。真奇怪……% ^3 o' ^/ m; r/ o6 \1 ?* }

) N, K0 ~( o% M& n内置的版本号控制功能4 I& u% Q/ G! D# {) |
在Project Options中的VersionInfo项里,有版本信息的定制,( R0 x0 [, K( Y% C, m
包括一个有趣的版本号自动增加功能(Auto-increment build, d% P4 |2 @4 O
number),即每Build一次,版本号中的Build Number加1。选中
2 ]0 G6 W2 b" E& w5 o, ~* qInclude version information in project,编译,用资源管/ q8 o# H* R7 I8 a" F6 c
理器里找到生成的.exe文件,点右键,查看“属性”一项,就9 ~7 D  X  x7 d- N& n' f. z
会看到在属性中多了一页“版本”,里面就是你刚才输入的各
; l5 K5 o2 M; b* b# h, S项内容。
# t4 x3 v+ F( [% l7 w! p& G; o( Q+ w+ h) s+ ^3 \1 G
$ B/ m9 ^7 I$ l( n( {- l( b# y
定制Speedbar8 F' D9 t0 I* G( x1 V9 [* T9 a/ A
右键点击左上角的加速键条(speedbar),选中Properties,8 Q) R+ V) v  _3 Q! V  f
在列表框中找到你想要加入speedbar的命令按钮,将它拖到% |3 Y- p+ o  q; Q# D
speedbar上的合适位置即可。如果speedbar上没有多余的空间
4 P/ m9 s( z0 Z* |/ ]5 I( R$ m2 R来容纳新的按钮,可把鼠标在speedbar右框处变为双向箭头的
) x3 i/ z: f# n形状,向右拖动一段距离,就可腾出空间。如想删除speedbar* t" Y! x9 Q; C, P. {8 ?
上的某个按钮,可简单地把它拖出speedbar的范围,就能删除。
, ?: N% }! M- p1 r
0 m( x& G2 O% `) t) l! s5 C. A) u# h+ f. t$ T- M. b! d( A# j6 C, H
计算出的字段6 z( |. W+ a& x/ W! V
在写一个程序时,我要在DBGrid中显示出一个memo的部分信息,当我把那个
$ F! V: V9 k  D! {  G5 s1 R: `memo字段放进去后,运行时只能显示出“(memo)”字样。从书上找到计算字+ \0 X% [  U# F: u( L! J! _
段的用法后,我在TTable中增加一个计算字段MemoHeader,宽度为40,在此5 W$ p9 U7 F3 J$ \# k
TTable的OnCalcFields事件中输入:
4 q' E2 Q0 D: K2 [+ h0 X# Pwith MyTable do
3 J/ P# ^; @) DFieldByName(‘memoheader’).asstring:=FieldByName(‘memo’).asstring;% i- d+ P* O. j/ C& ?6 p6 s
在DBGrid中放入MemoHeader,运行,OK!
3 c7 e) U, z; j4 f; C3 K2 F% Z* _( ]- L% C0 T; i

; `& ^( B, V, F% }字段编辑器: }% ], W& l% j& T
解决了上面的问题后,我继续学习字段编辑器的作用。原来,DELPHI通过字
; u4 p3 ~0 p4 W段编辑器,近乎完美地实现了数据库的字段级的控制,这包括:
( n( c$ I% {. d: I4 v! v3 K. N$ L1)字段在DBGrid中标题、宽度、能否可见;
# o  F, f3 D/ X4 M( \4 q& W2)字段的显示格式和编辑时输入的过滤条件;
3 [. D( p& h' f' y# ~3)字段是否只读;
6 i/ M( d) N1 W7 z* g1 p" z4)字段的类型:数据字段/计算字段/查询字段/内部计算字段;  I/ H  u" p! X8 S1 ^( M
5)字段的显示/赋值/修改等事件的定制。, n, ^# F, n2 y
7 w9 h6 j/ q" g  q
  s7 g2 }+ B! H! T5 D1 ^$ R
设计Form时的快捷键
* b# U: D" W2 ]7 N8 [0 A2 YDel 删除所选组件- v" ?+ I2 p; J4 O; M/ _
Esc 选择当前组件的容器(通常是Panel,Group或Form)
! P) M9 @0 g$ `/ _F11 在Form或Unit和对象检查器之间切换
: c* ?7 H' E; v" [/ ^% n* }  bF12 在Form和代码编辑器间切换( [  g* H. ~2 l# ]( h0 v
Ctrl-F12 显示“查看Unit”对话框
. d" v: ^; a+ }! xShift-F12 显示“查看Form”对话框% }# k0 Z/ c4 j, _7 \: t7 K  d
TAB 下一个组件
; p. C, E7 e( s$ _# {& h, i# cShift-TAB 上一个组件1 U  s! e2 D/ Q5 k" u# r
方向键 选中此方向上最近的组件
; v  S/ U6 A9 SCtrl-方向键 将所选组件移动一个点
: Y5 H( @$ \7 Q' T* X0 S1 XShift-方向键 将所选组件改变一个点的大小
8 o3 F2 Q+ [* V/ w' z0 R+ `! j6 I( KCtrl-Shift-方向键 将所选组件移动一个格% G$ l. ~% n. z7 ]1 Y
Shift-click 按住Shift键再用鼠标点击组件,可以选择多个组件。
  P3 ~' _+ l, q+ P: R* N–= 下面这条是我摸索出来的 =–9 f  a& k) E$ S6 X
Ctrl-drag 按住Ctrl键在一个容器组件(如Panel,QReport,Groupbox等)4 F; b* a/ b) \6 C( b' f; D
里拖动鼠标,可强制选择鼠标拖过的矩形框中的所有属于此容
9 w( b5 b) s4 F2 a7 S$ R器的可视组件但不包括该容器组件。
' v, s5 I4 E0 f$ X' a
: i, k9 }6 U  A+ S0 a' a
8 S5 ?! j% C) {4 t: B使用QReport的若干经验+ a9 U2 @7 ~: e: x# A& `* M- V" V! k
1)QuickRep1.DataSet:=query1
1 k# n4 h# z! r) J$ A" ?$ t不然无输出结果1 H' u2 r% m1 s# O' H
2)从qrpt2man.doc中查知,格式化输出结果的方法是:6 p2 Q9 @# p9 O
在QRDBText.Mask中设为.00;0,将使输出带两位小数。- V/ a! r& i: |0 ^' V
3)设置Group时,先加入一个QGroup,再加入一个QRBand,将QGroup的' T0 t% Z: e2 y1 i% Q" T
FooterBand设为刚才的QRBand,就可将其联系起来。6 K  T3 l3 _) \7 b( x
4)在Group中打印的合计数,其ResetAfterPrint设为True,可实现分组合
! P- e/ b* n% {2 i. Y0 N: o- A
+ h! x9 N; j. |; d2 Bformat(‘%*.*f’,[8,2,123.456]); //等价于format(‘%*8.2f’,[123.456])
+ @2 t3 t9 J; }( o4 @. Bformat(‘%d %d %0:d %d’[10,20]);
5 `, z& ^7 l8 Q, h, ^/ Q. D" Q1 k  x# e

9 L3 H+ l7 S5 i
( S! \6 p* q: ]9 b& X5 v播放一个wav文件
' ], m, x& m. `: r. n. yuse mmsystem;
9 M1 t9 ]  a! Y$ b7 WSndPlaySound(‘hello.wav’,SND_FILENAME or SND_SYNC)
& e, u9 @$ R; Y2 W; }* N
/ O7 a; A3 r" F+ w# m+ f使你的form适应不同的显示分辨率
8 o; U$ n! g9 C7 Z! K$ u5 @假设你在800*600的分辨率下设计的form,第一步:% a  T3 _3 b8 d% P/ k' k5 v
inplementation
  [9 Z2 B, S& F1 Qconst
1 [, D; s+ z! c7 U0 HScreenWidth: LongInt = 800; {I designed my form in 800×600 mode.}* Z, M& S% s4 D9 W$ t$ T
ScreenHeight: LongInt = 600;  L) v# |7 P$ d$ C
5 Y9 x2 ~( a7 B. R% q5 l
{$R *.DFM}
$ O5 x& ~0 Q1 G; Q( N5 u7 @. P. X8 B  [" F
procedure TForm1.FormCreate(Sender: TObject);' f- Z$ E6 k0 o. ?
begin, C: J5 Z" |! j5 p5 Q! c4 `$ c
scaled := true;" b8 |/ q2 f$ f8 u
if (screen.width <> ScreenWidth) then
; g9 j. q+ [* ?* d% m) `. B! Bbegin
% y! @2 Q2 q0 F) Q/ c; i: C( Sheight := longint(height) * longint(screen.height) div ScreenHeight;5 S2 C- {4 U' B% G
width := longint(width) * longint(screen.width) div ScreenWidth;: u( q' T# c0 F
scaleBy(screen.width, ScreenWidth);0 B0 B0 ?' D( M9 L/ a, [/ S/ V0 f
end;3 L9 I) _3 @; Q
end;' ]" y8 s7 D0 w6 w

$ y, k" _- o3 ]+ k下一步,要让每个子控制的字体改变到合适的大小:: [# P1 s6 G# b% @; `
type3 A$ Z+ y2 z8 M
TFooClass = class(TControl); { needed to get at protected }6 L, S9 E8 m! X& `8 a/ D( U2 n( f5 R
{ font property }1 ~" i+ a9 O! _, B
* w" n5 b5 G) X; a2 |
var( q8 Y' }1 D3 b  L) d, O& S2 x
i: integer;$ o+ J9 [3 o/ v  u" p5 _
begin
, \$ u, v! ~2 Kfor i := ControlCount – 1 downto 0 do* Y1 X, g6 O( W  B  a6 p, [  P
TFooClass(Controls).Font.Size :=
- p: W( J( t: d8 v, R, \) E& M(NewFormWidth div OldFormWidth) *1 H% A3 @6 U' W) {/ {. {7 ^) X
TFooClass(Controls).Font.Size;
$ Q! A0 B( E/ y9 d3 ?end;
* A4 K8 N! C2 o' F1 C  d# f
4 t. ~, G- X2 W' x6 v" H2 F, [用raise引发一个错误处理例程
4 k" F$ @/ E; M! N% y" J示例:先给出下面的定义$ p; F2 R9 ^- `. ~+ k
type EPasswordInvalid=class(Exception);; {+ b# }# W1 ?8 }$ f+ r
这样你就可以随时引发一个”password invalid”的例外:; X1 F3 p$ e1 G) D" Y) W: G- o
if Password<>CorrectPassword then$ `( h$ h8 M% i" B' ^  L6 U
raise EPasswordInvalid.Create(‘Increect Password entered’);% M$ M+ \1 Z6 j0 i& o0 N+ V
运行后,出现信息框
7 b- U$ v0 G" l9 T! f2 Q0 zProject Project1.exe raise exception class EPasswordInvalid: |) d# S# m- B8 ]! f# h9 c
with message ‘Incorrect Password entered’. Process stopped.
' ^9 H7 p% N0 d8 K7 v3 FUse step or run to continue./ d1 w/ |5 }2 q+ S1 i
再按Run按钮,出现一个信息框:1 I& `- @9 \0 [
Incorrect Password entered.
6 c% Y) F8 c+ p! C7 {
6 R! _5 p) K9 C: D+ d& m) `5 V8 a5 J- n5 A! b( n/ J
从DEMO例程中学到的若干小技巧, s9 e" F. x8 t% t% N% E) @7 c
在demo\internet\http\webbrows\main.pas中,
0 K. \9 s3 y1 e7 [+ J5 `: p9 v3 a1 qprocedure TForm1.DocumentSourceClick(Sender:Tobject);
: ^4 T# V% H  O) m  P5 xbegin
7 {5 K9 ?- s$ w9 H( _* rwith DocSourceForm do
0 s9 C' m5 p% g+ h& p- [3 \begin
5 O* M: D% ~7 U) j% S, e" Dshow; // 显示HTML源码的FORM. L& i* Q, S  `8 W" k1 j
Memo1.lines.clear; // 清空memo1中内容- q2 z5 {! w6 s* `# v
Memo1.lines.add(HTML1.SourceText); // 植入源码2 H# O; _% a5 ]- l. S2 n0 h
Memo1.SelStart:=0 // ***. S7 H- |% ^3 G& f, b
SendMessage(Memo1.Handle, // Memo1的窗口句柄
3 {3 ]+ n  h  _8 aEM_ScrollCaret //将Edit Control中的caret光标滚动到视野中
; ~+ w7 F" b5 r# ]* k0,0 //这两个参数暂不使用! p) T- h8 l8 S( I6 n1 e6 V
end;* e; F; C) Y, e/ N
end;. Q$ B  E* S! {* Z6 b
(此SendMessage系一WinAPI调用,给一个或一组窗口发送消息,直到
0 l) \5 Z, s) }相应窗口处理此消息后才有返回值。相似的另一函数为PostMessage,6 u* M2 [6 Y8 a  h  [* G
它将消息放入消息队列中后立即返回。)
6 S' h0 n" B# C9 h& Q*** 清空当前选择并将光标移动到指定字符(0代表第一个字符)。如同时9 U. Y2 ]0 H7 N) Q+ h
设memo1.sellength为一非0值,可选择一段文本。
' w5 Q+ R" l  H  b2 i- F. x% |. Q, I2 m+ K+ F5 w

) W- E& B$ r( Y  o- o1 l  x* f奇怪的I/O error — 我在开发过程中发现下面这两条语句- ^3 l  I8 c6 ]' b8 ^$ n
assignfile(fDesc,CDDatadir+describefile);
6 u2 D$ b2 l7 i; E4 w. P2 ?$ }reset(fDesc);
' [$ m. `  ?  h& r8 g每当我第一次运行到这里时,总会出现 I/O Error 183 的错误.% t. w7 K5 {! |0 H( N; H) ^- S
最后我想这也有可能是没有清除 ioresult 的原因.在两句之间加入
3 ]* P3 v# d" g8 Q9 a" E0 s/ hif ioresult<>0
& c- W8 K0 N9 t0 \/ \9 D* m! Pthen;
+ K& Y$ I8 O4 M1 qoooook! 可以了.
9 |8 Y, f/ f+ K2 ?) \5 o5 |0 M

: ?* X5 `5 B3 z4 P. ?$ C9 Y# Z值得注意的I/O error  Q- d# O, L6 f9 L& d2 S
AssignFile(F, fname);% f; @4 u, S( ?
Rewrite(F);
4 X$ X2 ]: ?% ]+ R6 U! Z4 Y; B% o当文件 F 经 Reset(F)打开的情况下, Rewrite(F)会引发一个异常: I/O error 32* B1 i' K0 f+ d- n
反之,经 Rewrite(F)打开, Reset(F)也会引发同一个异常.- Y. \9 o2 M' q, \+ `
Reset(F)两次,closefile(F),再Rewrite(F),或反之,也会引发同样异常.
: G# I9 U' p6 A; ]6 D/ }' l7 Q  |/ r

; D, u& e  D# J7 `( h! Y8 y# H- ?2 s9 T5 D+ {5 W1 A
string和pchar的相互转换:. b2 @# X9 N6 }1 y% A( m4 p' F  ^6 W( w
string –> pchar: pchar(s
/ _3 H# X1 t0 U2 Y7 dtr:string);- `' C# f- F# r9 |9 ~" c4 T
pchar –> string: strpas(p:pchar);
$ F# ^" \) Q& v5 m8 _! j4 y6 o% Y% L* M) f1 f) y9 I* d

6 i& z: m6 D3 V, d! {$ _
. u) i# q5 C+ D) n在Delphi代码中定义数据库
9 `) S' Y( M$ z5 B0 q/ Tprocedure tform1.create_tbl;
' n6 T$ q2 ?( q8 j5 \( Zvar tbl:ttable;3 L7 S" }/ Q! ?+ ]2 \( _
begin5 H2 T4 _0 q" e; }
tbl:=ttable.create(self); // 如没有声明中的”tform1.”,Delphi不认这个self
) |& s" k4 E2 z  P( @8 T! p, ^with tbl do
/ e0 b6 ~; q" ibegin
- O+ f( ~  I+ s! k5 X7 K) i9 ydatebasename:=;dbdemos’;
" n7 B/ X5 p6 T: `* d8 btablename:=’my_tbl’;" L' g1 C" u  R  i6 R2 u
with fielddefs do
' x& {0 y. K( |1 Z( Lbegin
0 L  a! |4 y& M6 w0 Eclear;% f2 w# j* r3 |# L
add(‘No’,ftInteger,0,false);
4 i4 f# Z0 i) ?0 I9 o3 Yadd(‘Name’,ftString,0,false);8 }; [% }( X4 O( n5 D" q

4 J3 i7 `* t9 Lend;
0 }6 g; m1 ^4 U/ x, qwith indexdefs do+ G/ B. K2 c9 l3 A! ?7 J
begin9 ~# o) w  E2 c1 N. E, l
clear;
  p$ p* t9 f( U$ g! l+ d& D8 Cadd(‘primary’,'no’,[ixPrimary,ixUnique]);! q2 v2 A4 p  D1 T6 m2 U: ]; n

  o8 O+ \4 B* mend;' d+ x/ x) O& A9 P
CreateTable;
3 J- P+ K2 [1 `) G7 f7 i6 @end;
+ k: J1 x8 H& Cend;0 `# i- p8 ~& r
8 F- y0 E* T/ J" V, a
7 K5 `  W- Y! P/ T
string、TStrings、pchar的相互转换(这里是我的个人经验); F1 w* |- O5 N- |
假设有如下定义:% y9 R1 P* g% d9 @# E7 ~! F: S9 D
var
( c3 Q3 A* q* O6 l" }  @; w8 Gp:pchar;
* E& F4 ^5 l! i) o0 L5 S/ zs:string;
, }0 c% s( x" w* }* |ss:tstrings;
/ J; g. D6 W# P$ pbegin
$ m: T7 P* l1 A1 v) rss:=tstringlist.create; // 开始时一定不要忘记创建ss' I" N8 X7 ~9 m
ss.text:=s; // string –> tstrings
- d- R. c( \9 q9 z; l7 J7 {% ?s:=ss.text; // tstrings –> string
+ R' G1 r9 M$ L' b1 Zp:=pchar(s); // string –> pchar3 Y- o7 G* @- M
s:=p; // pchar –> string2 D, h) d  t- f8 n) U9 D0 P/ d8 i
showmessage(s); // 合法语句
- ]# y8 u( E) t( _9 Ushowmessage(p); // 合法语句
: g5 ~$ G( M" R3 `… …8 {/ R1 \, G4 J# C
ss.free; // 最后还要记着释放ss占用的资源
; _3 V  I. e' Pend;
8 |# b9 m9 k7 y0 p. C! S/ n3 z8 r2 @% N' U) ?9 r* z* [

9 b) Q+ I! I7 k/ M1 v* l8 @
. \8 b9 L% t$ X+ [. `/ X/ }在设计Menu时,常用的ShortCut可从下拉菜单中选取。但我发现可选的ShortCut有些不在列表中,如ESC,Ctrl-Shift-A等。我试着在ShortCut项的右边输入:ESC,竟然成功了。再试Ctrl-Shift-A,这回Delphi自动把它变为Shift-Ctrl-A

TOP

發新話題