当前位置: 首页 > news >正文

Delphi窗体创建释放过程及单元文件小结(转)

Delphi窗体创建释放过程及单元文件小结

Delphi中的窗体,有模式窗体与非模式窗体两种。两种窗体的调用方式不同,模式窗体使用ShowModal显示,非模式窗体使用Show显示。当显示模式窗体的时候你是不能操作本程序的其他窗体的,你不能把焦点从模式窗体转到其他窗体上。而非模式窗体则没有这种限制,你可以从一个非模式窗体切换到另外一个非模式窗体上。两种窗体的区别仅仅在调用的方式上有区别。

窗体的创建:

 

当使用Delphi的IDE New一个窗体后,在Project1.dpr文件中,会出现一句Application.CreateForm(TForm2, Form2);意思是当程序启动的时候会创建TForm2类的Form2实例,也就是窗体2。这一过程是自动的,不管你是否调用显示Form2,Form2已经存在了,其OnCreate事件也已经触发了。这时候,如果你想显示Form2,那么可以显式调用Form2的Show或ShowModal方法,以非模式或模式显示窗体。

 

如果你不想随程序启动而创建窗体,而是动态的创建窗体,那么,你可以删除上面的那句代码,然后在程序中你想动态创建窗体的地方加上以下代码:

Application.CreateForm(TForm2, Form2);或者使用Form2 := TForm2.Create(Application);两者的主要区别在于,触发OnCreate事件的时候,第一种方法Form2变量已经指向了新生成的实例,外第二种方法先调用TForm2的Create方法,再给Form2这个变量赋值,在OnCreate时Form2变量还是未定义的。

窗体销毁:

 

有创建,就必须有销毁,不然的话会产生内存泄漏。对于程序自动生成的窗体,在程序结束的时候会自己释放,对于这种窗体,我不建议进行手动释放,除非你确定释放后绝对不会再用到这个窗体了,不然就会产生内存访问错误。对于动态生成的窗体,一旦不再使用,一定要手动释放资源,手动释放主要有两种方式,第一种是显示调用Form.Free这个方法。对于上面用的例子Form2来说:

Form2.Free;

Form2 := nil;

要将变量Form2赋值为nil,是为了防止此后的代码通过Form2变量访问已经被释放的TForm2实例。

另一种方法是在窗体的OnClose事件中将变量Action设置为caFree。

procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);

begin

Action := caFree; // TCloseAction = (caNone, caHide, caFree, caMinimize);

Form2 := nil;

end;

这两种方法没有什么本质区别,可以根据实际情况来使用,但是一定不要忘记在释放资源后将变量指向空,不然很容易出现非法访问的情况。实际上在TForm2的FormClose中写Form2 := nil 是无用的,应该写在创建Form2的单元中,因为这两个Form2变量是不同的,TForm2所在单元的Form2变量是一个私有变量,别人是访问不到的,别人可以访问到的,也就是可能触发非法访问的是在TForm2所在单元外的Form2变量。

注:Delphi无论释放窗体还是其它什么变量,都是使用Free而不是Destroy方法,后者是内部调用的,在FormCreate或Free方法被调用时会自动调用到。

Delphi 单元文件结构

unitUnit1;  

   

interface

  {接口部分开始}

uses

  {引用单元列表,这是可选的,如果包含必须紧跟interface关键字} 

   

  {接口部分声明常量/类型/变量/过程和函数,这些声明对引用单元就像自己的声明一样}

  {在接口部分声明的过程和函数,就像使用了forward关键字} 

   

  {接口部分结束}

implementation

  {实现部分}

uses

  {如果包含uses字句,必须紧跟关键字implementation}

  {在这里实现interface中定义的过程和函数,可以任意顺序的定义和调用.}

  {在这里可以省略过程和函数的列表,如果包括,必须一样.}

  {可以定义单元私有的常量/类型(包括类)/变量/过程和函数,但这些对引用单元的客户是不可见的} 

   

{$R *.dfm}

  {如果是对应窗体的单元文件,会有这句. $R 指令用于加载一个外部资源文件, 这里是指加载同名的窗体文件一起编译.}

initialization

  {初始化部分}

  {程序启动时先执行,并顺序执行}

  {一个单元的初始化代码运行之前,就运行了它使用的每一个单元的初始化部分}

finalization

  {结束化部分,程序结束时执行}

end.

转载于:https://www.cnblogs.com/boltwolf/p/3387837.html

相关文章:

  • Linux部署zabbix3.4 结合钉钉智能报警
  • 学生分数排序
  • zabbix3.4上简单web监测功能测试
  • linux系统man查询命令等级与意义
  • 关于ES6的Promise的使用深入理解
  • P1065 津津的储蓄计划
  • 2018年 7月总结8月计划
  • Proteus仿真_01、 8086 IO译码仿真
  • CentOS 7之Postfix部署系列 (二) CentOS网络设置
  • AJAX PHP 请求实例
  • 使用Formik轻松开发更高质量的React表单(二)使用指南
  • HDU-3874 Necklace 线段树+离线
  • topcoder srm 590 div1 (max_flow_template)
  • JavaScript 代码格式化
  • ubuntu12.04下面安装eclipse开发环境
  • 【前端学习】-粗谈选择器
  • 77. Combinations
  • 78. Subsets
  • android高仿小视频、应用锁、3种存储库、QQ小红点动画、仿支付宝图表等源码...
  • - C#编程大幅提高OUTLOOK的邮件搜索能力!
  • ES学习笔记(10)--ES6中的函数和数组补漏
  • IP路由与转发
  • nginx 负载服务器优化
  • Node + FFmpeg 实现Canvas动画导出视频
  • Object.assign方法不能实现深复制
  • Python爬虫--- 1.3 BS4库的解析器
  • vue.js框架原理浅析
  • 构建工具 - 收藏集 - 掘金
  • 计算机在识别图像时“看到”了什么?
  • 开发了一款写作软件(OSX,Windows),附带Electron开发指南
  • 聊聊directory traversal attack
  • 盘点那些不知名却常用的 Git 操作
  • 普通函数和构造函数的区别
  • 七牛云假注销小指南
  • 前端临床手札——文件上传
  • 详解NodeJs流之一
  • 在GitHub多个账号上使用不同的SSH的配置方法
  • Oracle Portal 11g Diagnostics using Remote Diagnostic Agent (RDA) [ID 1059805.
  • TPG领衔财团投资轻奢珠宝品牌APM Monaco
  • ​业务双活的数据切换思路设计(下)
  • ​云纳万物 · 数皆有言|2021 七牛云战略发布会启幕,邀您赴约
  • # MySQL server 层和存储引擎层是怎么交互数据的?
  • #define与typedef区别
  • #Linux杂记--将Python3的源码编译为.so文件方法与Linux环境下的交叉编译方法
  • #mysql 8.0 踩坑日记
  • #pragma once与条件编译
  • #QT项目实战(天气预报)
  • #考研#计算机文化知识1(局域网及网络互联)
  • #我与Java虚拟机的故事#连载01:人在JVM,身不由己
  • #我与Java虚拟机的故事#连载19:等我技术变强了,我会去看你的 ​
  • (12)目标检测_SSD基于pytorch搭建代码
  • (2021|NIPS,扩散,无条件分数估计,条件分数估计)无分类器引导扩散
  • (39)STM32——FLASH闪存
  • (C语言)球球大作战
  • (安全基本功)磁盘MBR,分区表,活动分区,引导扇区。。。详解与区别