一.基本注意点
1.访问公共变量时需要设置临界区
2.不可直接操作界面,需通过向窗口发送消息来处理
PS:下面的测试程序中,为简单起见,在线程中直接对主界面进行了操作,实际开发
项目时是不应该如此操作的。
二.主要代码
公共变量与临界区变量
unit GlobalVar; interface uses Windows; var userCount:Integer; UserInfoRTL:TRTLCriticalSection; implementation end.
线程定义
unit UserInfoManage_Thread; interface uses Classes, SysUtils, GlobalVar,Windows; type TUserInfoManage_Thread= class(TThread) private public constructor Create(CreateSuspended: Boolean); procedure Execute;override; destructor Destroy;override; end; implementation uses Main; { TUserInfoManage_Thread } constructor TUserInfoManage_Thread.Create(CreateSuspended: Boolean); begin inherited Create(CreateSuspended); end; destructor TUserInfoManage_Thread.Destroy; begin inherited; end; procedure TUserInfoManage_Thread.Execute; var printStr:string; begin inherited; EnterCriticalSection(UserInfoRTL);//进入临界区 try userCount:=userCount+1; printStr:='第'+inttostr(userCount)+'个线程已启动,并进入临界区'; FrmMain.Memo1.Lines.Add(printStr); printStr:='休眠2000毫秒。。。'; FrmMain.Memo1.Lines.Add(printStr); Sleep(2000); printStr:='第'+inttostr(userCount)+'个线程执行完毕,离开临界区'; FrmMain.Memo1.Lines.Add(printStr+#13#10); finally LeaveCriticalSection(UserInfoRTL);//离开临界区 end; Self.FreeOnTerminate:=True; end; end.
主程序初始化“临界区变量”
userCount:=0; InitializeCriticalSection(UserInfoRTL);
连续启动多个线程
begin TUserInfoManage_Thread.Create(False); TUserInfoManage_Thread.Create(False); TUserInfoManage_Thread.Create(False); end;
三.运行结果
关于Class里的成员:
1.Public,
2.Private,
3.Protected,
4.Published,
以上四个class 的成员指令,它们的功用是什么??要怎么用和什么时候输入?怎样用?
和C++是差不多的、可见性不同、比较容易弄混的就是private和protected了、protected是只有自己和子类可见、private是同单元可见
1.private用于声明对象方法和字段具有有限的可见性,在申明类的单元外这个类不能被访问;。
2.protected 用于表示对象方法和字段具有有限的可见性,只能被当前的类和他的子类访问,只用同一个单元中的类,子类和任何代码可以访问protected成员;
3.public 用于表示可以被程序代码中的任意部分访问的数据和对象方法.
4.Published是发布的,发布的属性可以在属性列表中看到
Private: 私有的,只能自己使用或者是同一单元的子类使用,实例不可使用
Protected,保护的,自己和子类均可使用,实例不可访问的
Public,公共的,具体实例可以访问和使用
Published,发布的,主要是针对元件定义的类型,可以在属性列表中可见,使用同Public
public和published差不多,区别仅在于Published的成员可以被Delphi开发环境的Object Inspector所显示,因此一般将属性或事件声明于Published段
public 和published都是公有的,published又称发行成员,是说他定义的变量能在设计期访问,也就是在Object Inspector中显示可供设计期修改.
一般来说,你拖放到窗体上的控件的代码申明,控件的事件代码的申明都是在Pubished里面,自己申明的东西不要放在Published下面。
我补充一下:
published:
对象的这一部分将产生运行期类型信息(RTTI),
并使程序的其他部分能访问这部分,
object inspector 用RTTI 来产生属性的列表.
private:只有自己类中的函数或友类中的函数可以访问private级别的数据,不允许类的对象和其子类访问
翻译后意思也不一样!
私有
公用
保护
发布
DELPHI初始化元件的属性时,是按published的顺序来的。因此,如果属性之间存在依赖(比如某属性的Get和Set方法会引用另外的属性),那么请根据依赖关系来编写published中的顺序。否则,可能在属性初始化时出错。
public:是公共的,允许任何函数,类,对象访问,一般来说操作private数据的函数定义成public级别,提供对象与外部的接口;
protected:是保护的,对于本类族是公开的,其它的类是私有的(即其它的类不可见)
转自:http://blog.csdn.net/weide001/article/details/4100481
Ctrl+PageUp 将光标移至本屏的第一行,屏幕不滚动。
Ctrl+PageDown 将光标移至本屏的最后一行,屏幕不滚动。
Ctrl+↓ 向下滚动屏幕,光标跟随滚动不出本屏。
Ctrl+↑ 向上滚动屏幕,光标跟随滚动不出本屏。
Ctrl+Shift+NUM 在光标行设置最多九个临时标志号,对临时切换非常有用。 行的左边将出现一本书,封面有NUM,再按一次取消设置。
Ctrl+NUM 直接将光标跳到NUM处,NUM是用Ctrl+Shift+NUM设置的标号。 NUM不能用小键盘。 Ctrl+Home 将光标移至文件头。
Ctrl+End 将光标移至文件尾。
Ctrl+B Buffer List窗口。
Ctrl+I 同Tab键。
Ctrl+M 同Enter键。
Ctrl+N 同Enter键,但光标位置保持不变。
Ctrl+T 删除光标右边的一个单词。
Ctrl+Y 删除光标所在行。
Ctrl+Shift+↑ 光标在函数体内时,将光标快速移至当前函数声明处。
Ctrl+Shift+↓ 光标在函数声明行时,将光标快速移至函数定义处。
Ctrl+Shift+C 声明一个过程或函数后,直接生成过程或函数的名称、begin、end;
Ctrl+Shift+E 光标在Edit窗口和Explorer窗口间切换。
Ctrl+Shift+G 插入GUID。
Ctrl+Shift+J 弹出Delphi语句提示窗口,选择所需语句将自动完成一条语句。
Ctrl+Shift+T 在光标行加入To-Do注释。
Ctrl+Shift+Y 删除光标之后至本行末尾之间的文本。
Ctrl+F3 Call Stack窗口。
Ctrl+F4 等于File菜单中的Close项。
Ctrl+鼠标转轮 加速滚屏。
Shift+F8 调试时弹出CPU窗口。
Shift+F10 等于鼠标右键(Windows快捷键)。
Alt+F4 关闭所有编辑框中打开的源程序文件,但不关闭项目。设置Code Insight 模板,begin...end,以后只要输入be,然后按ctrl+j就可以匹配begin,end;但是从begin到相应的end,就不知道了,匹配 括号之类的可以用alt+[,Alt+] 搜索editor keyboard shortcuts可能可以找到,你自己看帮助吧。在编程序时 unit 右键菜单的properties /Code Insight 设置你喜欢的任何东东ctr+j即可。DELPHI IDE中部分操作快捷方式(大部分在Delphi 5.0的菜单中找不到,其中有一些还是非常有用的)
1 代码模板:CTRL+J
2 代码整块移动:CTRL+SHIFT+I(右移) CTRL+SHIFT+U(左移)
3 选中窗体 : 先选中任一控件,SHIFT+鼠标左键
4 将鼠标指向变量名、单元名、类名,再用 CTRL+鼠标左键 可找到相应的说明
5 在过程、函数、事件内部, SHIFT+CTRL+向上的方向键 可跳跃到相应的过程、函数、事件的定义
6 相反,在过程、函数、事件的定义处,SHIFT+CTRL+向下的方向键 可跳跃到具体过程、函数、事件内部
更详细参考:http://blog.csdn.net/wangjiaotou/article/details/4422647
一.基本声明
TOnUserInfoShow = procedure(userName:string;userAge:Integer)of object;//定义事件模型中的回调函数原型 TUserInfo = class private FName:string; FAge:Integer; FOnUserInfoShow: TOnUserInfoShow; procedure FSetAge(theAge:Integer); public property Name:string read FName;//只读属性(私有变量) property Age:Integer read FAge write FSetAge;//读写属性(私有变量,私有方法) property OnUserInfoShow:TOnUserInfoShow read FOnUserInfoShow write FOnUserInfoShow;//事件模型回调函数 constructor Create; end;
二.只读属性
构造函数
constructor TUserInfo.Create; begin Self.FName:='Terry'; Self.FAge:=20; end;
读取只读属性
begin Self.Memo1.Lines.Add('读取只读属性姓名:'+Self.theUserInfo.Name); end;
运行
三.读写属性
构造函数
constructor TUserInfo.Create; begin Self.FName:='Terry'; Self.FAge:=20; end;
修改读写属性,并读取新值
begin Self.Memo1.Lines.Add('修改前的读写属性年龄为:'+inttostr(Self.theUserInfo.Age)); Self.theUserInfo.Age:=30; Self.Memo1.Lines.Add('修改后的读写属性年龄为:'+inttostr(Self.theUserInfo.Age)); end;
运行
四.事件回调函数
主窗体成员函数
procedure TFrmMain.UserInfoShow(name: string; age: Integer); begin Self.Memo1.Lines.Add('用户姓名为:'+Self.theUserInfo.Name); Self.Memo1.Lines.Add('用户年龄为:'+inttostr(Self.theUserInfo.Age)); end;
主窗体创建时,将函数指针赋值给“事件回调函数”
procedure TFrmMain.FormCreate(Sender: TObject); begin Self.Memo1.Color:=clBlack; Self.Memo1.Font.Color:=clGreen; theUserInfo:=TUserInfo.Create; Self.theUserInfo.OnUserInfoShow:=Self.UserInfoShow; end;
调用事件回调函数
begin Self.theUserInfo.OnUserInfoShow(Self.theUserInfo.Name,Self.theUserInfo.Age); end;
运行
一.基本概念
只是一个“验证推断”的调式工具,而不是程序的一部分。
a)断言作用:顾名思义,开发者用于“验证自己的推断”的工具,调试阶段使用。
简单的参数验证——变量
复杂的条件验证——函数
简而言之, 断言是用来验证我们编码时所做的假设,而不是用来处理
运行时的各种逻辑分支。
b)开启与关闭
整个IDE: Project—>Option—>Compiler—>Assertion
代码中:{$ASSERTIONS ON} ,{$ASSERTIONS OFF}
C)何处使用
1)私有函数中进行“参数检查”
2)适当的地方,检查系统中的某些关键变量
对于公共函数,通常不使用assertion检查,因为一般来说,公共函数
必须对无效的参数进行检查和处理。而私有函数往往是直接使用的。
如果触发了断言,说明私有函数的“调用者出了差错”——没有保证好参数的范围
PS: 为什么私有函数里的条件检查不用if-else,而用断言
1)断言更加简洁
2)编码习惯上,私有函数通常“直接使用参数,而不检查”,程序的release版本里,
断言可以直接去除。
二.应用实例
调用私有函数:
begin {$ASSERTIONS ON} Self.SetUserInfo('Terry',200); end;
私有函数:
procedure TFrmMain.SetUserInfo(name: string; age: integer); begin ASSERT(((age>0)and(age<120)), '年龄输入超出范围!!'); Self.FName:=name; Self.FAge:=age; end;
运行结果:
一.主要代码
a)主窗体
type TFrameClass = class of TFrame; TFrmMain = class(TForm) Button1: TButton; Panel1: TPanel; Button2: TButton; procedure Button1Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private declarations } FCurrentfrmClassName: string; FCurrentfrm: TFrame; procedure LoadFrameByClassName(theFrameClass: TFrameClass); public { Public declarations } end; var FrmMain: TFrmMain; implementation {$R *.dfm} procedure TFrmMain.FormCreate(Sender: TObject); begin FCurrentfrmClassName:=''; FCurrentfrm:=nil; end; procedure TFrmMain.LoadFrameByClassName(theFrameClass: TFrameClass); begin if Assigned(FCurrentfrm)and( not SameText(theFrameClass.ClassName,FCurrentfrmClassName)) then FreeAndNil(FCurrentfrm); FCurrentfrm:=theFrameClass.Create(nil); FCurrentfrm.Parent:=Panel1; FCurrentfrm.Left:=(Panel1.Width-FCurrentfrm.Width)div 2; FCurrentfrm.Top:=(Panel1.Height-FCurrentfrm.Height)div 2; FCurrentfrmClassName:=theFrameClass.ClassName; end; procedure TFrmMain.Button1Click(Sender: TObject); begin Self.LoadFrameByClassName(TFrmFirstFrame); ShowMessage('显示第一个Frame!'); end; procedure TFrmMain.Button2Click(Sender: TObject); begin Self.LoadFrameByClassName(TFrmSecondFrame); ShowMessage('显示第二个Frame!'); end; end.
b)第一个Frame
type TFrmFirstFrame = class(TFrame) private { Private declarations } public { Public declarations } end; implementation {$R *.dfm} end.
c)第二个Frame
type TFrmSecondFrame = class(TFrame) private { Private declarations } public { Public declarations } end; implementation {$R *.dfm} end.
二.测试
显示第一个Frame
显示第二个Frame
参考VCL的代码,结合笔者近两年来的一些经验,可以简单总结出一套Delphi下常用的命名规范。
- 类型定义(type)
- 包括class、record、枚举、procedure/function变量等所有写在type下的类型定义
- 用大写的T开头,例如TList(class)、TPoint(record)、TAlign(枚举)、TNotifyEvent(procedure变量)
- 常量(const)
- 自定义的简单类型常量(如Integer、Pointer等类型)建议用C开头
- 也有不少常量是需要根据单词意思推断的,如MaxDateTime(以Max开头,让人从意思上猜到是常量)
- 字符串常量用S开头(因为字符串常量与简单类型常量在编译时处理方式不同,详情可参考《Delphi源代码分析》2.2.4常量)
- 类的private成员变量、implementation下的全局变量
- 用F开头
- 类里绝对不要出现public成员变量,所有要公开的属性用property或者procedure、function代理出来
- interface下的全局变量
- interface下最好不要出现全局变量,可以替换为用interface里的function返回implementation下的全局变量值
- 如果一定要有的话,用G开头
- 局部变量
- 用L开头
- 函数(procedure或function)实参
- 用A开头
除了这些以外,笔者有一些自己常用的Delphi编程习惯,拿出来跟大家分享,欢迎拍砖。
- 用项目缩写做名字开头
- 由于Delphi里没有C++中的namespace或者Java里的package这些概念,所以名字冲突问题比较严重。为了尽量避免这种问 题,可以在一个项目的专有全局类型、常量前面加上项目名称的缩写。例如对于一个叫做MyProject的项目,其下的专属类可以叫做 TMPOneClass,常量可以叫做CMPOneNumber,等等。
- 用function代替全局变量
- 当我们需要访问剪切板时,会用到Clipboard这个对象,不知道大家有没有注意到,这其实是一个返回TClipboard对象的function,而且还用到了设计模式的Singleton模式。
- 由于Delphi里调用无参函数可以不写括号,所以很多时候可以把一个function当做一个变量使用,具体怎么用大家可以发散一下思维,Singleton只是其中一个例子。
- 用Pascal命名法
- 上面这些命名方式,总得来说是根据Pascal命名法演化而来的。
- Pascal命名法的基本思想就是一个名字里如果包含多个单词,每个单词的首字母都要大写,例如ThisIsAnExample。
- 不建议使用下划线命名法(如this_is_an_example),主要是因为Delphi的变量名自动补全工具不会自动过滤下划线,手动输入比较累。。。
- 由于Delphi中变量名对大小写不敏感(如A和a其实是同一个变量,这是跟C语系的语言最大的不同),所以绝对不要尝试用字母大小写区分变量,所有变量最好都用大写字母开头。
-------------------------------------------------
本博客中凡是未标明【转】字样的文章均为原创,作者保留版权,转载请务必保留原文地址。
博客地址:http://xuxn.cnblogs.com
如有问题请联系:xuxin1123@gmail.com

