1.
form.Free - 释放Form占用的所有资源。Free后,Form指针不能再使用,除非对Form重新赋值。
form.Hide - 隐藏Form。可以调用form.Show再一次显示。
form.close - 关闭Form,实际的结果取决于OnCloseQuery和OnClose,
如果OnCloseQuery的CanClose为False,不执行任何操作,如果为True,
进一步考察OnClose的Action的值:
caNone: 不执行任何操作
caHide: 隐藏窗口,同form.Hide
caFree: 释放Form占用的资源,同form.Free
caMinimize: Form最小化。
caFree最主要应用于MDI(多窗体)中,因为子窗体关闭时默认的动作是Hide,即隐藏,所以如果希望其释放所占用的资源时,就要设定关闭动作,也就是在OnClose事件中加一句Action:=caFree;
而Application.Terminate正如兄台所说的是关闭整个应用程序。
Create是从继承下来的方法,作用是给对象实例分配内存,语法为:
Formname:=Tformname.Create(Application); //参数Application表示此窗体的拥有者为Application。
Show是显示已经创建的窗口。语法为:
Formname.Show;
另外,告诉你:Show是无模式显示窗体,ShowModal是模式显示窗体。
创建form的顺序:
1.formcreate
2.formactive
3.formshow
==========================
2.
implementation分割代码的作用域。implementation防止外部引用单元涉及,任意单元如果访问该单元,只能引用该单元的interface节,对于implementation内声明但没有在interface中声明的函数或过程,其他引用该单元的单元都不能调用,同样,implementation内声明的变量,只能在该单元内被使用。
==========================
3.
FormDestroy 和 FormClose 有什么区别和联系?
(1).窗口的所有资源真正释放时调用 FormDestroy。当你关闭窗口时,VCL会调用FormClose,如果你在FormClose里写Action = caFree,那么VCL会继续调用FormDestroy;如果你将Action的值赋为其它任何值,VCL不会真正释放窗口资源(如果Action=caNone则什么事都不做,窗口保持原状),这时就不会调用 FormDestroy 。
(2).看这个程序:
将Form2改为available,然后在TForm2.FormClose 写 action := caFree; 在TForm2.FormDestroy 写 Form2 := nil;
然后这样使用Form2
if not Assigned(Form2) then
Form2 := TForm2.Create(Self);
Form2.Show;// Form2.ShowModal ;
第一种情况: 在FormClose中调用Form1.Close,则会调用到TForm.OnClose,其中又调用到了FormClose,所以就死递归了。一死递归,当然就栈溢出(Stack Overflow)。
第二种情况: 在FormClose调用Form1.Free,这样会调用TForm.Destroy,TForm.Destroy会判断自己是否与Application.MainForm相同,如果是,则会将Application.MainForm置为nil,TForm.Destroy然后触发FormDestroy,在FormDestroy中Form1被置成了nil。FormClose是由TForm.Close调用的,本来在FormClose之后,比较它自己是否Application.MainForm,如果是,就调用Application.Terminate结束应用程序。但这时虽然Self还是非nil,它只是Close方法中的一个隐藏变量,而Application.MainForm已经为nil,所以即使MainForm已经不存在了,但应用程序还是存在,只是看不见它了。Application本身也是一个窗口,但它的大小为0。所以只能用别的办法来关闭应用程序了(Ctrl+Alt+Del或在Delphi IDE中按Ctrl+F2)。
忠告:
尽量不要用Free方法来关闭窗体,尤其是主窗体,应该用Close方法。在FormCreate, FormShow, FormActivate, FormCloseQuery, FormClose, FormDestroy各事件中不要调用关闭、释放或销毁窗体的方法。
不要在方法或事件中直接引用Form1这类全局实例变量,如果别人用下列方法创建窗体,用Form1变量就没有作用了:
var
myFormVar: TForm1;
begin
myFormVar := TForm1.Create(Application);
myFormVar.Show;
// 用myFormVar用一些事
myFormVar.Close;
end;
因为这时候TForm1.FormClose中运行的其实是myFormVar而不是Form1。
在FormDestroy中可以改成这样:
if Self=Form1 then
Form1 := nil;
用这个方法来防止别的程序对Form1的无意错误引用。
==================================
4.
用ord函数可以取得字符的ASCII码的值
函数的参数是一个字符型 返回值是一个整型
若是要定义了一个string类型的变量
则要取这个变量中的字符ASCII码则要用数组的形式去访问
要取得字符串中的每个字符的ASCII码值应该这样写
var
Ansiretn,i:integer;
TestAnsi:string;
TestAnsi:='happy new year!';
For i:=0 To Length(TestAnsi) Do
ShowMessage(IntToStr(ord(TestAnsi[i])));
==============================
5.
tabcontrol从(Twincontrol)派生,只有一个页头在变,也就是说不管有多少页,都是一个twincontorl.
pagecontrolc从(Twincontrol)派生,而且每个tabsheet也是从twincontrol派生,也就是说有多少页就会生成多少个twincontrol对象。
上面主要是占用资源的区别。
另外从使用的方便程序上也有区别:如果每个页面的内容差不多的话用tabcontrol比较好。
如果每个页面的内容都不同用pagecontrol就比较方便,如果用tabcontrol的话控制每个页面的控件显示和隐藏以及控件位置,那会烦的不得了。
用TabControl也不一定要隐藏/显示,所有"页"都放到一独立的Panel中,由此就有Panel1,Panel2...等等,保证他们一样大,要显示某"页"时,只需要执行如Panel1.BringToFront一类的代码,不需要隐藏/显示
=============================
6.
假设你在800*600的分辨率下设计的form,第一步:
先设置Form.scale:=false;
然后
inplementation
const
ScreenWidth: LongInt = 800; {I designed my form in 800x600 mode.}
ScreenHeight: LongInt = 600;
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin
scaled := true;
if (screen.width <> ScreenWidth) then
begin
height := longint(height) * longint(screen.height) div ScreenHeight;
width := longint(width) * longint(screen.width) div ScreenWidth;
scaleBy(screen.width, ScreenWidth);
end;
end;
下一步,要让每个子控制的字体改变到合适的大小:
type
TFooClass = class(TControl); { needed to get at protected }
{ font property }
var
i: integer;
begin
for i := ControlCount - 1 downto 0 do
TFooClass(Controls[i]).Font.Size :=
(NewFormWidth div OldFormWidth) *
TFooClass(Controls[i]).Font.Size;
end;
====================================
7.
TClass1 = class
procedure func1; virtual;//virtual;这个是做什么的
end;
TClass2 = class(TClass1)
procedure func1; override;//override这个是做什么的
end;
virtual 的作用就是允许Tclass1的子类也可以有fun1的过程定义.
override 的作用就是告诉tclass1在子类(tclass2)中重新定义了fun1过程.
具体运行的时候,
a: tclass1 ;
b: tclass2 ;
a.fun1 调用 tclass1的 fun1
b.fun1 调用 tclass2的 fun2
1). virtual翻译过来就是虚方法,它自已可以实现也可以不实现,主要给后代一个可以override的方法。以便子类和父类用相同的函数下实现不同的功能。
2). override就是子类用相同的函数名来做和父类不同的事,但不覆盖父类方法,(还可以继承父类的方法)函数名相同而不带override字样的函数不同。
=============================
8.
我希望做个启动画面,但如果在formcreate里show另一个form,就会出错,为什么?
方法一:调用Showmodal函数来实现。Showmodal方式使一个窗口为激活窗口, 和Show相似,但它令窗口模式化。现举一例说明:
⒈开始一个新工程。给表格起名为MainForm,MainForm的单元起名为Main, 工程文件起名为Test。
⒉在MainForm中插入一个Button部件,将其Caption属性设为“关闭”,为该部件的OnClick事件创建一个过程,并在过程的begin和end之间插入Close语句。
⒊在应用程序添加一个表格,将这个表格起名为MoveForm,MoveForm 的单元起名为Move。
⒋为便于演示,在MoveForm中插入一个Label部件,设置其Caption 属性为“欢迎进入本系统”。
⒌建立两个表格之间的关联。在Unit Main的 implementation 中加入语句 uses move;
再为MainForm创建OnActivate事件。
procedure TMainForm.FormActivate(sender:TObject);
begin
MoveForm.Showmodal;
end;
⒍从Component模板的System类别中选择一个计时器(Timer),添加入 MoveForm 表格中,设置其Interval属性为3000(可根据需要自定义),再为其OnTimer事件添加语句
close;
加入一个Timer部件目的是用以控制闪现窗口显示时间。在此,MoveForm显示了3秒钟后关闭,主窗口MainForm自动被激活。
⒎编译、运行程序,就能得到延迟为3秒的闪现窗口。
方法二:你可通过修改工程文件中的源代码来实现,这在Delphi 的编程中是很少见的。现举一例具体说明:
前四步同方法一。
⒌选择View/Project Manager,击Option按钮,选择结果Project Option 对话底部的Forms页栏目。注意,MainForm和MoveForm是在Auto-create forms 列表中。选择MoveForm并击右键头按钮,把这个表格移到 Available forms 。 所有的
Delphi表格通过缺省方式自动在内存中建立, 因此它们要消耗内存和系统资源。在类似这里(程序运行时创建一个表格)的情况下, 你应该将表格从自动创建列表格中去掉。
⒍下一步修改工程的源代码。选择View/Project Source,修改begin和end之间的
语句如下:
程序清单Test.Dpr
program Test
uses
forms,
Main in ’MAIN.PAS’{MainForm},
Move in ’Move.PAS’{MoveForm}
{$R *.RES}
begin
MoveForm:=TMoveForm.Create(Application);{Create创建闪现窗口对象}
MoveForm.Show;
MoveForm.Update;
Application.CreateForm(TMainForm,MainForm);
MoveForm.Hide;
MoveForm.Free;{Free从内存中释放对象}
Application.Run;
end.
第一条语句创建了对象,该对象存在内存中,但还不能看见, 为了让它出现并更 新它的内容,调用对象的Show和Update成员函数:Show和Update。当闪现窗口使用完后,用Hide函数将它隐藏起来,然后用Free函数释放它所占据的内存。
=======================
9.
請問delphi自定議函數中的result是不是和其它語言的return一樣?不過在其它語言中遇到return便會結束函數.delphi中好像不是.請高手幫助提示下!!!
区别在与:
在c++中:
跳出一个函数用return (返回类型),在return的同时就跳出函数了, 无返回类型函数 直接return就跳出了。
但delphi不一样: result中保存的是返回值,
但真正跳出函数要用exit, exit在退出函数的同时把result值返回, 如果是procedure,就没有result
delphi中result一般做为函数的返回值,不做为退出条件,退出条件是楼上所说exit,abort等
给 result 赋值不会退出函数。
=======================
10.
TMainForm = class(TForm)
procedure mmiCloseAllClick(Sender: TObject);
public
procedure OpenTextFile(EditForm: TForm; Filename: string);
procedure OpenBMPFile(FileName: String);
procedure OpenRTFFile(RTFForm: TForm; FileName: string);
end;
这其中,mmiCloseAllClick和OpenTextFile这两个在不同地方声明的过程,使用有什么不同的地方?
它们在使用上没有什么不同,只不过前者是定义在protected里的,后者定义在public里,它们在使用上的不同体现在子类对它们的继承使用上和其它对等类对它们的引用上。
换句话讲:如果没有规定类函数/属性的类型(我是指Public、Private...) ,那么默认就是Protected。
=======================
11.
谁能告诉我继承和派生的区别是什么??"子类"和"派生类"的区别是什么???
父子关系只能是一代间的 , 而祖先和子孙是可以隔代的;
a派生b b派生c 也可以说是:b继承a c继承b
那么b是a的继承类,b,c是a的派生类,也是a的子类;
=======================
12.
对于对象来说,一个域就象一个变量。域可以是任何类型,包括类类型。(也就是说,域可以保存对象引用。)域通常是私有的。
要定义类的域成员,只需简单地象声明变量那样声明域。所有的域声明必需出现在任何属性或方法声明之前。例如,下面的声明创建了一个叫做TNumber的类,该类中除继承自TObject的方法之外,仅有一个叫做Int的整数域成员。
type TNumber = class
Int: Integer;
end;
域的范围是静态的,即编译时对域的引用是固定的。要明白这一含义,考虑如下代码:
type
TAncestor = class
Value: Integer;
end;
TDescendant = class(TAncestor)
Value: string; //隐藏了继承得到的Value域
end;
var
MyObject: TAncestor;
begin
MyObject := TDescendant.Create;
MyObject.Value := 'Hello!'; //错误
TDescendant(MyObject).Value := 'Hello!'; //正常工作
end;
尽管MyObject保存了TDescendant的一个实例,它声明为TAncestor,但编译器仍将MyObject.Value解释为对TAncestor中声明的整数域的引用。不过,在TDescendant实例对象中仍然存在两个域,只是继承得到的Value域被新的域隐藏而已,可以通过类型转换访问前者。
===================================
13.
内存出错的讨论:"Access violation at address 地址 in Module '你的应用'.
这种在Delphi的开发中普遍存在.
这种内存访问错误,往往是访问了已经Free掉的对象,或是访问还没有生成的对象.
如果这个地址为 0000000, 则一般为访问还没有创建的对象.
如果这个地址不为0 ,而是一个地址, 那可能是要访问的对象已经Free掉. 或是要访问的对象是局部变量, 但还没有创建.
如果是调用DLL中的函数,则有可能
(1)取DLL函数入口失败.
(2)DLL中函数与调用处函数的调用约定不同(StdCall? )