This function creates a named or unnamed file-mapping objectfor the specified file. HANDLE CreateFileMapping( //通过调用fileopen or FileCreate后返回的文件句柄,如果是内存,则//$FFFFFFFF HANDLE hFile, //安全性结构,一般null LPSECURITY_ATTRIBUTES lpFileMappingAttributes, //文件试图的保护类型,PAGE_READONLY,PAGE_READWRITE, DWORD flProtect, //文件大小的高32位,一般设置为0,除非文件大于4G DWORD dwMaximumSizeHigh, //文件大小低32位 DWORD dwMaximumSizeLow, //映射的名字 LPCTSTR lpName );
...{ 作者: wudi_1982 联系方式: wudi_1982@hotmail.com 开发工具以及平台:DELPHI7+WINXP 转载请注明出处 } unit comm; interface uses Windows,SysUtils; const FILEMAPPINGNAME ='MyFileMapping'; // 指定内存映射的名字 MUTEXNAME='MutexName'; //互斥对象的名字 type TShareMem = record //共享内存的结构信息 Data : array[0..255] of char; //描述共享数据信息 ModifyUser : array[0..255] of char; //对数据的修改者 ModifyTime : array[0..7] of char; //数据最近一次的修改时间 end; PShareMem =^TShareMem; var FileMapHandle : THandle; //建立映射的句柄 MutexHandle : THandle; // 互斥对象的句柄 ShareMem : PShareMem; //一个指向共享内存的指针 function OpenMap:THandle; //打开一个映射文件并映射到本进程中 function CreateMap:THandle; //新建一个映射文件并映射到本进程中 function LockMap:boolean; //加锁 procedure UnLockMap; //解锁 procedure CloseMap; //关闭映射 function ReadCommData:TShareMem; //从共享信息中读取数据 procedure WriteCommData(data,user,time : string);//对共享内存进行写操作 implementation function OpenMap:THandle; begin //打开映射文件 FileMapHandle := OpenFileMapping(FILE_MAP_ALL_ACCESS, //所有权限 false, //子进程不可继承 FILEMAPPINGNAME ); if FileMapHandle <>0 then //如果映射文件打开成功 begin //将映射文件映射到本进程 ShareMem := pSharemem(MapViewOfFile(FileMapHandle,FILE_MAP_ALL_ACCESS,0,0,0)); if ShareMem = nil then begin CloseHandle(FileMapHandle); Result :=0; end else begin //初始化共享区域 FillChar(ShareMem^,sizeof(TSharemem),0); Result := FileMapHandle; end; end else Result :=0; end; function CreateMap:THandle; begin FileMapHandle := CreateFileMapping($FFFFFFFF,//内存映射 nil, PAGE_READWRITE,//读写操作 0,//高32位 ,一般为0,除非要映射的文件大于4G sizeof(TShareMem), FILEMAPPINGNAME ); if FileMapHandle <>0 then begin ShareMem := pSharemem(MapViewOfFile(FileMapHandle,FILE_MAP_ALL_ACCESS,0,0,0)); if ShareMem = nil then begin CloseHandle(FileMapHandle); Result :=0; end else Result := FileMapHandle; end else Result :=0; end; function LockMap:boolean; begin //创建一个互斥对象并加锁 MutexHandle := CreateMutex(nil,false,MUTEXNAME); if MutexHandle <>0 then begin if WaitForSingleObject(MutexHandle,1000)= WAIT_FAILED then Result :=false else Result :=true; end else Result :=false; end; procedure UnLockMap; begin //释放资源 if MutexHandle <>0 then begin ReleaseMutex(MutexHandle); CloseHandle(MutexHandle); end; end; procedure CloseMap; begin // 关闭映射并释放资源 if ShareMem <> nil then UnmapViewOfFile(ShareMem); if FileMapHandle <>0 then CloseHandle(FileMapHandle); end; function ReadCommData:TShareMem; var tm : TShareMem; begin with tm do begin Data := ShareMem^.Data; ModifyUser := ShareMem^.ModifyUser; ModifyTime := ShareMem^.ModifyTime; end; Result := tm; end; procedure WriteCommData(data,user,time : string); begin StrCopy(ShareMem^.Data,pchar(data)); StrCopy(ShareMem^.ModifyUser,pchar(user)); StrCopy(ShareMem^.ModifyTime,pchar(time)); end; end.
代码的另一个部分就是根据需要调用这些函数的FirstTest.pas,即上面窗体单元对应的代码
...{ 作者: wudi_1982 联系方式: wudi_1982@hotmail.com 开发工具以及平台:DELPHI7+WINXP 转载请注明出处 } unit FirstTest; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls, ExtCtrls; const WM_MYMESSAGE=WM_USER+1024; //一个自定义消息,用来通知接受程序数据到达 type TForm1 =class(TForm) GroupBox1: TGroupBox; Label1: TLabel; Label2: TLabel; Label3: TLabel; edData: TEdit; edModifyUser: TEdit; edModifyTime: TEdit; Panel1: TPanel; btnCreate: TButton; btnOpen: TButton; btnRead: TButton; btnSet: TButton; btnClose: TButton; btnClear: TButton; StatusBar1: TStatusBar; GroupBox2: TGroupBox; Label4: TLabel; Label5: TLabel; Label6: TLabel; edRData: TEdit; edRUser: TEdit; edRTime: TEdit; procedure btnCreateClick(Sender: TObject); procedure btnOpenClick(Sender: TObject); procedure btnSetClick(Sender: TObject); procedure btnCloseClick(Sender: TObject); procedure btnReadClick(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure btnClearClick(Sender: TObject); procedure FormCreate(Sender: TObject); private atm : TAtom; //一个原子 nextwindow : string; //被发送消息程序的标题信息 procedure MyMessage(var msg : TMessage);message WM_MYMESSAGE; //自定义消息的处理 public end; var Form1: TForm1; implementation uses comm; ...{$R *.dfm} procedure TForm1.btnCreateClick(Sender: TObject); begin if CreateMap =0 then ShowMessage('内存映射建立失败') else begin btnCreate.Enabled :=false; btnOpen.Enabled :=false; StatusBar1.Panels[0].Text :='内存映射文件新建立完毕' end; end; procedure TForm1.btnOpenClick(Sender: TObject); begin if OpenMap =0 then ShowMessage('内存映射打开失败') else begin btnCreate.Enabled :=false; btnOpen.Enabled :=false; StatusBar1.Panels[0].Text :='内存映射文件打开完毕' end; end; procedure TForm1.btnSetClick(Sender: TObject); var hd : THandle; begin if (edData.Text ='') or (edModifyUser.Text ='') then ShowMessage('请填写完整信息') else begin edModifyTime.Text := FormatDateTime('mm:hh:mm',Now); WriteCommData(edData.Text,edModifyUser.Text,edModifyTime.Text); //查找此程序的另外一个实例,如果找到,发送数据到达的消息 hd := FindWindow(nil,pchar(nextwindow)); if hd <>0 then SendMessage(hd,WM_MYMESSAGE,1,0); end; end; procedure TForm1.btnCloseClick(Sender: TObject); begin UnLockMap; CloseMap; btnCreate.Enabled :=true; btnOpen.Enabled :=true; end; procedure TForm1.btnReadClick(Sender: TObject); var tm : TShareMem; begin tm := ReadCommData; edRData.Text := tm.Data; edRUser.Text := tm.ModifyUser; edrTime.Text := tm.ModifyTime; end; procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin UnLockMap; CloseMap; //下面这一句非常重要,如果不及时删除原子表中添加的原子, //怕是只有重启计算机才能干掉程序启动时添加到原子表中的信息了 GlobalDeleteAtom(atm); end; procedure TForm1.btnClearClick(Sender: TObject); begin edData.Text :=''; edModifyUser.Text :=''; edModifyTime.Text :=''; end; procedure TForm1.MyMessage(var msg: TMessage); begin if msg.WParam =1 then begin Application.BringToFront; StatusBar1.Panels[0].Text :='新数据到代'; btnReadClick(nil); end; end; procedure TForm1.FormCreate(Sender: TObject); begin //下面的代码将在程序启动时执行,主要是通过原子表检查此程序是否运行, //本程序运行运行两个实例,一个用来建立映射文件, //一个用来打开映射文件,你完全可以用两个不同的程序来处理,这里为了方便 //以及演示原子表的使用而采用一个程序执行两次的方法来做 if GlobalFindAtom(pchar('wudi_1982')) <>0 then//查找原子表如果第一个窗体已经存在 begin if GlobalFindAtom(pchar('jingyang')) <>0 then//如果第二个窗体也存在 begin Application.Terminate; end else begin //添加原子到原子表,以记录此程序的第二个实例已经运行,并做相应操作 atm := GlobalAddAtom(pchar('jingyang')); Application.Title :='MyMapForm_2'; Form1.Caption :='MyMapForm_2'; nextwindow :='MyMapForm_1'; end; end else begin //添加原子到原子表,以记录此程序的第一个实例已经运行,并做相应操作 atm := GlobalAddAtom(pchar('wudi_1982')); Application.Title :='MyMapForm_1'; Form1.Caption :='MyMapForm_1'; nextwindow :='MyMapForm_2'; end; end; end.