打印

delphi 技巧合輯

delphi 技巧合輯

INI文件的操作要点4 Y% g  ~, O0 h" m3 R3 T
(1)在interface关键字后的uses子句中加入
. {0 T; S# s/ f% luses …,inifiles;: E3 ]$ }+ L: Y. `
(2)设置变量:var inifile:=TIniFile;  a1 J; S5 v* S' ^% m+ s! ]2 N
(3)使用前,一定要先做:8 G' V$ B' i; @5 U
inifile:=TIniFile.Create(inifilename);: f6 z- F  }$ b0 q
我在这里绕了个弯子,写成7 |/ z8 i% Y* s, d9 [
inifile.Create(inifilename);
, {/ \) d- R; X8 K( c% W5 |( M, R8 a) @" v9 G1 E6 z$ s
TShiftState用来检测CTRL,ALT,Shift,以及鼠标按键的状态,
: _4 P+ l+ `- d6 F4 Z4 ]常常用在键盘或鼠标的事件处理程序之中。4 g( J) d  W2 l2 v" Y' Y  x! Z
0 h: c$ A5 O# h5 p  c
DCU文件(编译的库单元)的重用& |& @; P9 [7 i6 J0 n
(1)在interface里的uses子句中引用。如Windows,Dialogs,1 ?4 v! X2 Y: @
等等,要求被引用的DCU一定要放在Delphi 3\Lib子目录中。0 K) @! g/ M) R9 K3 R: c+ E- t/ P
(2)在implementation里的uses子句中引用。如果是自行编写的+ Z+ B- S7 w( W4 s1 G) X
DCU文件,应采用这一方式,并将被引用的DCU文件放入当前
4 g1 p: ^7 ~3 Y工程所在的子目录中。: ?# ^% @5 N7 X% _5 b% M
executefile函数(在FmxUtils.DCU中定义)不能用在FormCreate
3 m5 o: }4 }  |事件中。真奇怪……/ `. w" Y; ]/ V# ]0 R6 J

5 T* M/ n2 @- n' U. l1 Q9 g% l) `内置的版本号控制功能- h2 p! ]. z! Y& Q& M1 g
在Project Options中的VersionInfo项里,有版本信息的定制,
9 c* c- T) E+ k& W3 s5 k包括一个有趣的版本号自动增加功能(Auto-increment build8 d" \, J) x  j1 z8 N
number),即每Build一次,版本号中的Build Number加1。选中% D( c9 Y, [2 j$ a9 C: |
Include version information in project,编译,用资源管
; c. K6 L: O& S1 F理器里找到生成的.exe文件,点右键,查看“属性”一项,就
1 F! U; C: k% w; @会看到在属性中多了一页“版本”,里面就是你刚才输入的各
$ U- N/ C- x6 ?* c/ J2 x项内容。* q2 j  e# r  @2 b) Q
3 q( Y/ [$ ?8 h, J6 I: \  b7 D0 N

  L0 h" o( I3 H. u( k& V' d* {3 k. G定制Speedbar6 q1 w3 |9 F% A2 |3 C3 K
右键点击左上角的加速键条(speedbar),选中Properties,  k8 ~$ g: y: \! t; o
在列表框中找到你想要加入speedbar的命令按钮,将它拖到
9 V$ K; X5 y5 O' G. xspeedbar上的合适位置即可。如果speedbar上没有多余的空间' W6 G& P: _( v; o( C
来容纳新的按钮,可把鼠标在speedbar右框处变为双向箭头的
+ N8 J$ A, B$ E- A! ?; {: }* d5 {# L7 ~形状,向右拖动一段距离,就可腾出空间。如想删除speedbar+ M! w2 t* X0 v8 G+ \* N- B
上的某个按钮,可简单地把它拖出speedbar的范围,就能删除。
" V; `. ?1 Y8 o& C
2 w1 [: F+ ~( j
7 e7 _0 i$ c1 ^' t) v+ }计算出的字段% A$ s) Z3 x' ^2 i  Q6 g$ p
在写一个程序时,我要在DBGrid中显示出一个memo的部分信息,当我把那个
. v# \& x+ z2 ]7 ~. hmemo字段放进去后,运行时只能显示出“(memo)”字样。从书上找到计算字
- c+ s: S& O8 I7 }5 r3 g段的用法后,我在TTable中增加一个计算字段MemoHeader,宽度为40,在此
9 _) d+ t2 n* [1 x9 YTTable的OnCalcFields事件中输入:
% L. V6 M- l7 w' I/ Nwith MyTable do7 b1 V9 M4 b7 e, c' L
FieldByName(‘memoheader’).asstring:=FieldByName(‘memo’).asstring;
  ?" D! ^3 ~9 Z- p7 ?  B) l在DBGrid中放入MemoHeader,运行,OK!8 x' R4 A" \$ o) o  W- k0 V( w
7 T( g9 x  ?! u7 ^! `! `. \- k
5 K1 A8 I* Y8 F: X
字段编辑器* l  ]9 P; t' N8 Q- H8 b+ S
解决了上面的问题后,我继续学习字段编辑器的作用。原来,DELPHI通过字! i) M  \6 \6 N& P: c$ [# G& m
段编辑器,近乎完美地实现了数据库的字段级的控制,这包括:+ D# B9 W3 O- p5 [
1)字段在DBGrid中标题、宽度、能否可见;
6 o& L" i; w* P' C. s/ v, j% G$ u2)字段的显示格式和编辑时输入的过滤条件;
* ~0 _. y# H) i2 f# h! q: M3)字段是否只读;
+ U0 ^3 H( [! o7 N! F- J4)字段的类型:数据字段/计算字段/查询字段/内部计算字段;) Q$ i" X0 ]  ]2 X
5)字段的显示/赋值/修改等事件的定制。! Y( |$ X5 ]! `' z  x, h- G
) v' ~  A8 l" r* C  S7 Y1 m
' p. y& q# I9 G( C
设计Form时的快捷键& ]8 Q7 b; Q* l/ ^3 m1 \, }
Del 删除所选组件
! Z( a# Z9 h1 g* SEsc 选择当前组件的容器(通常是Panel,Group或Form)7 c( }; d0 _$ O& ]% C% ^6 k5 S8 [
F11 在Form或Unit和对象检查器之间切换
& [2 B* @+ h, x, [. `; V* P# iF12 在Form和代码编辑器间切换! z' f, G) J% k' b* a, _) s
Ctrl-F12 显示“查看Unit”对话框
7 U7 K* S- z2 p9 ?+ ?4 CShift-F12 显示“查看Form”对话框7 @5 H9 U( ^5 u: b$ }4 [
TAB 下一个组件2 }4 \7 D3 Q+ h. x4 s' g  D
Shift-TAB 上一个组件
0 m7 j: v: t, z7 x! \" e方向键 选中此方向上最近的组件2 ]) C* `% d0 Q2 a8 w
Ctrl-方向键 将所选组件移动一个点; |: ^' V  X9 y7 q+ c
Shift-方向键 将所选组件改变一个点的大小  r0 u- f$ F: ^& M5 l
Ctrl-Shift-方向键 将所选组件移动一个格
- s- |9 c; _# o3 VShift-click 按住Shift键再用鼠标点击组件,可以选择多个组件。
* `6 z$ {: {6 N, \& ?) s& x1 m–= 下面这条是我摸索出来的 =–, Q7 I2 N3 H' J! K
Ctrl-drag 按住Ctrl键在一个容器组件(如Panel,QReport,Groupbox等)6 r- U" k  J. L( l% }! N
里拖动鼠标,可强制选择鼠标拖过的矩形框中的所有属于此容2 E! @( z1 {( o5 U0 B! L1 I
器的可视组件但不包括该容器组件。5 a6 \: N; I) o2 x( s4 C6 R
# b  v# v4 J' x% i
& [% X$ e3 r. H/ c9 z
使用QReport的若干经验$ T5 l# G) g3 W
1)QuickRep1.DataSet:=query1& g/ ?5 X' o( {- j7 [* {
不然无输出结果
, z( C. N9 x' C  c; W3 A; T4 ^2)从qrpt2man.doc中查知,格式化输出结果的方法是:2 }$ a4 _# X6 ]5 ~
在QRDBText.Mask中设为.00;0,将使输出带两位小数。) w3 I8 D1 }; ?! f; q, x
3)设置Group时,先加入一个QGroup,再加入一个QRBand,将QGroup的
6 r$ a3 `# {4 c2 R8 N- j( ?FooterBand设为刚才的QRBand,就可将其联系起来。! c" x  L5 Z# l
4)在Group中打印的合计数,其ResetAfterPrint设为True,可实现分组合2 Z1 F2 M2 _: N9 h2 E' g

" }, Z4 [( e4 r) r9 iformat(‘%*.*f’,[8,2,123.456]); //等价于format(‘%*8.2f’,[123.456])& o: K. T, K/ S* D
format(‘%d %d %0:d %d’[10,20]);
4 O& |9 I: v$ }$ c! w0 ]" j9 l/ v6 N5 _3 ^& v: v* h* C  M/ w
6 b8 h$ U" m* R9 l! i
; R# ~5 X5 p6 r, f
播放一个wav文件8 _' Q- i1 p% W0 V& x
use mmsystem;% j7 |9 v0 e4 Q0 j1 [6 T, G* v$ }9 q
SndPlaySound(‘hello.wav’,SND_FILENAME or SND_SYNC)
2 ?" `; {  ~$ X  R2 x) E+ |" Q8 C8 A+ z' {2 \
使你的form适应不同的显示分辨率5 u' Y1 @' p$ A) k
假设你在800*600的分辨率下设计的form,第一步:
0 ]" m1 e5 G* ?- L1 f! oinplementation2 f1 `3 L5 i& X  [9 j2 ~
const
) H% [/ ]  s4 i" Y; a) CScreenWidth: LongInt = 800; {I designed my form in 800×600 mode.}2 ~8 f, u1 O3 U8 b6 u/ r8 k
ScreenHeight: LongInt = 600;
2 e6 O0 @" S: m0 l, a1 @0 x/ n7 j4 @  b5 _
{$R *.DFM}7 ]4 t, h! x3 y/ R# ?. k4 s- y

: D  j6 J" U1 F" Fprocedure TForm1.FormCreate(Sender: TObject);/ K) @4 a3 @! E9 q/ O
begin
- e) A: O8 A8 m4 C& B2 `8 dscaled := true;, X% j- @- G8 g. q* b3 B% R
if (screen.width <> ScreenWidth) then
8 I. f# }6 x$ E) ?0 q) J7 mbegin
( e- I3 T! i. B9 v4 ^3 n! Uheight := longint(height) * longint(screen.height) div ScreenHeight;( Q$ v0 A4 p0 ?$ F' m
width := longint(width) * longint(screen.width) div ScreenWidth;
+ |1 w$ I! l7 p" g; [- DscaleBy(screen.width, ScreenWidth);
5 i( O# V& j) A4 S/ Z- Y0 nend;) D+ y: X  p& E7 P- }
end;
" ?1 W, o0 E1 W3 c; ^' |" n+ _
0 \, a3 j' A& r& t/ c下一步,要让每个子控制的字体改变到合适的大小:* @2 `- Y' N! C% y1 d
type7 `2 _9 a, J8 T' u
TFooClass = class(TControl); { needed to get at protected }
- f+ V* b/ m" g6 e( ]* ~) F1 u{ font property }! c; B; }( |2 [& [
1 ~# M, F9 I& y5 @
var
8 A7 j- q2 v5 R& Zi: integer;
# l6 S& U$ N1 hbegin
: ?/ X+ Z! }* sfor i := ControlCount – 1 downto 0 do/ @7 M% C( N1 E
TFooClass(Controls).Font.Size :=
$ M1 h* p" m+ Y(NewFormWidth div OldFormWidth) *+ i8 o; s0 X" a+ |' [
TFooClass(Controls).Font.Size;
7 |) R' a8 b6 V; o. U0 Gend;
2 s8 z, w# k* L0 J* @5 g8 m! m
4 p. F' l' h7 R% R( {5 C用raise引发一个错误处理例程
  }, J) S5 g+ J# t% n示例:先给出下面的定义, {  O3 J1 ]2 e; U. U
type EPasswordInvalid=class(Exception);
2 G; _% x! u) `' |9 G4 {) N& ?这样你就可以随时引发一个”password invalid”的例外:  a5 A) _4 r+ J2 j
if Password<>CorrectPassword then* ?" e% ?/ }6 C7 U' P1 t
raise EPasswordInvalid.Create(‘Increect Password entered’);* @! n# @( @% A0 f, T
运行后,出现信息框
7 a" G; Z5 K6 l- m) b) i' P6 rProject Project1.exe raise exception class EPasswordInvalid+ A+ O: A/ o7 Q! T
with message ‘Incorrect Password entered’. Process stopped.& Z+ a1 _* @# m% p; _: r
Use step or run to continue.0 D) W2 E' r% S1 k4 e% q# ?
再按Run按钮,出现一个信息框:
) w8 b1 B$ P% T* L/ e, aIncorrect Password entered.
' E- j( ^$ H2 y, J8 R
' W0 k9 N; q/ |. A, v: w) j7 h' E+ t* }: n: k
从DEMO例程中学到的若干小技巧6 x2 M1 {& X1 i
在demo\internet\http\webbrows\main.pas中,. I+ Y" H+ i0 S
procedure TForm1.DocumentSourceClick(Sender:Tobject);0 ]+ u% J2 R* I, i0 s$ M) b# [
begin7 E' X  {' X& o; V0 C
with DocSourceForm do
: f  `+ D1 ^; C! B1 \  Obegin# `; |, ~  R/ d
show; // 显示HTML源码的FORM% i, g6 U, L& d2 s0 w
Memo1.lines.clear; // 清空memo1中内容0 c( g( g9 m- |- H+ a( W
Memo1.lines.add(HTML1.SourceText); // 植入源码
6 ~2 a9 F4 s8 H/ MMemo1.SelStart:=0 // ***3 X! @9 v* p0 O$ m) f4 z$ ]
SendMessage(Memo1.Handle, // Memo1的窗口句柄
5 B, ]; D# m5 B1 f% Q, D  Q4 a3 LEM_ScrollCaret //将Edit Control中的caret光标滚动到视野中% ]7 v" m( g2 ?) T/ U% i) b, D
0,0 //这两个参数暂不使用
' z  Q% q& x! x! N3 B7 Aend;
. l. R' D  f. }% }( Qend;1 q% v) v+ Q% i! M5 u
(此SendMessage系一WinAPI调用,给一个或一组窗口发送消息,直到0 V& g1 X  m+ J7 O8 x
相应窗口处理此消息后才有返回值。相似的另一函数为PostMessage,# U1 \8 M; h+ c4 R! J# u
它将消息放入消息队列中后立即返回。)8 R) @& g" d# r
*** 清空当前选择并将光标移动到指定字符(0代表第一个字符)。如同时- ~' m& {1 P& x  q6 [! i( S
设memo1.sellength为一非0值,可选择一段文本。
1 a0 ^' D$ x& v9 c  }5 V4 Q7 E. N2 _4 `
9 h8 l: T3 G0 q/ T& R& r$ A0 a4 X$ @
奇怪的I/O error — 我在开发过程中发现下面这两条语句+ V1 k5 N% `( A0 O  A
assignfile(fDesc,CDDatadir+describefile);, ^% c/ D( s+ z
reset(fDesc); 5 n" I/ q4 p  [- [
每当我第一次运行到这里时,总会出现 I/O Error 183 的错误.
. N" e0 N. r3 m) n. E( q8 H最后我想这也有可能是没有清除 ioresult 的原因.在两句之间加入5 {5 ^5 [9 s6 l; L3 T* u) U1 I/ i0 h
if ioresult<>07 c( B- W- c; w* P2 ~
then; ' }) X2 ^: @7 X$ @# q
oooook! 可以了.+ _0 j5 I( l. L* v
7 ^. O0 U/ F8 O2 J1 {
5 C- C7 B* [$ T* b7 x1 H
值得注意的I/O error
6 N1 q* ^/ Y# u) eAssignFile(F, fname);% X1 v0 {+ o+ N9 b% B" [" _
Rewrite(F);5 D: F7 d/ J* }2 a  m
当文件 F 经 Reset(F)打开的情况下, Rewrite(F)会引发一个异常: I/O error 32  b5 ]; U7 k0 j, k. @) u. u; R
反之,经 Rewrite(F)打开, Reset(F)也会引发同一个异常.
; M6 K7 ^: }! q9 hReset(F)两次,closefile(F),再Rewrite(F),或反之,也会引发同样异常.% w- N5 D0 }) e9 }1 [' V1 m
0 p6 }# T6 D  f, I. A' N

1 \5 Q7 n! g3 j* b
5 K6 c5 f' {. x/ bstring和pchar的相互转换:3 y  A% n( \, T1 |: K& X. [/ v
string –> pchar: pchar(s9 m. \$ @' H: x
tr:string);
4 D2 B) S. }7 |; n. ~2 ppchar –> string: strpas(p:pchar);
$ Q* }6 p/ W+ D9 `3 b  Q
& f+ Y3 Q0 l6 i2 H5 q- D! Y; E- T$ |* I8 R
5 u, O' Q, _4 N' b  i- Y. S
在Delphi代码中定义数据库8 {5 v! n( A$ e  ~! ~/ f
procedure tform1.create_tbl;: S0 d" o; {7 x' U: f
var tbl:ttable;4 @( q- d+ y: ?# |" L
begin
' X3 ]+ h& h0 k- i- z$ j0 n) n4 ktbl:=ttable.create(self); // 如没有声明中的”tform1.”,Delphi不认这个self
) S3 X) S& s4 \- g: q+ b- Vwith tbl do
- f# m. f, F+ Q# e7 r; Nbegin
9 y* U3 D" {5 I; L5 b1 Sdatebasename:=;dbdemos’;
9 C+ N1 |4 n0 J4 G- d3 m& wtablename:=’my_tbl’;
7 Y$ m8 u9 n# Zwith fielddefs do" U& z* q+ N  S: E( |6 e% G, p! c
begin- S! s$ ?( C" o* Q9 B
clear;
, \* j" o8 y+ U! X2 Aadd(‘No’,ftInteger,0,false);- _+ }  k' D& t' ?% J
add(‘Name’,ftString,0,false);% Z! h6 s9 {# H, [8 U7 E

: c8 d8 D% U2 x/ f6 d) i" xend;" ^+ Q8 ]2 `" O
with indexdefs do
& v& T( R" ^8 m0 d, a3 U/ pbegin
( Z4 [0 I* ^& \clear;3 Z* ]4 [! x) K! [
add(‘primary’,'no’,[ixPrimary,ixUnique]);5 k- J, q* [$ c: V: G2 N
8 ^( J" b+ P( G& P; Z4 F
end;( H+ x; T( o& H; `
CreateTable;
! ~) [! i8 ^+ ~" T0 ]: f3 Send;
' I* f+ |! c  ^* Oend;
, o) p. c2 [: X5 b! C) n7 ^6 I+ @% U9 N
$ H7 e# Z9 u' Y6 O
string、TStrings、pchar的相互转换(这里是我的个人经验)
, R" M$ m* e  f! h# ~假设有如下定义:5 e8 c) n4 m5 l2 }2 o: f: S" R. y
var! }! _' q6 g, n' U  }
p:pchar;( L. t& H3 ^& F: d
s:string;2 |6 x  x: a5 K5 u& V$ R( k$ |
ss:tstrings;
. r, h& K$ P) W3 m% j# Cbegin
+ |0 ]. n) [7 q6 H5 v* s9 Mss:=tstringlist.create; // 开始时一定不要忘记创建ss
, h* z7 r. B( A1 w" n/ Gss.text:=s; // string –> tstrings
" |1 E% P1 q5 a7 t0 X& z- Vs:=ss.text; // tstrings –> string
* x/ e1 L7 n1 Y1 K2 `" ~  n5 ip:=pchar(s); // string –> pchar/ ^# m) f2 g1 D- l* g
s:=p; // pchar –> string
' t/ {, ?0 f% H2 |) S& pshowmessage(s); // 合法语句
  }  H( G- R9 Q6 j2 N$ R, R; P/ ?showmessage(p); // 合法语句
0 F2 ]5 f  C9 a8 z… …, K0 ?; s9 o5 o" @' H* L0 s: K
ss.free; // 最后还要记着释放ss占用的资源6 U) U" u  m1 E, C3 r$ g  U
end;
5 y7 Z5 k. F/ b% U# `0 D: V- t8 g. S' K, M  a  L
) }  W' k: a6 E6 U) x$ H6 D
: {$ i$ f) I0 b) Y
在设计Menu时,常用的ShortCut可从下拉菜单中选取。但我发现可选的ShortCut有些不在列表中,如ESC,Ctrl-Shift-A等。我试着在ShortCut项的右边输入:ESC,竟然成功了。再试Ctrl-Shift-A,这回Delphi自动把它变为Shift-Ctrl-A

TOP

發新話題