標題:
delphi 技巧合輯
[打印本頁]
作者:
segaa
時間:
2010-3-10 04:40 PM
標題:
delphi 技巧合輯
INI文件的操作要点
) v% w* C0 R6 \" t! x- ?
(1)在interface关键字后的uses子句中加入
1 J9 O+ S! d7 W" [; P2 V
uses …,inifiles;
7 Q7 N, |2 G# M! t, w/ t5 H
(2)设置变量:var inifile:=TIniFile;
% t! o3 ]0 w$ v
(3)使用前,一定要先做:
; @" d8 t$ T" W6 g$ ]
inifile:=TIniFile.Create(inifilename);
/ N. ^8 \% B, m2 t
我在这里绕了个弯子,写成
+ E) {4 h. t" h' W" z" [! W
inifile.Create(inifilename);
3 w2 g! U0 C; _# A
' k% \- v0 B9 j6 S$ t/ C
TShiftState用来检测CTRL,ALT,Shift,以及鼠标按键的状态,
. L2 }) B7 W/ j" j) S# P) S
常常用在键盘或鼠标的事件处理程序之中。
! v6 m5 @7 n. B
) N% t7 j( [7 n
DCU文件(编译的库单元)的重用
! G) |9 j* h$ ?8 M. W
(1)在interface里的uses子句中引用。如Windows,Dialogs,
9 @! ?$ j2 B2 {; l3 U
等等,要求被引用的DCU一定要放在Delphi 3\Lib子目录中。
# l- b6 ~3 W' C
(2)在implementation里的uses子句中引用。如果是自行编写的
- \& ?$ U/ V3 p) K" d" I) t
DCU文件,应采用这一方式,并将被引用的DCU文件放入当前
5 l& i U0 ? i% w8 n3 g
工程所在的子目录中。
2 J' j) |: D' L, c% c7 Q+ \
executefile函数(在FmxUtils.DCU中定义)不能用在FormCreate
5 Z: ?# u- m5 F
事件中。真奇怪……
, c( P6 W. r- v/ \" G: ]0 t
' E V2 X+ ~' r9 }
内置的版本号控制功能
! i, P8 c# w8 K0 t9 D
在Project Options中的VersionInfo项里,有版本信息的定制,
! L' ~: q7 o6 u' y% z' `
包括一个有趣的版本号自动增加功能(Auto-increment build
' E- T; p0 ?1 T" m8 y2 Y, X8 D H( Y
number),即每Build一次,版本号中的Build Number加1。选中
( ~ u1 O+ m6 |! [& _
Include version information in project,编译,用资源管
, n5 G! T1 d! O5 B
理器里找到生成的.exe文件,点右键,查看“属性”一项,就
4 V- M/ p6 ]6 B! o J0 c+ ^
会看到在属性中多了一页“版本”,里面就是你刚才输入的各
6 P/ j* u6 V) `2 R/ [) Y* I
项内容。
/ a# O5 {0 Q% n+ p* a3 G7 _
m7 R" h$ }5 X7 w/ N
Y% o( s ?5 F8 V/ N$ Y; o
定制Speedbar
3 W9 `0 l+ `/ R5 C1 F6 C+ J* p6 q
右键点击左上角的加速键条(speedbar),选中Properties,
! x" O2 f$ j* x( h, h" ?
在列表框中找到你想要加入speedbar的命令按钮,将它拖到
/ h, S' s8 [) H$ `5 p
speedbar上的合适位置即可。如果speedbar上没有多余的空间
; y1 g: f5 w) U( T
来容纳新的按钮,可把鼠标在speedbar右框处变为双向箭头的
8 W, y0 x: w8 `5 {
形状,向右拖动一段距离,就可腾出空间。如想删除speedbar
1 }; k0 H% k; i+ j1 N
上的某个按钮,可简单地把它拖出speedbar的范围,就能删除。
Y! M# f- F* f" t0 Z$ e
! ?4 @0 c; |; I; M3 Q( X H
8 p4 Z+ _; u: O( P8 |) \8 f
计算出的字段
1 C* v4 @, K5 p
在写一个程序时,我要在DBGrid中显示出一个memo的部分信息,当我把那个
/ F8 T4 T) ^$ U% w& G$ {8 L9 Y
memo字段放进去后,运行时只能显示出“(memo)”字样。从书上找到计算字
( ~: O+ p. e3 G. S) X
段的用法后,我在TTable中增加一个计算字段MemoHeader,宽度为40,在此
; n1 }* @' f- g, x! [* }8 U5 I" k
TTable的OnCalcFields事件中输入:
* c z/ s) p3 ]
with MyTable do
- h6 v# w& ^: U& q
FieldByName(‘memoheader’).asstring:=FieldByName(‘memo’).asstring;
1 j. o2 ]) F! B
在DBGrid中放入MemoHeader,运行,OK!
8 j& o7 v3 `4 L2 y* e
6 x" h7 a6 }* Z2 J) d# R6 f
7 V$ o* ?! I$ R) i- Q O) M& d$ j. r
字段编辑器
: c! L$ k; |" Z8 T
解决了上面的问题后,我继续学习字段编辑器的作用。原来,DELPHI通过字
" Q" b$ s2 ]. f2 u, Q, h
段编辑器,近乎完美地实现了数据库的字段级的控制,这包括:
2 }; a, R$ ?' A9 l5 e
1)字段在DBGrid中标题、宽度、能否可见;
& R7 N }' D6 r# u: T3 n
2)字段的显示格式和编辑时输入的过滤条件;
7 s, h8 M3 m, U2 k% _
3)字段是否只读;
1 ?. q+ P# B; l% y4 C
4)字段的类型:数据字段/计算字段/查询字段/内部计算字段;
. d2 o+ @4 C7 S/ T7 T4 b7 l( J
5)字段的显示/赋值/修改等事件的定制。
3 ^/ Z. S6 d9 _2 x, `& I
. R$ Z4 P, c9 s. n& h4 X) G" c7 t
5 S8 |* }! M% S: d0 S2 x, e
设计Form时的快捷键
" t d2 _, T7 h( F1 `" s0 G3 e# ]2 }: ?
Del 删除所选组件
* r) H R9 w+ ~: [$ w! ^ M; T
Esc 选择当前组件的容器(通常是Panel,Group或Form)
8 M( p5 P/ u8 V
F11 在Form或Unit和对象检查器之间切换
7 |2 Y6 ?! l) P: J2 m
F12 在Form和代码编辑器间切换
# \6 _7 C, ~& t1 i
Ctrl-F12 显示“查看Unit”对话框
1 Y, ?; @5 ~+ [+ V3 c
Shift-F12 显示“查看Form”对话框
- l! J* a1 o- I% Z# L: A9 a! f! Y
TAB 下一个组件
! |! E$ r* W z+ Q" \0 [, U
Shift-TAB 上一个组件
8 b1 w% o ^7 M# R# E
方向键 选中此方向上最近的组件
6 s- D, ?2 l `0 V
Ctrl-方向键 将所选组件移动一个点
- @* x% r. d2 T, @- G
Shift-方向键 将所选组件改变一个点的大小
" c( o3 X1 Y9 ^- o! F6 A$ \) c# [) @
Ctrl-Shift-方向键 将所选组件移动一个格
$ n3 i) u- S4 O3 S# E% _- s
Shift-click 按住Shift键再用鼠标点击组件,可以选择多个组件。
- |/ w e5 E) ^# E
–= 下面这条是我摸索出来的 =–
8 m+ e6 v' V) S3 h
Ctrl-drag 按住Ctrl键在一个容器组件(如Panel,QReport,Groupbox等)
3 c# Q( i* Q0 [) d6 e- r
里拖动鼠标,可强制选择鼠标拖过的矩形框中的所有属于此容
/ _/ c+ D _. N# x
器的可视组件但不包括该容器组件。
8 f6 @9 r- V9 @9 ~( z6 u" ~
# A! |1 ?# e$ m- P$ V& ^( o
! l7 P% g v9 D6 [0 E! x: ]
使用QReport的若干经验
" J" O7 X* E' n* l+ ]- ~( w+ }
1)QuickRep1.DataSet:=query1
$ e2 l% w! H6 O, `! d/ ^1 L
不然无输出结果
: _/ H1 U9 L; l0 @) v
2)从qrpt2man.doc中查知,格式化输出结果的方法是:
* y) c( V3 ?7 n( A" y
在QRDBText.Mask中设为.00;0,将使输出带两位小数。
0 r' a7 T8 Z! u4 N7 v% h( W
3)设置Group时,先加入一个QGroup,再加入一个QRBand,将QGroup的
; X4 I+ e" w( Y" C8 Q* j( W
FooterBand设为刚才的QRBand,就可将其联系起来。
# C6 G; L9 h7 F9 a
4)在Group中打印的合计数,其ResetAfterPrint设为True,可实现分组合
1 G8 |( p1 C& `# s% N* U% C% V+ z
9 \" f# A& i$ o, b r
format(‘%*.*f’,[8,2,123.456]); //等价于format(‘%*8.2f’,[123.456])
: g* S. B) O1 t6 r: Q
format(‘%d %d %0:d %d’[10,20]);
# u7 J. J" G" G" N* d: f" Z
- F$ D; X& S4 M) W$ W
/ d+ t3 E+ U. K7 d0 Z8 [
h4 |0 a3 k, n U
播放一个wav文件
: W! l$ P5 O. [
use mmsystem;
/ P3 m- `0 G$ X
SndPlaySound(‘hello.wav’,SND_FILENAME or SND_SYNC)
. J, A2 w( u+ t4 j1 D% `
* h# X. q* W% T) y% v' K' l9 W
使你的form适应不同的显示分辨率
4 l4 F) z T# \4 P: ?8 v/ A, b
假设你在800*600的分辨率下设计的form,第一步:
1 @' q% f# ^% J# o" d
inplementation
% {8 l5 n3 [$ B
const
4 R' j! Z2 o R5 I1 \" L J
ScreenWidth: LongInt = 800; {I designed my form in 800×600 mode.}
6 p* X( ^" w5 L: l2 E3 o
ScreenHeight: LongInt = 600;
1 B( _' {% Y+ k/ b \' i' ?# y
7 O) w* `$ @# l8 O: Q. D, l
{$R *.DFM}
K/ C" r; p D1 m+ N7 [% ?! e: t
0 C! f4 }8 Z( `& y
procedure TForm1.FormCreate(Sender: TObject);
7 r3 a6 T3 A* @: i+ I. B
begin
5 B: ]" u7 B7 w! s3 P2 S* E
scaled := true;
& Y8 x" _$ ^5 N5 E( b
if (screen.width <> ScreenWidth) then
$ u1 @% F4 Z" J1 I1 y
begin
" l9 ]0 q k9 R/ r
height := longint(height) * longint(screen.height) div ScreenHeight;
. U1 m. B# O8 i
width := longint(width) * longint(screen.width) div ScreenWidth;
, h& Q- W/ }4 O$ y
scaleBy(screen.width, ScreenWidth);
; z/ L6 v4 |8 b$ f, O* c+ ~( s; q" |
end;
% E9 O0 h. R5 p" F- o9 a
end;
( M+ s+ q4 @! E% Z5 K, U& B6 X1 Z
- C% w3 g: c) ^/ ^/ _$ n; v0 r
下一步,要让每个子控制的字体改变到合适的大小:
. N& d7 b# A+ m& L0 y9 E5 S0 \$ l
type
) `- ]; ^/ I, g. c3 U
TFooClass = class(TControl); { needed to get at protected }
0 q: D& o3 c" q0 Y% O. H3 e
{ font property }
* D, d: V: t5 i, m& c
9 l& I, `7 C2 x ~/ p
var
& ~: ]0 u: o3 Y) t# }; P+ e
i: integer;
~7 U) x- y5 Y9 D/ S) b
begin
1 K {! l4 Y: B- g# [+ l. j
for i := ControlCount – 1 downto 0 do
) z F3 j* W4 ?! I7 I4 r
TFooClass(Controls
).Font.Size :=
$ R. M9 ~: Z2 P# G( |
(NewFormWidth div OldFormWidth) *
! N. {) }5 i! }# W
TFooClass(Controls
).Font.Size;
3 v$ ~9 e. ~ H l l
end;
) P( c2 v6 c0 m8 N! B
1 @- O5 d- t; P0 E) W
用raise引发一个错误处理例程
2 m0 |1 Z |$ f7 H" J, s
示例:先给出下面的定义
|- w6 _* t" m5 Y3 j
type EPasswordInvalid=class(Exception);
* u0 e( K; @; v! a `8 h7 n+ i
这样你就可以随时引发一个”password invalid”的例外:
" o" F! p6 S& K* Z& F
if Password<>CorrectPassword then
7 G' w' j3 r7 l6 G& I
raise EPasswordInvalid.Create(‘Increect Password entered’);
, N2 a: B* v4 _1 r7 |
运行后,出现信息框
2 V+ y1 d: w% @* G3 k: \
Project Project1.exe raise exception class EPasswordInvalid
+ t- q. g- ~8 l* B7 |5 M g$ W
with message ‘Incorrect Password entered’. Process stopped.
: V' x. o( ?8 m
Use step or run to continue.
( ~6 q: `* G: A
再按Run按钮,出现一个信息框:
" L" a9 A( d) f/ V. P; c
Incorrect Password entered.
# J3 B" f$ c; K0 }- q
& `( |& ^, I4 {; F& a
/ x& P0 u2 E8 ~# h+ c1 l
从DEMO例程中学到的若干小技巧
0 N6 z' h4 {- `2 q6 D- c
在demo\internet\http\webbrows\main.pas中,
0 {$ a% p! [( ~# A' O7 x& Z
procedure TForm1.DocumentSourceClick(Sender:Tobject);
8 q! o4 x/ C% [. H
begin
- Z$ {/ w& E6 A
with DocSourceForm do
" }2 E/ d z! C, f# V# t
begin
3 n$ o# I. X. H8 L% G
show; // 显示HTML源码的FORM
" ?! q3 N1 O6 S1 @
Memo1.lines.clear; // 清空memo1中内容
. ]6 l4 O! L1 O, c
Memo1.lines.add(HTML1.SourceText); // 植入源码
9 [2 X4 J; [( \
Memo1.SelStart:=0 // ***
) G+ y0 C9 u( e) @1 |
SendMessage(Memo1.Handle, // Memo1的窗口句柄
9 n9 j2 K9 l% @) S
EM_ScrollCaret //将Edit Control中的caret光标滚动到视野中
6 P% I0 w W' M# b* V+ K" y
0,0 //这两个参数暂不使用
( L) ]& i) l5 ]/ [
end;
1 h% x0 [1 b# K0 Y* m( x
end;
i8 n4 l- ^, U2 Q! m0 K
(此SendMessage系一WinAPI调用,给一个或一组窗口发送消息,直到
1 a" P( f3 P7 F" {" K* l
相应窗口处理此消息后才有返回值。相似的另一函数为PostMessage,
% i$ ~7 N, _+ e
它将消息放入消息队列中后立即返回。)
2 U4 \: G# [& _7 l
*** 清空当前选择并将光标移动到指定字符(0代表第一个字符)。如同时
6 l$ C" h# y2 x5 _( H2 D9 ]" x
设memo1.sellength为一非0值,可选择一段文本。
; p1 [- F/ F5 }/ @# J! H
: O: v: _" F5 Q; j9 L. T; y" ~# @
5 B6 c+ M0 a8 o5 G6 t) F9 s4 A
奇怪的I/O error — 我在开发过程中发现下面这两条语句
4 _/ `/ P5 D# H( J
assignfile(fDesc,CDDatadir+describefile);
3 Q. {1 }: ?1 S; @: z3 q- {
reset(fDesc);
G. D4 E7 g/ Z$ {4 A
每当我第一次运行到这里时,总会出现 I/O Error 183 的错误.
1 w' q) U8 e& f8 P
最后我想这也有可能是没有清除 ioresult 的原因.在两句之间加入
. o% o6 G8 F3 N6 d% }5 F9 e
if ioresult<>0
/ {* ]; @! D _1 z
then;
! J9 v5 Y* Q4 y) x! i3 b: o
oooook! 可以了.
; b+ P/ l5 B, g; p. ?/ x C
- g& ?( w% j( @) O3 \! j
" k* W# V' k8 j: @3 Y
值得注意的I/O error
1 q# v4 U3 N; D( U
AssignFile(F, fname);
' S" W [$ u4 g% l8 O- j2 P
Rewrite(F);
) {) ^$ j4 H- i$ l
当文件 F 经 Reset(F)打开的情况下, Rewrite(F)会引发一个异常: I/O error 32
5 B- X! ?5 D& Q. W
反之,经 Rewrite(F)打开, Reset(F)也会引发同一个异常.
* Y& y( ~: N5 s% G3 d
Reset(F)两次,closefile(F),再Rewrite(F),或反之,也会引发同样异常.
# ]2 i$ u B# q7 }: d) Y$ r
+ @; ~+ V* C: Q( m; h @
9 i& i& u/ T( m7 m3 }' _, O
' b/ s2 S; _ R: V
string和pchar的相互转换:
3 R8 U+ d: J4 S% X# J% e8 K
string –> pchar: pchar(s
0 Y [9 [5 x, S. c, C# i2 ~ f
tr:string);
0 K/ N9 U: e8 {
pchar –> string: strpas(p:pchar);
! l9 G+ b! }2 J' M( Y' P
" c2 A' g8 ?, V, [) m4 {; V
* F4 V ?- [; W9 j: H, d; [
7 D: k X% V5 k8 N7 Q) B
在Delphi代码中定义数据库
6 _) @0 o P1 I- ]2 T8 J: V- z) i
procedure tform1.create_tbl;
" s( N4 W# }+ {: [! s) P* a1 D5 R7 A
var tbl:ttable;
# _, q8 T0 X5 p; \7 g
begin
# ^- u; T# F; H6 q( v/ }5 G
tbl:=ttable.create(self); // 如没有声明中的”tform1.”,Delphi不认这个self
2 F% v4 ], W- h. J
with tbl do
# Y4 ]& b7 m, B
begin
9 [2 g3 J. F3 l" w
datebasename:=;dbdemos’;
' G* w( H$ M3 v+ A
tablename:=’my_tbl’;
1 l% s9 @6 Z( |) ]' Q! a& E
with fielddefs do
$ X% D8 W% C, K: N/ C0 G
begin
$ Q7 w; {9 R* z3 ~
clear;
2 p- w% L% z% W
add(‘No’,ftInteger,0,false);
) g4 {6 i- O9 K7 p
add(‘Name’,ftString,0,false);
! J; r( M {* {
…
. y' w6 Y0 W1 ^+ y8 s, Q4 M. _4 s
end;
. c3 Y" }- u+ R/ u+ N# ^! C
with indexdefs do
/ ]/ P! g/ z+ h; X Z
begin
9 S6 s+ K4 j' n. i4 [( ~
clear;
- ~- H- y, i0 m2 ~* g) e
add(‘primary’,'no’,[ixPrimary,ixUnique]);
* u$ `+ m3 M: t+ m. l# `% B
…
# u2 ~& ?/ z" \6 ^
end;
+ R2 Z+ ^$ F& t6 R* r8 F2 G- }; Y
CreateTable;
, g' Y9 ]: a$ b6 {9 j
end;
! q* k, _9 |/ J$ {! M" P- t- p
end;
4 j4 O: Y, r& W1 L6 k" t! _
' B9 u: y0 S& p
9 ]% k3 Y6 ?8 a, d2 ^. |& g
string、TStrings、pchar的相互转换(这里是我的个人经验)
0 r) _# |- s8 P
假设有如下定义:
9 q4 x5 N' `) M7 \9 Q* r- n/ g' V3 p+ }
var
8 Z0 m1 F9 w: W+ h2 G! T: z
p:pchar;
' q8 M2 g7 m+ |' S& S9 F' H" W
s:string;
4 T6 D* A/ s; t1 a
ss:tstrings;
7 T4 E! t4 g8 x" U# W
begin
5 O. }* M w) N+ [
ss:=tstringlist.create; // 开始时一定不要忘记创建ss
8 F$ n. f. J) Y, H2 L. U# S4 x
ss.text:=s; // string –> tstrings
" V0 g2 _2 @, ~$ H- M5 Y
s:=ss.text; // tstrings –> string
2 m$ p$ f% R1 ?; D Q c! E" I! U
p:=pchar(s); // string –> pchar
5 k3 A; x( Z5 e* k7 e
s:=p; // pchar –> string
( i/ D0 z2 g5 [
showmessage(s); // 合法语句
9 K: [! ~! B9 {, ]8 @6 a* |
showmessage(p); // 合法语句
1 P/ v# R6 A3 o
… …
/ v4 d/ i) \ |
ss.free; // 最后还要记着释放ss占用的资源
# I t8 j# O$ S, @3 L
end;
F3 D' F* t- Z
% B/ Z' F& b9 W
2 z8 _8 f4 N' H' T- i' s# L
) C5 _& W! d5 o, R0 T) ?% w
在设计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