一.基本注意点

          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;

 

 

三.运行结果

   

posted @ 2012-05-23 16:58 edisonfeng 阅读(65) 评论(1) 编辑

关于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:是保护的,对于本类族是公开的,其它的类是私有的(即其它的类不可见)

posted @ 2012-05-23 09:55 edisonfeng 阅读(51) 评论(0) 编辑

转自: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

posted @ 2012-05-22 19:02 edisonfeng 阅读(7) 评论(0) 编辑

一.基本声明

 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;

  运行

 

 

posted @ 2012-05-22 18:54 edisonfeng 阅读(53) 评论(0) 编辑

一.基本概念

  只是一个“验证推断”的调式工具,而不是程序的一部分。
  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;

    运行结果:

   

posted @ 2012-05-22 15:46 edisonfeng 阅读(52) 评论(0) 编辑
摘要: 一.原理 通过使用“内存映射文件”,实现内存共享二.主要操作 共享内存结构: PShareMem = ^TShareMem; TShareMem = Record id:string[10]; name:string[20]; age:Integer; end; 基本变量: shareMemName:string; //共享内存名 fileHandle : THandle;//内存映射文件句柄 pUserInfoShareMem : PShareMem;//指向共享内存的指针 a)写入程序 1)创建“内存映射文件”begin //创建“内存映射文...阅读全文
posted @ 2012-05-21 17:42 edisonfeng 阅读(59) 评论(0) 编辑
摘要: 一.钩子的基本概念 a) Hook作用:监视windows消息,在“特定消息”没有到达窗口之前捕获它。 b)钩子分类: 线程专用钩子:只监视指定的线程 全局钩子:监视系统中的所有线程 如果Hook过程在应用程序中实现,若应用程序不是当前窗口时,该Hook就不起作用; 如果Hook在DLL中实现,程序在运行中动态调用它,它能实时对整个系统进行监控. c)几种常用类型的钩子: 1)键盘钩子可以监视各种键盘消息。 2)鼠标钩子可以监视各种鼠标消息。 3)外壳钩子可以监视各种Shell事件消息,启动和关闭应用程序等。 4)日志钩子可以记录从系统消息队列中取出的各种事件消息。...阅读全文
posted @ 2012-05-18 15:32 edisonfeng 阅读(71) 评论(0) 编辑

一.主要代码

   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

   

posted @ 2012-05-15 17:12 edisonfeng 阅读(15) 评论(0) 编辑

参考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

posted @ 2012-05-15 16:19 edisonfeng 阅读(88) 评论(0) 编辑
摘要: 一.自定义消息号和消息结构const WM_5001=WM_USER+5001; WM_5002=WM_USER+5002; WM_5003=WM_USER+5003; WM_6001=WM_USER+6001;type //自定义消息结构 PMsgRec = ^TMsgRec; TMsgRec = record msgNo : Cardinal; msgText: string; end;二.消息分发 向特定的对象分发消息:Dispatch函数 原理: 在TObject类中,有一个Dispatch()方法和一个DefaultHandler()方法,它们都是与消...阅读全文
posted @ 2012-05-14 17:07 edisonfeng 阅读(85) 评论(0) 编辑