Delphi编程技巧总汇--------[持续更新] 本帖最后由 s11ss 于 2014-02-06 13:54:50 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 加上开关{$O-},取消代码优化,这样被优化的语句就可以下断点了,利于调试。{$O-}procedure TForm1.FormCreate(Sender: TObject);var I: Integer;begin I:=1;//加上开关后,此处就可以下断点了end;{$O+} 从TInterfacedObject派生的类,可以利用接口会自动释放的特性,来省掉显示调用Free。implementation{$R *.dfm}type TMyObject = class(TInterfacedObject) private FMsg: string; procedure ShowMsg; public destructor Destroy; override; end;{ TMyObject }destructor TMyObject.Destroy;begin ShowMessage('Free了'); inherited;end;procedure TMyObject.ShowMsg;begin ShowMessage(FMsg)end;procedure TForm1.FormCreate(Sender: TObject);var I: IInterface; O: TMyObject;begin O := TMyObject.Create; I := O; O.FMsg := 'abc'; O.ShowMsg; //此处并没有显示调用O.Free,但由于I自动释放,就隐式调用了O.Free!end;end. 1、6楼的不错,LS的就不太算技巧了,都是见于教科书中的知识点。期待LZ继续爆料,跟踪学习中~~ LZ多爆点编译指令和inc的技巧来学习学习嘛 不知道,我在delphi7下测试的! inc的话,个人认为,就是可以把一些关键的地方独立到一个文件。特别是代码比较多的单元文件,把一些可能会改到的地方独立到一个文件,就比较好使!比如Unit1.pasprocedure TForm1.FormCreate(Sender: TObject);const{$I str.inc}begin ShowMessage(MSG);end;str.incMSG = 'abc'; 这个好,继续关注~用法俺了解,想了解一些技巧和需要注意的地方另外一些第三方组件中基本都会使用inc,好像还会有交叉的,有时看源码看得自己有点乱 貌似他们的inc里面都是$IFDEF和$DEFINE之类的 设置标题可以用[color=#FF0000]SetTextBuf('abc')或Text:='abc'[/color].procedure TForm1.FormCreate(Sender: TObject);begin SetTextBuf('abc'); ShowMessage(Text); Text := 'def'; ShowMessage(Caption)end; 用delphi的人好少了,招的人也少 新建一个控制台工程,然后把{$APPTYPE CONSOLE}注释掉,或者换成{$APPTYPE GUI},这样就变成不带任何窗口的工程了。program Project1;//{$APPTYPE CONSOLE}uses SysUtils, Dialogs;begin ShowMessage('abc')end. 新建一个普通工程,然后在工程源文件里,在program一句的下一行加上{$APPTYPE CONSOLE},这样就可以在程序中使用Write之类的语句在控制台输出调试信息了。program Project2;{$APPTYPE CONSOLE}uses Forms, Unit1 in 'Unit1.pas' {Form1};{$R *.res}begin Write('start!'); Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run;end. 单元文件最后一行“end.”前可以加上begin或asm,然后中间可以加上代码,这段代码在单元初始化的时候执行。implementation{$R *.dfm}begin//这里也可以是asm MessageBeep(MB_OK)end. procedure也可以有返回值:procedure Add(a,b:Integer);asm//eax存储a,edx存储b,相加的结果又保存到eax add eax,edxend;procedure TForm1.FormCreate(Sender: TObject);type TAdd=function(a,b:Integer): Integer;var P: Pointer; I: Integer;begin P := @Add; I := TAdd(P)(1,2); ShowMessageFmt('%d', [I])end; {$R 'zz.res' 'zz.rc'}这样就能在工程里包含zz.rc脚本,并自动build出zz.res! 通过指针,可以对只读属性进行写操作。type TObj = class private FNumber: Integer; public property Number: Integer read FNumber;//只读属性,不可写 end;procedure TForm1.FormCreate(Sender: TObject);var O: TObj;begin O := TObj.Create; PInteger(@O.Number)^ := 2;//通过指针的方式访问 ShowMessageFmt('%d', [O.Number]); O.Free;end; 通过内嵌汇编,可以对只写属性进行读操作。type TObj = class private FNumber: Integer; public property Number: Integer write FNumber;//只写属性,不可读 end;procedure TForm1.FormCreate(Sender: TObject);var O: TObj; I: Integer;begin O := TObj.Create; O.Number := 2;//对此句下断点,看cpu,可看到O.Number的地址为eax+4 asm push edx mov edx, [eax+4] mov I, edx pop edx end; ShowMessageFmt('%d', [I]); O.Free;end; good good study,day day up 局部常量字符串 or 全局常量字符串?procedure a;const STR = 'abc';begin Form1.Tag := Integer(PChar(STR));end;procedure TForm1.FormCreate(Sender: TObject);begin a; ShowMessage(PChar(Form1.Tag))end; 把.dpr文件的第一行program Project1;注释掉之后,再把{$R *.res}改为{$R Project1.res}或干脆也注释掉,照样可以Build成功。//program Project1;uses Forms, Unit1 in 'Unit1.pas' {Form1};//{$R *.res}{$R Project1.res}begin Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run;end.再来另一个省略program的例子,运行包含以下代码的批处理文件,则build出来a.exe。@more /e +1 "%~f0">a.dpr&dcc32 a&goto :eofuses Windows;begin MessageBeep(MB_OK)end.[size=9px]ps:本人最近有要事在身,最近几天不会更新了![/size] 得到结构中元素的偏移值type PTestStru = ^TTestStru; TTestStru = record ID : integer; B : Boolean; Name : String; Time : TSystemTime; Closed : Boolean; Prop : DWORD; end;var iOffset : integer;begin //得到Closed在TTestStru结构中的偏移 iOffset := Integer(@PTestStru(NIL).Closed); //该方法只能运行时得到,不能用这个表达式定义常量.囧end; 怎样在Delphi里插入版权符号© 不加控件能显示信息吗? 谁帮忙看看, 基础问题 各位帮忙看看为什么delphi在调试时有一个模块怎么也跟踪不进去 delphibbs.com为什么关闭了啊? 有关query的数据显示问题 如何使form透明 50分的简单问题 如何列举一个目录下的所有文件(包括子目录)? 请问如何动态的添加ACCESS数据库到SQL中 这种情况是不是要用线程,SPCOMM如何在线程中使用? 关于ComboBox和DBLookupComboBox多步操作产生错误的问题
procedure TForm1.FormCreate(Sender: TObject);
var
I: Integer;
begin
I:=1;//加上开关后,此处就可以下断点了
end;
{$O+}
TMyObject = class(TInterfacedObject)
private
FMsg: string;
procedure ShowMsg;
public
destructor Destroy; override;
end;{ TMyObject }destructor TMyObject.Destroy;
begin
ShowMessage('Free了');
inherited;
end;procedure TMyObject.ShowMsg;
begin
ShowMessage(FMsg)
end;procedure TForm1.FormCreate(Sender: TObject);
var
I: IInterface;
O: TMyObject;
begin
O := TMyObject.Create;
I := O; O.FMsg := 'abc';
O.ShowMsg;
//此处并没有显示调用O.Free,但由于I自动释放,就隐式调用了O.Free!
end;end.
期待LZ继续爆料,跟踪学习中~~
Unit1.pas
procedure TForm1.FormCreate(Sender: TObject);
const
{$I str.inc}
begin
ShowMessage(MSG);
end;str.inc
MSG = 'abc';
另外一些第三方组件中基本都会使用inc,好像还会有交叉的,有时看源码看得自己有点乱
begin
SetTextBuf('abc');
ShowMessage(Text);
Text := 'def';
ShowMessage(Caption)
end;
program Project1;//{$APPTYPE CONSOLE}uses
SysUtils,
Dialogs;begin
ShowMessage('abc')
end. 新建一个普通工程,然后在工程源文件里,在program一句的下一行加上{$APPTYPE CONSOLE},这样就可以在程序中使用Write之类的语句在控制台输出调试信息了。
program Project2;{$APPTYPE CONSOLE}uses
Forms,
Unit1 in 'Unit1.pas' {Form1};{$R *.res}begin
Write('start!');
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
MessageBeep(MB_OK)
end.
asm//eax存储a,edx存储b,相加的结果又保存到eax
add eax,edx
end;procedure TForm1.FormCreate(Sender: TObject);
type
TAdd=function(a,b:Integer): Integer;
var
P: Pointer;
I: Integer;
begin
P := @Add;
I := TAdd(P)(1,2); ShowMessageFmt('%d', [I])
end;
这样就能在工程里包含zz.rc脚本,并自动build出zz.res!
TObj = class
private
FNumber: Integer;
public
property Number: Integer read FNumber;//只读属性,不可写
end;procedure TForm1.FormCreate(Sender: TObject);
var
O: TObj;
begin
O := TObj.Create;
PInteger(@O.Number)^ := 2;//通过指针的方式访问
ShowMessageFmt('%d', [O.Number]);
O.Free;
end;
TObj = class
private
FNumber: Integer;
public
property Number: Integer write FNumber;//只写属性,不可读
end;procedure TForm1.FormCreate(Sender: TObject);
var
O: TObj;
I: Integer;
begin
O := TObj.Create;
O.Number := 2;//对此句下断点,看cpu,可看到O.Number的地址为eax+4
asm
push edx
mov edx, [eax+4]
mov I, edx
pop edx
end;
ShowMessageFmt('%d', [I]);
O.Free;
end;
const
STR = 'abc';
begin
Form1.Tag := Integer(PChar(STR));
end;procedure TForm1.FormCreate(Sender: TObject);
begin
a;
ShowMessage(PChar(Form1.Tag))
end;
//program Project1;uses
Forms,
Unit1 in 'Unit1.pas' {Form1};//{$R *.res}
{$R Project1.res}begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
再来另一个省略program的例子,运行包含以下代码的批处理文件,则build出来a.exe。
@more /e +1 "%~f0">a.dpr&dcc32 a&goto :eof
uses Windows;
begin
MessageBeep(MB_OK)
end.[size=9px]ps:本人最近有要事在身,最近几天不会更新了![/size]
PTestStru = ^TTestStru;
TTestStru = record
ID : integer;
B : Boolean;
Name : String;
Time : TSystemTime;
Closed : Boolean;
Prop : DWORD;
end;
var
iOffset : integer;
begin
//得到Closed在TTestStru结构中的偏移
iOffset := Integer(@PTestStru(NIL).Closed);
//该方法只能运行时得到,不能用这个表达式定义常量.囧
end;