標題:
delphi 技巧合輯
[打印本頁]
作者:
segaa
時間:
2010-3-10 04:40 PM
標題:
delphi 技巧合輯
INI文件的操作要点
* q! q! } a2 t6 K% r4 _ f+ o
(1)在interface关键字后的uses子句中加入
1 T* C2 ~$ c0 ?- f7 {! g1 g- P8 l
uses …,inifiles;
! G0 h( Q! E3 b/ \& l8 [
(2)设置变量:var inifile:=TIniFile;
! B9 s; j, ^3 q- f9 A
(3)使用前,一定要先做:
" t9 J/ k1 _ z+ c
inifile:=TIniFile.Create(inifilename);
7 D5 {/ @$ {. D
我在这里绕了个弯子,写成
4 ^) b$ E, v0 i/ O" f1 y( ?/ q
inifile.Create(inifilename);
, Y. p. _) Y1 y8 w7 Q( H+ p; }
& o; n" i5 m& q2 |5 ?- |
TShiftState用来检测CTRL,ALT,Shift,以及鼠标按键的状态,
: A5 j) z ]0 X3 Z4 A% F
常常用在键盘或鼠标的事件处理程序之中。
P9 W$ J- x; ~
6 c5 n! r- \! j1 _: R: E* L
DCU文件(编译的库单元)的重用
, X8 S, k* R! |0 l' z* }0 F, b
(1)在interface里的uses子句中引用。如Windows,Dialogs,
2 }* E: t7 x2 P, @
等等,要求被引用的DCU一定要放在Delphi 3\Lib子目录中。
' @7 O3 E/ |; g
(2)在implementation里的uses子句中引用。如果是自行编写的
1 {7 }. T) O' r' X8 }8 k
DCU文件,应采用这一方式,并将被引用的DCU文件放入当前
2 r2 p2 d6 K# t+ i4 ~3 ~) l. O* z3 i
工程所在的子目录中。
( Z" h' @: [- ]
executefile函数(在FmxUtils.DCU中定义)不能用在FormCreate
; h7 H3 n0 _2 M5 ]/ f1 W
事件中。真奇怪……
" ~; N: r# \2 A0 G
5 S2 M) N% P9 ]
内置的版本号控制功能
. f& f0 \8 `: P; ]
在Project Options中的VersionInfo项里,有版本信息的定制,
' m; k* S. d, u& P/ ^% P
包括一个有趣的版本号自动增加功能(Auto-increment build
3 H1 c$ b, g, D
number),即每Build一次,版本号中的Build Number加1。选中
" g- q4 b1 q. W8 ~
Include version information in project,编译,用资源管
- M; D# F# u' r9 Z$ y
理器里找到生成的.exe文件,点右键,查看“属性”一项,就
' @5 C9 }& ?) u. A0 f" ^/ U. c
会看到在属性中多了一页“版本”,里面就是你刚才输入的各
( {+ r% J% o J
项内容。
D( _6 C6 \* g
* ]( G$ R$ V6 v! Q8 S( J: C
: y& Z, c. L, H& Y+ y& C* }5 i
定制Speedbar
& j0 i8 O4 {" ~
右键点击左上角的加速键条(speedbar),选中Properties,
& _+ n: B" w9 y! D; ~% L: \
在列表框中找到你想要加入speedbar的命令按钮,将它拖到
5 ^7 E U& J" N
speedbar上的合适位置即可。如果speedbar上没有多余的空间
$ U4 X0 S k% U R) H. |
来容纳新的按钮,可把鼠标在speedbar右框处变为双向箭头的
( E5 Q2 L# M4 U& m( \, {
形状,向右拖动一段距离,就可腾出空间。如想删除speedbar
6 G5 N, `* f- c' h( J6 w) t4 D
上的某个按钮,可简单地把它拖出speedbar的范围,就能删除。
3 w; v2 l$ c7 ]& \/ v8 D8 M
) h9 Y( ^' U" i) C
8 X& a+ O- ~1 j. ~
计算出的字段
( M' d* o1 s+ _* J b+ Z0 f. D( G
在写一个程序时,我要在DBGrid中显示出一个memo的部分信息,当我把那个
9 e+ E2 w& E6 U" Z/ o R0 _0 }" _3 N
memo字段放进去后,运行时只能显示出“(memo)”字样。从书上找到计算字
+ S; r: _/ M$ \9 |' @0 z8 U. d
段的用法后,我在TTable中增加一个计算字段MemoHeader,宽度为40,在此
: {2 O& g! I( d) k
TTable的OnCalcFields事件中输入:
- I* D) z, j. W" y; C6 N- p
with MyTable do
C( M' p. g) A
FieldByName(‘memoheader’).asstring:=FieldByName(‘memo’).asstring;
+ W; W" q6 e8 P" Q8 y1 j
在DBGrid中放入MemoHeader,运行,OK!
5 b+ @) }8 Z: F" v8 `
! d, Q9 c8 i7 q2 A# j
2 C5 C# _/ K7 \! M z1 ~; B
字段编辑器
8 t u9 ?1 F" Y4 R# w
解决了上面的问题后,我继续学习字段编辑器的作用。原来,DELPHI通过字
- |+ G# X9 I( Q* Q' ~* R
段编辑器,近乎完美地实现了数据库的字段级的控制,这包括:
/ o0 G, h& B; d
1)字段在DBGrid中标题、宽度、能否可见;
! s9 l- t0 x* y9 x! S: [0 p& l
2)字段的显示格式和编辑时输入的过滤条件;
2 F7 {3 @0 F% d& E% D, W
3)字段是否只读;
, V) @6 i/ q' M1 p# O+ _- @6 Y
4)字段的类型:数据字段/计算字段/查询字段/内部计算字段;
8 p4 e3 a( b- F# Q) y1 J
5)字段的显示/赋值/修改等事件的定制。
3 r0 j& v( _1 u$ T6 p7 T4 o; b; p5 G
: h q7 p, L+ u" ]! c) Z
* @, K+ K' B1 ^/ F
设计Form时的快捷键
D7 w# \0 ]3 Z. f! R7 m0 r
Del 删除所选组件
5 M% y1 ?, i+ \
Esc 选择当前组件的容器(通常是Panel,Group或Form)
7 E+ H- F7 T+ `
F11 在Form或Unit和对象检查器之间切换
; p! |9 D& \! o% b3 Y5 o9 t4 A) ?
F12 在Form和代码编辑器间切换
( r; @+ z% u: n/ ]+ ^2 |
Ctrl-F12 显示“查看Unit”对话框
5 T" I: ^* Y0 E& ]
Shift-F12 显示“查看Form”对话框
" U9 b2 p2 C1 w6 X% S
TAB 下一个组件
- U: \! k* n0 o) P& F
Shift-TAB 上一个组件
/ j Q% m' v! |: n) ^- g
方向键 选中此方向上最近的组件
% |" P! @- N3 e! X1 ~( B( V5 h
Ctrl-方向键 将所选组件移动一个点
: q7 u$ x3 e) {- Z( U# K
Shift-方向键 将所选组件改变一个点的大小
& e. [% k2 A% D( l# z9 d4 e
Ctrl-Shift-方向键 将所选组件移动一个格
. o0 [2 N( B& ]1 `4 o
Shift-click 按住Shift键再用鼠标点击组件,可以选择多个组件。
0 @( b7 U' q+ o" m; Z5 N9 G1 S: W5 B
–= 下面这条是我摸索出来的 =–
5 k4 u7 T- e2 {
Ctrl-drag 按住Ctrl键在一个容器组件(如Panel,QReport,Groupbox等)
5 f e5 J/ n/ }9 X6 f- S
里拖动鼠标,可强制选择鼠标拖过的矩形框中的所有属于此容
! B9 C" h( D* f( Q7 x, {
器的可视组件但不包括该容器组件。
! i: ~+ j% y$ [6 Q% M7 z
; h/ e# ?/ f( C- L1 `
1 L/ o4 M; n% Y
使用QReport的若干经验
, ]6 o R7 d2 F8 |: H7 s0 V
1)QuickRep1.DataSet:=query1
9 L) b6 }$ s0 r% I1 n, ^
不然无输出结果
. o* n( x- b* t
2)从qrpt2man.doc中查知,格式化输出结果的方法是:
% e& b! X# V9 g3 c
在QRDBText.Mask中设为.00;0,将使输出带两位小数。
* y3 l- e' O4 M4 _# F/ I, y
3)设置Group时,先加入一个QGroup,再加入一个QRBand,将QGroup的
& u, W3 w+ w$ P
FooterBand设为刚才的QRBand,就可将其联系起来。
5 W5 m, [& R% e# C8 _5 a( Y! P
4)在Group中打印的合计数,其ResetAfterPrint设为True,可实现分组合
, S, Z* n) ?) ?2 O+ I! b' y
; A$ [0 q% h- ?0 N
format(‘%*.*f’,[8,2,123.456]); //等价于format(‘%*8.2f’,[123.456])
6 [2 a6 Z W" I: b4 V
format(‘%d %d %0:d %d’[10,20]);
% m) b. c/ r; d/ H! ]
7 d+ U. O ], h& L1 _3 N4 ]
; k; B7 ^( f) V! v7 O M4 D
; j) W0 m* I" B+ h0 [6 D
播放一个wav文件
5 ]9 F" Z1 U- S2 l0 b( {/ A
use mmsystem;
" `$ i# d) H; X# W0 f
SndPlaySound(‘hello.wav’,SND_FILENAME or SND_SYNC)
" ]" u0 |6 [2 @7 j) Z
- H+ p L: \$ }1 H8 d
使你的form适应不同的显示分辨率
4 D, {4 U z9 k7 i9 I/ L
假设你在800*600的分辨率下设计的form,第一步:
" R8 S' `# {/ v: @. W/ ~- h
inplementation
/ b1 U5 o& [5 x; E
const
% R' X$ t8 ?/ ?9 K8 L% _2 ~& |
ScreenWidth: LongInt = 800; {I designed my form in 800×600 mode.}
) Z7 ~& d P% z$ P- j
ScreenHeight: LongInt = 600;
7 o" A- b: @3 _6 q! q% R7 @4 k
3 `6 R; g& b6 w! U* A
{$R *.DFM}
0 a; o$ z- Q! v: Q! g
; h% ?! x) D% {
procedure TForm1.FormCreate(Sender: TObject);
2 `1 U& ^# h- U0 B
begin
$ w Y4 ?. U! Q3 } i
scaled := true;
# U7 m6 Y( m( y0 T
if (screen.width <> ScreenWidth) then
( _' m. d: T4 Y- X8 O6 S' q
begin
1 O* \' t( v3 k) i9 r) K/ d, [$ L
height := longint(height) * longint(screen.height) div ScreenHeight;
7 [& E, I6 ^4 \# t8 M
width := longint(width) * longint(screen.width) div ScreenWidth;
6 Y% S f9 ~8 C. l2 V+ a% M3 c3 e8 ^( {
scaleBy(screen.width, ScreenWidth);
& O A. t; y) i9 S6 \
end;
8 l. _. Y, F% S% [( Q: W" k
end;
( V$ G9 W8 l' r) C' x' M
) {% f0 i- w2 \5 G
下一步,要让每个子控制的字体改变到合适的大小:
# M' \2 O) _2 T3 v2 l: d f
type
: t/ q8 r1 c+ T! b* ]
TFooClass = class(TControl); { needed to get at protected }
% x0 y6 _1 o, s2 Y, G0 v
{ font property }
! C. E7 |7 N0 Y7 x# i* `3 |
. k6 j% b `4 w! g
var
8 F& K8 l- b7 m3 J( K0 C$ p* n
i: integer;
( E8 I8 l9 ]) ]) n0 W
begin
6 d- I9 x1 g. h6 i7 Q* S
for i := ControlCount – 1 downto 0 do
' M" f2 A4 C9 \2 v: \% Y
TFooClass(Controls
).Font.Size :=
0 d# l! s$ U( P9 I0 {
(NewFormWidth div OldFormWidth) *
3 ?7 L6 x. D0 ?2 A* H2 S/ q
TFooClass(Controls
).Font.Size;
/ j5 Y. ?" ], f8 {1 |
end;
/ ~$ r0 D7 H% w* }
, V$ l' M3 S, i! {
用raise引发一个错误处理例程
- V9 h" _ O! j! D+ _8 ?
示例:先给出下面的定义
$ [( F3 V7 q3 ~# c" q# J
type EPasswordInvalid=class(Exception);
, y+ Y& X( P6 c' c: S
这样你就可以随时引发一个”password invalid”的例外:
2 R# o+ j1 b0 C. Q/ g3 Q( T* J! _
if Password<>CorrectPassword then
' r$ k! H, A6 V! b, K
raise EPasswordInvalid.Create(‘Increect Password entered’);
$ A5 Z* J T; U6 z4 ]; S) F7 J/ i
运行后,出现信息框
6 I* p8 _* j9 a( b+ E1 g4 k
Project Project1.exe raise exception class EPasswordInvalid
! Q" T* A# {+ g& S3 o
with message ‘Incorrect Password entered’. Process stopped.
( a9 t6 o0 q- i
Use step or run to continue.
3 s+ _# I; N7 j- k5 P( ]
再按Run按钮,出现一个信息框:
# L! H* R" p+ \2 w. c! d' |
Incorrect Password entered.
9 @, C$ r F5 L. j& T ^
* E t O3 }2 X4 r( K
3 C5 l. }; T6 q* U3 R
从DEMO例程中学到的若干小技巧
% U2 K7 D$ l& f
在demo\internet\http\webbrows\main.pas中,
2 R& E" M) M/ I Q+ r7 z
procedure TForm1.DocumentSourceClick(Sender:Tobject);
* B$ v9 V# g9 G2 {( k3 j: u
begin
' O$ `2 S7 E' V' |
with DocSourceForm do
1 B( \5 K' e* Y+ J( s: c$ u* o
begin
6 y4 n! J' w* J4 e$ Q1 t* M
show; // 显示HTML源码的FORM
( f2 m) E5 Z2 M- ^$ I
Memo1.lines.clear; // 清空memo1中内容
3 _' o+ {5 { e8 A% I" A& m
Memo1.lines.add(HTML1.SourceText); // 植入源码
5 u! V- \7 I# E# ^- E1 u
Memo1.SelStart:=0 // ***
: J, N W6 B0 K- x
SendMessage(Memo1.Handle, // Memo1的窗口句柄
5 R- Y+ g% m; m% M
EM_ScrollCaret //将Edit Control中的caret光标滚动到视野中
, b6 Y! {; {2 s
0,0 //这两个参数暂不使用
4 U7 S9 N: M& ^
end;
) |9 }- p. I! V+ P1 T9 f) Y
end;
. U" m/ Q- {! \ E7 a
(此SendMessage系一WinAPI调用,给一个或一组窗口发送消息,直到
% {7 _9 a3 D5 e; A8 h6 j; _
相应窗口处理此消息后才有返回值。相似的另一函数为PostMessage,
( U, E0 A/ b1 h3 O' D
它将消息放入消息队列中后立即返回。)
* W. C+ A; }3 y" X6 \. p6 p
*** 清空当前选择并将光标移动到指定字符(0代表第一个字符)。如同时
' d L# p" b+ x
设memo1.sellength为一非0值,可选择一段文本。
' I; Y# Y/ D7 ]; W0 I
1 u7 L0 B8 C- \2 K4 v
) j3 a+ C5 ?+ y' R$ O( E
奇怪的I/O error — 我在开发过程中发现下面这两条语句
& T% t: O, ~9 o& l; @
assignfile(fDesc,CDDatadir+describefile);
/ ]5 @& F9 G9 a) m# C
reset(fDesc);
3 L8 ?- m$ R/ K' i: x2 F
每当我第一次运行到这里时,总会出现 I/O Error 183 的错误.
: D6 w7 `0 F+ Q Y/ w2 w
最后我想这也有可能是没有清除 ioresult 的原因.在两句之间加入
0 z# K" G7 @! t* G+ ^
if ioresult<>0
1 X* b/ J( V# S6 i; [" E* `# X
then;
7 C& O' X, M& H, @6 h3 A
oooook! 可以了.
" f" |5 e$ e0 u0 w. b K: C
- O# V0 I" R) G2 Q/ N' w1 N
; K7 g6 m' h7 i) B2 y, L. A" q X1 f
值得注意的I/O error
- y, c( C1 {2 t$ }
AssignFile(F, fname);
C9 m. v w6 Q; c' f5 x: J# z
Rewrite(F);
& D$ L! e& l4 Z2 F- B
当文件 F 经 Reset(F)打开的情况下, Rewrite(F)会引发一个异常: I/O error 32
- N @. T9 h) | e
反之,经 Rewrite(F)打开, Reset(F)也会引发同一个异常.
- Z A( ]' ?/ o( h/ ?
Reset(F)两次,closefile(F),再Rewrite(F),或反之,也会引发同样异常.
: N& a. Q& R- w3 j! o; l
- ?( e+ s, ^9 H& g" m2 u; ~. N. I: Z& q
: a0 e$ V5 l1 k: r
. m$ F F$ b; U) m4 M' r. Y
string和pchar的相互转换:
2 i3 T* a1 }, u6 U7 h% o/ h% D
string –> pchar: pchar(s
4 s* y" o7 Y5 Z4 H% I
tr:string);
5 v9 S. W: A& \. C$ f) f( E: l1 _1 n* T
pchar –> string: strpas(p:pchar);
8 i7 w0 _$ d0 D# t2 r; z# L9 Y! X, `
0 F4 q2 r% S, h0 {
4 A. L# m* l$ }9 w1 H* b7 [/ @( G& W
9 a% |1 R, `! E9 _6 i
在Delphi代码中定义数据库
% p2 E' H1 d3 c8 b
procedure tform1.create_tbl;
/ N! o) [$ Y5 m/ t9 O7 b
var tbl:ttable;
" W5 ]$ G9 d t) e8 P6 ~" t1 G
begin
, \: Y, P. l6 @# n% I# V1 p
tbl:=ttable.create(self); // 如没有声明中的”tform1.”,Delphi不认这个self
; w: H2 ?/ c' |
with tbl do
5 s7 r: a+ v t. A
begin
7 {2 W$ @( |2 R1 `: g/ T' G
datebasename:=;dbdemos’;
! m5 i) w" m! @9 u3 c6 H: l
tablename:=’my_tbl’;
3 W0 v6 F( {. ]
with fielddefs do
/ f" `! X b2 y- ?5 t. [+ m
begin
, V4 X: h& l7 l* {' t
clear;
8 O( u& N$ m% N2 i4 l6 C- K
add(‘No’,ftInteger,0,false);
+ }9 P+ A: _( l2 Y
add(‘Name’,ftString,0,false);
1 t2 w& w" R9 S% D/ J
…
0 \4 S0 ^* v0 |: M
end;
6 S" Z" W6 ~- T7 ?- K3 r8 ?
with indexdefs do
2 m5 j0 p! _' o
begin
9 g# ~: f6 a. ~, ^2 l. w6 p- Q
clear;
, I5 Y( s/ ]# |' y/ E' A
add(‘primary’,'no’,[ixPrimary,ixUnique]);
- C) X: `; C1 J& x% }* v
…
: i) Q3 a+ O( e
end;
' `8 [; k# @7 x9 `
CreateTable;
+ Y$ a# A/ o! c
end;
- J5 P. ^2 y' ]' T& ]
end;
1 M8 d* l o# _( E' F% t; y& o! `& a
! O8 T& g! @! x$ v( ]% F
) J A4 m, `4 G( w6 R2 E# N
string、TStrings、pchar的相互转换(这里是我的个人经验)
4 e* i3 H2 f# {# k6 c
假设有如下定义:
' X% c. `3 t5 B: n8 m4 w" e7 N
var
* p/ E5 P# R# n1 }& a
p:pchar;
9 F/ \# f" v& c v
s:string;
1 {8 j! {3 u; x* j' }& ]$ l; a
ss:tstrings;
( `, I7 @1 B1 j* y& D
begin
; J( Z. V m2 \. y, W9 o
ss:=tstringlist.create; // 开始时一定不要忘记创建ss
, o/ ]- d3 l3 r. H) f% z- d' r
ss.text:=s; // string –> tstrings
' _ J& ^* A* S# P
s:=ss.text; // tstrings –> string
# c \7 d$ T4 F2 r9 V
p:=pchar(s); // string –> pchar
( R& q- \* M! @9 Z6 a
s:=p; // pchar –> string
! k1 `4 i. V0 r' {. w( a) a
showmessage(s); // 合法语句
2 S- g3 h$ {4 i
showmessage(p); // 合法语句
. Y& v2 i" X+ K" q+ j
… …
\# C. C' F. Y K A# }
ss.free; // 最后还要记着释放ss占用的资源
5 ^# n/ E, k7 \
end;
P! S+ x3 f+ m: n, y7 t
) _! |7 u% @, p' k
. Z Q, F( t, d8 @0 |. x' f6 {5 |
! b/ A/ K' J* m0 r
在设计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