標題:
delphi 技巧合輯
[打印本頁]
作者:
segaa
時間:
2010-3-10 04:40 PM
標題:
delphi 技巧合輯
INI文件的操作要点
5 O5 X6 a9 I) n0 R
(1)在interface关键字后的uses子句中加入
9 q7 F& R" N- P8 ?8 J* s- d
uses …,inifiles;
4 d% J! `& F/ Q- m; c; g, l
(2)设置变量:var inifile:=TIniFile;
5 `; A; k2 v9 n+ o6 N4 i) q8 k
(3)使用前,一定要先做:
G4 l* O. t$ c. q4 ]& W
inifile:=TIniFile.Create(inifilename);
+ n7 ]- J8 T9 h+ n
我在这里绕了个弯子,写成
6 s8 M# r: q ?+ Q. V3 w
inifile.Create(inifilename);
' U0 h- D5 x; Z
6 {5 P1 M6 y s. S: R" h
TShiftState用来检测CTRL,ALT,Shift,以及鼠标按键的状态,
6 Q9 A+ }+ o0 a* [( T
常常用在键盘或鼠标的事件处理程序之中。
, h- U/ U" e1 }8 Y @+ f/ W
9 N6 o# q: J# H1 b( k1 E) U& b
DCU文件(编译的库单元)的重用
3 n; K4 y0 |- Y* ^
(1)在interface里的uses子句中引用。如Windows,Dialogs,
9 {! T* B( \ @7 M s
等等,要求被引用的DCU一定要放在Delphi 3\Lib子目录中。
) @( S/ \, {0 `# D# h
(2)在implementation里的uses子句中引用。如果是自行编写的
9 `8 F0 ^% y/ @: I9 E: g
DCU文件,应采用这一方式,并将被引用的DCU文件放入当前
- h" k2 Y9 w |. |4 F
工程所在的子目录中。
! h4 u3 n! ?4 t2 P( ]- w$ u
executefile函数(在FmxUtils.DCU中定义)不能用在FormCreate
9 a4 Q* M; I8 @
事件中。真奇怪……
# ]6 ^3 {: ^& x6 A' a/ H
! M; S. u* ]+ j8 I8 l
内置的版本号控制功能
- w; E( t, x8 C( K. y5 ~: \3 a4 a
在Project Options中的VersionInfo项里,有版本信息的定制,
6 [& E% r: N0 ^; y7 J
包括一个有趣的版本号自动增加功能(Auto-increment build
; W# M1 C, R# ?0 Q7 \& B
number),即每Build一次,版本号中的Build Number加1。选中
$ i8 i) Q% |8 L$ N* m
Include version information in project,编译,用资源管
5 o, p8 W+ G Z( }
理器里找到生成的.exe文件,点右键,查看“属性”一项,就
1 W7 d" Q/ e1 D$ g3 E; x. A2 _( f
会看到在属性中多了一页“版本”,里面就是你刚才输入的各
( ^- H8 Y" f' R6 q, J; m9 [: {# c; n
项内容。
3 v* O; H- e3 R% F' \
r9 U; F: T$ Z8 U( X- d' I H+ F
( c/ [0 A& S7 x9 a
定制Speedbar
/ x7 g1 c: [7 }$ Z% V" g
右键点击左上角的加速键条(speedbar),选中Properties,
6 M( s) D) l) B
在列表框中找到你想要加入speedbar的命令按钮,将它拖到
: D9 P+ s K% b' t- O: R) t
speedbar上的合适位置即可。如果speedbar上没有多余的空间
0 m, G- p) l- I( B/ M: H# ?
来容纳新的按钮,可把鼠标在speedbar右框处变为双向箭头的
. M9 H. m8 R+ r3 ?
形状,向右拖动一段距离,就可腾出空间。如想删除speedbar
# K0 ~7 ?1 \0 D ?1 f6 Q$ z# q
上的某个按钮,可简单地把它拖出speedbar的范围,就能删除。
5 G7 X' u4 f- F3 b7 i1 ^
) N% p2 G$ l5 {" U: q6 }" i
9 P( E& I9 t- @" U' }* R
计算出的字段
$ s( Q6 O) P4 H
在写一个程序时,我要在DBGrid中显示出一个memo的部分信息,当我把那个
* z( O) _* Q _5 j: W' \0 b
memo字段放进去后,运行时只能显示出“(memo)”字样。从书上找到计算字
( E8 E2 d* K2 F) q
段的用法后,我在TTable中增加一个计算字段MemoHeader,宽度为40,在此
/ E; n3 s; [- A; Z
TTable的OnCalcFields事件中输入:
) U$ l5 O2 j1 T+ I
with MyTable do
1 h. s1 H `4 `8 G1 {
FieldByName(‘memoheader’).asstring:=FieldByName(‘memo’).asstring;
* m+ }9 F, }& d ~
在DBGrid中放入MemoHeader,运行,OK!
3 C, w8 Z& e; H6 ~( F
# F& l7 Q* |. i, h
9 j; d$ K) {+ C* I& Q
字段编辑器
% B% Q1 s& n1 Y0 ]4 v
解决了上面的问题后,我继续学习字段编辑器的作用。原来,DELPHI通过字
* X3 w: E1 [/ `9 W! Y2 ^7 ?- C+ Y/ q
段编辑器,近乎完美地实现了数据库的字段级的控制,这包括:
7 k$ m: S5 M. T7 \( @
1)字段在DBGrid中标题、宽度、能否可见;
" N& P1 m n% e5 \ U
2)字段的显示格式和编辑时输入的过滤条件;
5 a1 U2 r/ Q( L# Y9 I. i
3)字段是否只读;
# v* s. P$ K0 u; |0 `
4)字段的类型:数据字段/计算字段/查询字段/内部计算字段;
% u" k! k( B8 ~. D
5)字段的显示/赋值/修改等事件的定制。
$ B" y9 Q( O6 D2 _4 l7 Z* T
8 h6 n1 D' M7 H
B, P' k" \- ]" Q" A6 `% F
设计Form时的快捷键
+ N2 \- @# T" }( D7 w8 {
Del 删除所选组件
3 B) k$ _/ J, S
Esc 选择当前组件的容器(通常是Panel,Group或Form)
+ N* _& S; j9 j4 M0 Z1 S
F11 在Form或Unit和对象检查器之间切换
/ |1 B- Q) v! f4 j8 Z1 ]# F7 j
F12 在Form和代码编辑器间切换
( \' [* \: k, |% ]
Ctrl-F12 显示“查看Unit”对话框
, M, |1 S5 M- Q; Q
Shift-F12 显示“查看Form”对话框
! U# |4 {+ B+ k' E5 [% _$ U3 V: S' ^
TAB 下一个组件
# }0 Q- M4 ~/ U8 U5 n; J( y% O
Shift-TAB 上一个组件
# q5 g3 b/ O2 t7 X9 u+ _
方向键 选中此方向上最近的组件
: Y' G6 F2 ^8 p
Ctrl-方向键 将所选组件移动一个点
8 v/ l% _, D/ i; b6 i' W5 ]+ {
Shift-方向键 将所选组件改变一个点的大小
; k5 `4 \3 x3 X/ @$ u
Ctrl-Shift-方向键 将所选组件移动一个格
7 X% ?; d; R$ J6 b8 @! \
Shift-click 按住Shift键再用鼠标点击组件,可以选择多个组件。
- P0 r$ T! C% Y! p7 {7 z5 }( J
–= 下面这条是我摸索出来的 =–
8 P% }7 i K9 L$ A1 X
Ctrl-drag 按住Ctrl键在一个容器组件(如Panel,QReport,Groupbox等)
1 X- C7 @ z* K) S, I
里拖动鼠标,可强制选择鼠标拖过的矩形框中的所有属于此容
1 S" X( `6 h- r+ F0 F- a. k
器的可视组件但不包括该容器组件。
0 ~: W1 K2 P0 N+ Y" J1 ?+ ?/ K
& S2 q7 @$ X( l1 u- k) W& [
9 U7 F+ K/ [! r* C
使用QReport的若干经验
2 _2 A5 Q7 \& W5 f+ A% Q7 ?
1)QuickRep1.DataSet:=query1
' w' }: {; ^% V
不然无输出结果
$ x$ d/ V. ^* |; t4 ]
2)从qrpt2man.doc中查知,格式化输出结果的方法是:
. u1 ?8 t* `* @5 s
在QRDBText.Mask中设为.00;0,将使输出带两位小数。
9 L- n& U" K+ F4 U) r
3)设置Group时,先加入一个QGroup,再加入一个QRBand,将QGroup的
0 J Z4 \4 |: Q z) ]
FooterBand设为刚才的QRBand,就可将其联系起来。
1 H4 Q3 e5 g! Y) d! r+ K/ O
4)在Group中打印的合计数,其ResetAfterPrint设为True,可实现分组合
) Y9 w2 _' ~8 j" E2 ^
$ i( Q8 Q! o( l- r$ d. `
format(‘%*.*f’,[8,2,123.456]); //等价于format(‘%*8.2f’,[123.456])
# C! z$ Q% D; o" r5 n0 @
format(‘%d %d %0:d %d’[10,20]);
5 f- R: P# G j I, u; |
5 n1 F4 X7 ?& {( |9 S
+ m4 |) T* l4 V4 ~; B! O2 f, Z
! ^2 ^) v# Z: y v
播放一个wav文件
8 E* n$ `% t. [/ e
use mmsystem;
T$ q5 d% U7 Q$ [) ` f& P
SndPlaySound(‘hello.wav’,SND_FILENAME or SND_SYNC)
8 Y4 Z5 r: m& K4 y7 s& f; K
& I8 O0 L+ @0 f( M
使你的form适应不同的显示分辨率
9 m" y6 @$ N) L; R3 }0 s! T+ o
假设你在800*600的分辨率下设计的form,第一步:
/ }- c4 u( [8 t0 G' x' P
inplementation
, E5 j: k8 M! t2 H' h
const
0 B3 l2 e) c+ s7 M
ScreenWidth: LongInt = 800; {I designed my form in 800×600 mode.}
8 e2 Y) D7 Q% |, G8 w
ScreenHeight: LongInt = 600;
: Z$ ?9 y3 ]1 K3 c0 Z0 y5 P4 f$ v! J, W
1 N* n" Z1 d1 J$ Z( I4 a8 f
{$R *.DFM}
2 Z' q, W$ u/ K6 d
$ I6 X& g z' w; Y8 F' z
procedure TForm1.FormCreate(Sender: TObject);
( @: n8 w% s; b: ^# M( k7 _
begin
! {6 ? W- Q5 n* l1 o# P3 T
scaled := true;
; |4 |% ^: H' a
if (screen.width <> ScreenWidth) then
! g" M- w. h" ^3 i. n
begin
; L! s: N# N% S( h
height := longint(height) * longint(screen.height) div ScreenHeight;
: F( W& O( E3 M1 q
width := longint(width) * longint(screen.width) div ScreenWidth;
+ w+ O" N0 f7 V- m5 a
scaleBy(screen.width, ScreenWidth);
7 E( w- O/ x) b" I
end;
# j! H6 v/ W( O" O
end;
0 C3 @5 P5 ^# p# D
0 @' l# N3 o! R. G* H8 S
下一步,要让每个子控制的字体改变到合适的大小:
( R1 M/ f8 Z/ Z8 O, c
type
! z7 Z' V5 [5 W
TFooClass = class(TControl); { needed to get at protected }
) Q j' ^( V: F4 @
{ font property }
$ L' `, E* Q& W* {
|/ L- j. d! i/ w" G
var
) ~; G6 \& o0 S
i: integer;
: v: ~. D/ c/ i! Q
begin
$ ?2 ?) i6 o" _9 u [" `0 i
for i := ControlCount – 1 downto 0 do
1 O7 V. x; V- y' s9 Y- h! k0 K
TFooClass(Controls
).Font.Size :=
# j) h3 A! X! H
(NewFormWidth div OldFormWidth) *
$ `) |$ p4 G4 g& g7 [: i5 I
TFooClass(Controls
).Font.Size;
' v. W9 w2 v7 k# Z! P; W
end;
6 Y8 n1 X' u* V
( [& g1 n8 V7 u9 \' f8 m3 O
用raise引发一个错误处理例程
4 t* p! d' D! W- G( r
示例:先给出下面的定义
* x7 @5 { u/ D9 e+ ?
type EPasswordInvalid=class(Exception);
; u0 g4 }/ y% D! }4 t2 o
这样你就可以随时引发一个”password invalid”的例外:
& W) Y1 R( X3 E' M F
if Password<>CorrectPassword then
1 {8 O j# B" s5 l' p6 B! v, O2 |
raise EPasswordInvalid.Create(‘Increect Password entered’);
0 ]2 k! p$ k: B" L. [- E6 a
运行后,出现信息框
$ |5 Y6 @7 e6 y
Project Project1.exe raise exception class EPasswordInvalid
$ H5 M7 Z) Q6 g" s1 _
with message ‘Incorrect Password entered’. Process stopped.
+ n4 x2 q/ O, @# |: _
Use step or run to continue.
1 P! Z- m7 x0 G% a' V1 m: k: V0 Z3 ~
再按Run按钮,出现一个信息框:
& v x8 J4 B2 ~# m# u# r
Incorrect Password entered.
( d1 G) [- S' ^' J
& {) ^/ W4 Q5 e
# Y6 R1 `$ h) b" B3 V
从DEMO例程中学到的若干小技巧
9 L: o4 @/ R' C7 w8 O9 m
在demo\internet\http\webbrows\main.pas中,
/ w* j v, k7 \" h& Y/ L
procedure TForm1.DocumentSourceClick(Sender:Tobject);
% W# @; y# Q- z( p
begin
6 b, T1 M/ E9 V( @
with DocSourceForm do
$ O5 G: M& h8 r! e
begin
+ O* U( I# i4 K1 [ ?" @: E5 R
show; // 显示HTML源码的FORM
Y2 Z3 _, m3 L5 C* K N
Memo1.lines.clear; // 清空memo1中内容
8 i+ ^1 X5 [$ x3 c+ E2 X, N
Memo1.lines.add(HTML1.SourceText); // 植入源码
; X4 O" y1 K) B! [2 m5 \0 {+ r1 a8 _
Memo1.SelStart:=0 // ***
; x5 f) h5 f2 o) [, R
SendMessage(Memo1.Handle, // Memo1的窗口句柄
, c/ [, w8 ], [: j
EM_ScrollCaret //将Edit Control中的caret光标滚动到视野中
+ v( R. q2 y) a1 n2 g
0,0 //这两个参数暂不使用
% c7 T1 j, t& A/ Q
end;
: p3 v) F2 `- q7 f% ~4 K, S
end;
7 a- E! c7 |+ Y* M9 B2 I
(此SendMessage系一WinAPI调用,给一个或一组窗口发送消息,直到
# ^5 n( z8 v. X% P0 D
相应窗口处理此消息后才有返回值。相似的另一函数为PostMessage,
% b" v3 r2 p0 i- H( [
它将消息放入消息队列中后立即返回。)
* C! J; K: g4 p9 y, [5 ^0 L( i# ]
*** 清空当前选择并将光标移动到指定字符(0代表第一个字符)。如同时
( K+ k& Y8 |7 o2 o' E
设memo1.sellength为一非0值,可选择一段文本。
- r3 T. e1 X' n( S& k9 I" s
+ ^0 ^+ _$ n5 C- M5 b
! t/ w' _! q \
奇怪的I/O error — 我在开发过程中发现下面这两条语句
# o$ m: s& l' o8 ]5 b
assignfile(fDesc,CDDatadir+describefile);
3 {* c2 K4 f1 j3 n
reset(fDesc);
; i1 H8 `4 a2 c& D! h% \* R7 j& A
每当我第一次运行到这里时,总会出现 I/O Error 183 的错误.
+ `1 @6 j" u8 z6 `2 Z
最后我想这也有可能是没有清除 ioresult 的原因.在两句之间加入
' H7 N9 }+ a5 R
if ioresult<>0
* ?# ?# ]& x- @/ m: d( ?0 k
then;
9 V4 U. A' W3 W0 H) U7 {
oooook! 可以了.
8 h4 y- x7 c1 D' ~6 f" w! d
) i8 t6 D6 T- z: o
0 t+ C2 w; w$ `7 f! [- u9 V
值得注意的I/O error
6 A% |1 Y3 p5 @# P/ C
AssignFile(F, fname);
. E `' o& O5 ~: [7 u7 I6 X1 r
Rewrite(F);
9 r& n3 x' O4 J
当文件 F 经 Reset(F)打开的情况下, Rewrite(F)会引发一个异常: I/O error 32
* Y5 y. g, V+ F
反之,经 Rewrite(F)打开, Reset(F)也会引发同一个异常.
6 Y' w w+ c( m# M- d+ z$ `
Reset(F)两次,closefile(F),再Rewrite(F),或反之,也会引发同样异常.
# Y' }# e/ o6 o+ f. |) }
8 L8 L. b% p2 C8 k% ~
& P/ W( |" B/ I- U, B2 T
9 |2 L7 ]( m7 Q3 i- G
string和pchar的相互转换:
) v1 G* G5 T* |# o( w4 Z- V
string –> pchar: pchar(s
! `' k W& q& H9 H; p
tr:string);
9 h7 i) Q m9 z3 }8 g$ C
pchar –> string: strpas(p:pchar);
; l, i A3 A* U
5 h b R) t) O+ V' D2 F5 I k
8 I* c t R5 r1 ]1 O( D+ [
8 t6 P1 S8 t8 S. ~8 A/ b
在Delphi代码中定义数据库
# H3 g; A, _. P
procedure tform1.create_tbl;
% z$ v$ k. B: s7 k
var tbl:ttable;
1 X4 X$ ~* c- W) N4 S
begin
' l" o5 n% g4 I1 j
tbl:=ttable.create(self); // 如没有声明中的”tform1.”,Delphi不认这个self
9 T- Y5 \5 H$ ?" f/ P1 m
with tbl do
9 L7 E6 T0 ^0 x# x) E6 s: e
begin
5 c1 y& n; M& p" X
datebasename:=;dbdemos’;
, O3 j3 A; [ E9 f: _6 J* d: ?* ]
tablename:=’my_tbl’;
6 \. b. W0 @, u/ X; Q* W- o& i
with fielddefs do
/ [: V5 W) R: q" l* N) _
begin
, o2 K- X* }3 S9 J7 j) F0 B+ s
clear;
% V- I7 a5 Z6 _# s4 \
add(‘No’,ftInteger,0,false);
/ a* C" s9 C. q* G
add(‘Name’,ftString,0,false);
, w# z5 p: M' D, n5 ?
…
+ }4 D# E+ N8 ?* `- H* `7 X5 `3 s
end;
6 ^; ^3 l3 i% P2 o
with indexdefs do
n5 o5 A" s% k1 E7 s
begin
8 ?6 q! r$ s4 e
clear;
_: v( c. Z0 g2 D) |
add(‘primary’,'no’,[ixPrimary,ixUnique]);
% t8 p- o- U' @- a
…
+ F6 X: D# _, C( s9 U% p
end;
6 q4 }( ?* c9 z5 ^: T
CreateTable;
5 Y4 N0 a* w$ l5 k m' M6 L0 W
end;
, R; `1 t" v4 S/ {
end;
) r) h# G) W+ r$ v8 x
" h/ g( O8 l$ t9 G1 h6 m" ^
+ J/ H/ }; v c7 }, d/ F1 m+ f9 G
string、TStrings、pchar的相互转换(这里是我的个人经验)
8 j) X! a+ p3 L7 Z0 u
假设有如下定义:
$ b- M# ]5 V ]4 x( G% q# F3 h# K2 M
var
7 ?; K" `+ w1 a4 @- r5 U5 _
p:pchar;
( x9 H; i! l1 _. v* U
s:string;
5 Q% L- O: R- ^/ K
ss:tstrings;
% C) d3 l: y" C# M$ S. X4 J- { x$ v
begin
; O s/ C% e! k4 m
ss:=tstringlist.create; // 开始时一定不要忘记创建ss
2 h$ S. D6 X% a4 i4 y& m
ss.text:=s; // string –> tstrings
# }, v, p! P. \) C9 K8 g" C. ]
s:=ss.text; // tstrings –> string
! }7 A; M& _7 S* i, J I
p:=pchar(s); // string –> pchar
/ ^% V: l B4 v; h
s:=p; // pchar –> string
8 `& @/ R) O* F% a$ ]/ W
showmessage(s); // 合法语句
9 n+ R/ i& B- ^; y
showmessage(p); // 合法语句
5 q8 k! H0 k* B- }- o
… …
6 q* a0 i& c- |1 n& s* Q- Y
ss.free; // 最后还要记着释放ss占用的资源
4 S$ C) t( t0 S3 y' p
end;
( e, o* o5 H+ t
+ U- y/ j6 |$ V2 `; b
: Y0 h9 F3 o/ f* ]+ m
. W' }# J" e; ]
在设计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