特急:请问如何用sendmessage在两个应用程序间通讯?(300分示例代码)(300分)

  • 主题发起人 主题发起人 gztiger
  • 开始时间 开始时间
G

gztiger

Unregistered / Unconfirmed
GUEST, unregistred user!
有自己写的两个应用程序,app1.exe及app2.exe,如何在app2.exe中发一消息至app1.exe?<br>望能给出发消息及接消息的示例代码。
 
实在没有时间帮你作,可参见下帖及处理WM_COPYDATA消息<br>http://www.delfan.com/language/delphi/self/wmcopy.html<br>有源程序
 
请看我在下面两帖中的回复, 有空多在站内搜索一下吧。<br>http://www.delphibbs.com/delphibbs/dispq.asp?lid=1216872<br>http://www.delphibbs.com/delphibbs/dispq.asp?lid=547734
 
发送端<br>unit Unit1;<br><br>interface<br><br>uses<br>&nbsp; Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,<br>&nbsp; Dialogs, StdCtrls;<br><br>type<br>&nbsp; TForm1 = class(TForm)<br>&nbsp; &nbsp; Button1: TButton;<br>&nbsp; &nbsp; Edit1: TEdit;<br>&nbsp; &nbsp; procedure Button1Click(Sender: TObject);<br>&nbsp; private<br>&nbsp; &nbsp; { Private declarations }<br>&nbsp; public<br>&nbsp; &nbsp; { Public declarations }<br>&nbsp; end;<br><br>var<br>&nbsp; Form1: TForm1;<br><br>implementation<br><br>{$R *.dfm}<br><br>procedure TForm1.Button1Click(Sender: TObject);<br>var<br>&nbsp; H: THandle;<br>&nbsp; CopyDataStruct: TCopyDataStruct;<br>begin<br>&nbsp; h:=FindWindow(nil, 'App1');<br>&nbsp; if h&lt;&gt;0 then<br>&nbsp; begin<br>&nbsp; &nbsp; CopyDataStruct.cbData:=Length(Edit1.Text)+1;<br>&nbsp; &nbsp; CopyDataStruct.lpData:=PChar(Edit1.Text);<br>&nbsp; &nbsp; SendMessage(h, WM_CopyData, 0, LParam(@CopyDataSTruct))<br>&nbsp; end<br>end;<br><br>end.<br>接受端:<br>unit Unit1;<br><br>interface<br><br>uses<br>&nbsp; Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,<br>&nbsp; Dialogs;<br><br>type<br>&nbsp; TForm1 = class(TForm)<br>&nbsp; &nbsp; procedure FormCreate(Sender: TObject);<br>&nbsp; private<br>&nbsp; &nbsp; { Private declarations }<br>&nbsp; &nbsp; procedure WMCopyData(var Msg: TWMCopyData); message WM_CopyData;<br>&nbsp; public<br>&nbsp; &nbsp; { Public declarations }<br>&nbsp; end;<br><br>var<br>&nbsp; Form1: TForm1;<br><br>implementation<br><br>{$R *.dfm}<br><br>procedure TForm1.FormCreate(Sender: TObject);<br>begin<br>&nbsp; Caption:='App1'<br>end;<br><br>procedure TForm1.WMCopyData(var Msg: TWMCopyData);<br>var<br>&nbsp; s: string;<br>begin<br>&nbsp; s:=StrPas(PChar(Msg.CopyDataStruct^.lpData));<br>&nbsp; ShowMessage(s)<br>end;<br><br>end.
 
//发送端<br>function tform1.IsAlermAndVioce(sMsg:string):integer;<br>var BgnAt,EndAt,i,Index:integer;<br>&nbsp; &nbsp; BoxTno,Boxno:string;<br>&nbsp; &nbsp; Opt,PerID,Postno:integer;<br>&nbsp; &nbsp; RecTime:TDateTime;<br>&nbsp; &nbsp; rc:integer;<br>&nbsp; &nbsp; ds: TCopyDataStruct;<br>&nbsp; &nbsp; hd: THandle;<br>begin<br>&nbsp; Index:=0;<br>&nbsp; for i:=1 to Length(sMsg) do<br>&nbsp; begin<br>&nbsp; &nbsp; case sMsg of<br>&nbsp; &nbsp; &nbsp; '[':BgnAt:=i;<br>&nbsp; &nbsp; &nbsp; ']':<br>&nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; EndAt:=i;<br>&nbsp; &nbsp; &nbsp; &nbsp; Inc(Index);<br>&nbsp; &nbsp; &nbsp; &nbsp; case Index of<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //交接箱弹编号<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2:BoxTno:=copy(sMsg,BgnAt+1,EndAt-BgnAt-1);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //交接箱编号<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3:Boxno:=copy(sMsg,BgnAt+1,EndAt-BgnAt-1);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //操作对象<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 4:Opt:=strtoInt(copy(sMsg,BgnAt+1,EndAt-BgnAt-1));<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //员工工序号<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 5:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PerID:=strtoInt(copy(sMsg,BgnAt+1,EndAt-BgnAt-1));<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; except<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PerID:=0;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //命令时间<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 6:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; RecTime:=StrtoDatetime(copy(sMsg,BgnAt+1,EndAt-BgnAt-1));<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; except<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //局号<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 9:Postno:=strtoInt(copy(sMsg,BgnAt+1,EndAt-BgnAt-1));<br>&nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; end;<br>&nbsp; end;<br>&nbsp; if (BoxTno='8004') or (BoxTno='8005') or (BoxTno='8006') then<br>&nbsp; begin<br>&nbsp; &nbsp; {showMessage('Postno='+Inttostr(Postno)+#13+<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ';BoxTno='+BoxTno+#13+<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ';PerID='+Inttostr(PerID)); }<br>&nbsp; &nbsp; StoredProc1.ParamByName('@Pno').asInteger:=Postno;<br>&nbsp; &nbsp; StoredProc1.ParamByName('@Lno').asstring:=BoxTno;<br>&nbsp; &nbsp; StoredProc1.ParamByName('@HID').asInteger:=PerID;<br>&nbsp; &nbsp; StoredProc1.ParamByName('@CHDT').asDateTime:=RecTime;<br>&nbsp; &nbsp; try<br>&nbsp; &nbsp; &nbsp; StoredProc1.ExecProc;<br>&nbsp; &nbsp; &nbsp; result:=StoredProc1.ParamByName('@RC').asInteger;<br>&nbsp; &nbsp; except<br>&nbsp; &nbsp; &nbsp; result:=0;<br>&nbsp; &nbsp; end;<br>&nbsp; end else<br>&nbsp; begin<br>&nbsp; &nbsp; result:=-1;<br>&nbsp; &nbsp; if (Opt=3) or (Opt=4) then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; ds.cbData := Length (sMsg) + 1;<br>&nbsp; &nbsp; &nbsp; GetMem (ds.lpData, ds.cbData ); //为传递的数据区分配内存<br>&nbsp; &nbsp; &nbsp; StrCopy (ds.lpData, PChar (sMsg));<br>&nbsp; &nbsp; &nbsp; Hd := FindWindow (nil, '语音报警'); // 获得接受窗口的句柄<br>&nbsp; &nbsp; &nbsp; if Hd &lt;&gt; 0 then<br>&nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; SendMessage (Hd, WM_COPYDATA, Handle,Cardinal(@ds)); // 发送WM_COPYDATA消息<br>&nbsp; &nbsp; &nbsp; &nbsp; Result:=22;<br>&nbsp; &nbsp; &nbsp; end<br>&nbsp; &nbsp; &nbsp; else Result:=21;<br>&nbsp; &nbsp; &nbsp; FreeMem (ds.lpData); //释放资源<br>&nbsp; &nbsp; end;<br>&nbsp; end;<br>end;<br>//接收端<br>type<br>&nbsp; PAlermRec=^TAlermRec;<br>&nbsp; TAlermRec=record<br>&nbsp; &nbsp; Boxno:string;<br>&nbsp; &nbsp; Postno:Integer;<br>&nbsp; &nbsp; Station:string;<br>&nbsp; &nbsp; AlermTime:TDatetime;<br>&nbsp; end;<br>...<br>procedure TvioceMain.GetAlermMessage(var t:TWmCopyData);<br>var InfoSta:Integer;<br>&nbsp; &nbsp;AlermRec:PAlermRec;<br>begin<br>&nbsp; New(AlermRec);<br>&nbsp; RecieveStr:=StrPas(t.CopyDataStruct^.lpData);<br>&nbsp; InfoSta:=SetAlermMessage(RecieveStr,AlermRec);<br>&nbsp; lstMessage.Items.Add(Format('[%d]局交接箱[%s]在',[AlermRec^.Postno,AlermRec^.Boxno])+<br>&nbsp; &nbsp; FormatDatetime('yyyy"年"mm"月"dd"日" hh:mm:ss',AlermRec^.AlermTime)+<br>&nbsp; &nbsp; Format('出现[%s]',[AlermRec^.Station]));<br>&nbsp; case InfoSta of<br>&nbsp; &nbsp;-1:SetlstMessageLine(1);<br>&nbsp; &nbsp; 0,1,2:<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; SetlstMessageLine(2);<br>&nbsp; &nbsp; &nbsp; case QueryExecSQL(Format(SQL_PerTelStr,[AlermRec^.Postno,AlermRec^.Boxno])) of<br>&nbsp; &nbsp; &nbsp; &nbsp;-1:SetlstMessageLine(3);<br>&nbsp; &nbsp; &nbsp; &nbsp; 0:begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if GetWavFiles(AlermRec^.Boxno,AlermRec^.station)&lt;&gt;-1 then exit;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CurlstIndex:=0;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CurDialTimes:=0;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Dialtel;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; end;<br>&nbsp; end;<br>&nbsp; Dispose(AlermRec);<br>end;
 
摘自:Delphi之未经证实的葵花宝典version 2.7<br><br>用Delphi实现程序间的数据传递<br><br>在实际应用中,我们经常需要多个程序相互配合来完成某些特定功能。例如两个应用<br>程序间的同步、互斥;应用程序在起第二份实例时的参数自动传递…。要实现这些功<br>能,就必须能实现程序间的数据传递。<br><br>有些特殊的高级技术可在不同的程序间传递数据,如剪贴板、动态数据交换以及OLE<br>自动化,但有条件限制并且相对较复杂。这里,我介绍三种有效的底层技术,希望对<br>编程爱好者有所帮助。<br><br>利用WM_COPYDATA消息 <br> <br><br>使用该消息涉及一个TcopyDataStruct结构类型的指针。该结构中有三个成员:<br><br>dwData 是一个32位的附加参数<br><br>cbData 表示要传递的数据区的大小<br><br>lpData 表示要传递的数据区的指针<br><br>下面举个例子。该例子由两个程序构成,分别为SendData和GetData。<br><br>SendData程序向GetData程序发送消息,并传递edit1中的字符串;GetData在收到<br>消息后,把SendData发送的字符串接受下来,并显示在相应的edit1中。<br><br>SendData程序: <br>……<br><br>var<br><br>Form1: TForm1;<br><br>implementation<br><br>{$R *.DFM}<br><br>procedure TForm1.Button1Click(Sender: TObject);<br><br>var<br><br>ds: TCopyDataStruct;<br><br>hd: THandle;<br><br>begin<br><br>ds.cbData := Length (Edit1.Text) + 1;<br><br>GetMem (ds.lpData, ds.cbData ); //为传递的数据区分配内存<br><br>StrCopy (ds.lpData, PChar (Edit1.Text));<br><br>Hd := FindWindow (nil, 'Form2'); // 获得接受窗口的句柄<br><br>if Hd &lt;&gt; 0 then<br><br>SendMessage (Hd, WM_COPYDATA, Handle,<br><br>Cardinal(@ds)) // 发送WM_COPYDATA消息<br><br>else<br><br>ShowMessage ('目标窗口没找到!');<br><br>FreeMem (ds.lpData); //释放资源<br><br>end;<br><br>GetData程序: <br> <br><br>TForm2 = class(TForm)<br><br>Edit1: TEdit;<br><br>private<br><br>{ Private declarations }<br><br>public<br><br>procedure Mymessage(var t:TWmCopyData);message WM_COPYDATA;<br><br>{ Public declarations }<br><br>end;<br><br>var<br><br>Form2: TForm2;<br><br>implementation<br><br>procedure TForm2.Mymessage(var t:TWmCopyData);<br><br>begin<br><br>Edit1.text:=StrPas(t.CopyDataStruct^.lpData);//接受数据并显示。<br><br>end;<br><br>使用这种方法是WIN32应用程序进行交互的最简单的方法。<br><br>使用全局原子 <br>Win32系统中,为了实现信息共享,系统维护了一张全局原子表。每个原子中存放了一<br>些共享数据。关于对原子的操作,有一组专门的API函数:<br><br>GlobalAddAtom 在表中增加全局原子<br><br>GlobalDeleteAtom 在表中删除全局原子<br><br>GlobalFindAtom 在表中搜索全局原子<br><br>GlobalGetAtomName 从表中获取全局原子<br><br>笔者用这种方法实现了避免程序二次启动,但把第二次启动所带的参数传到第一个实<br>例中以进行相应的处理的程序。基本处理如下:<br><br>在工程文件中:<br><br>program Pvdde;<br><br>uses<br><br>Forms,shellapi,Windows,dialogs,dde in 'dde.pas' {Form1};<br><br>{$R *.RES}<br><br>begin<br><br>if GlobalFindAtom(PChar('PDDE_IS_RUNNING')) = 0 then<br><br>//避免二次启动<br><br>begin<br><br>K:=GlobalAddAtom(PChar('PDDE_IS_RUNNING'));<br><br>Application.Initialize;<br><br>Application.CreateForm(TForm1, Form1);<br><br>Application.Run;<br><br>end<br><br>else<br><br>begin<br><br>//传递二次启动时的参数到第一个实例<br><br>H := FindWindow(PChar('TForm1'), PChar('资料保密 严禁外传'));<br><br>if ParamCount &gt; 0 then<br><br>begin<br><br>L := GlobalAddAtom(PChar(ParamStr(1)));<br><br>if H&lt;&gt;0 then<br><br>SendMessage(H, WM_MYMESSAGE, 0, L); <br><br>{ 传递原子句柄 }<br><br>GlobalDeleteAtom(L); { 使用后释放 }<br><br>end;<br><br>Application.Terminate;<br><br>end;<br><br>end.<br><br>在相应的窗口单元dde.pas增加对自定义消息WM_MYMESSAGE的处理:<br><br>procedure TForm1.MyMessage(var T:TMessage); <br><br>{对 WM_MYMESSAGE消息进行处理 }<br><br>var<br><br>P:Array [0..255] of char;<br><br>begin<br><br>GlobalGetAtomName(T.LParam, P,255); { 接受数据到p数组中 }<br><br>。。。<br><br>end;<br><br>使用存储映象文件 <br> <br><br>这种方法相对较复杂一些。<br><br>当Win95与Winows Nt向内存中装载文件时,使用了特殊的全局内存区。在该区域内,<br>应用程序的虚拟内存地址和文件中的相应位置一一对应。由于所有进程共享了一个用<br>于存储映象文件的全局内存区域,因而当两个进程装载相同模块(应用程序或DLL文<br>件)时,它们实际可以在内存中共享其执行代码。<br><br>笔者通过调用一个带有特殊参数的CreateFileMapping函数,来间接达到程序间共享<br>内存的目的。下面简要解释一下该函数。<br><br>HANDLE CreateFileMapping(<br><br>HANDLE hFile, //文件句柄 <br><br>LPSECURITY_ATTRIBUTES lpFileMappingAttributes, // 可选安全属性<br><br>DWORD flProtect, // 映象文件保护方式 <br><br>DWORD dwMaximumSizeHigh, // 映象文件区域的底值 <br><br>DWORD dwMaximumSizeLow, // 映象文件区域的顶值 <br><br>LPCTSTR lpName // 映象文件的名字<br><br>); <br><br>如果hFile是0xFFFFFFFF,在调用程序中必须指定dwMaximumSizeHigh 和<br>dwMaximumSizeLow参数的值以确定映象文件的大小。通过这样的参数指定,该函数<br>就创建了一个由操作系统页文件支持的特殊逻辑映象文件,而不是由实际操作系统<br>的文件支持的逻辑映象文件。这个逻辑映象文件可以通过复制、继承或者按名字来<br>达到共享。至于其它参数的详细说明,请参看在线帮助。<br><br>在建立了映象文件之后,我们可以通过调用另外一个API函数MapViewOfFile来访问<br>它的内存,该函数会返回一个指向共享内存块的特定指针。<br><br>LPVOID MapViewOfFile(<br><br>HANDLE hFileMappingObject, // 映象文件句柄 <br><br>DWORD dwDesiredAccess, // 访问方式 <br><br>DWORD dwFileOffsetHigh, // 映象文件区域的底值 <br><br>DWORD dwFileOffsetLow, // 映象文件区域的顶值<br><br>DWORD dwNumberOfBytesToMap // 映射字节数<br><br>);<br><br>如果 dwNumberOfBytesToMap 是0,映射整个文件。<br><br>以下举例说明:<br><br>private<br><br>hMapFile: THandle;<br><br>MapFilePointer: Pointer;<br><br>public<br><br>{ Public declarations }<br><br>end;<br><br>var<br><br>Form1: TForm1;<br><br>implementation<br><br>{$R *.DFM}<br><br>procedure TForm1.FormCreate(Sender: TObject);<br><br>begin<br><br>hMapFile := CreateFileMapping (<br><br>$FFFFFFFF, // 特殊内存映射句柄<br><br>nil, page_ReadWrite, 0,10000, <br><br>'DdhDemoMappedFile'); // 文件名<br><br>if hMapFile &lt;&gt; 0 then<br><br>MapFilePointer := MapViewOfFile (<br><br>hMapFile, // 上面映象文件的句柄<br><br>File_Map_All_Access, <br><br>0, 0, 0) // 访问整个映象文件<br><br>else<br><br>ShowMessage ('hMapFile = 0');<br><br>if MapFilePointer = nil then<br><br>ShowMessage ('MapFilePointer = nil');<br><br>end;<br><br> <br><br>procedure TForm1.BtnWriteClick(Sender: TObject);<br><br>begin<br><br>StrCopy (PChar (MapFilePointer),<br><br>PChar (EditWrite.Text));//把内容写入共享内存<br><br>end;<br><br> <br><br>procedure TForm1.BtnReadClick(Sender: TObject);<br><br>var<br><br>S: string;<br><br>begin<br><br>S := PChar (MapFilePointer);//从共享内存读出内容<br><br>EditRead.Text := S;<br><br>end;<br><br>用这种方法,不但可以在不同的程序之间共享数据,还可以在同一程序的不同实例间<br>共享数据。为了及时通知其它进程共享数据的变化,可以自定义一条用户消息,通过<br>发消息来实现,这里不再赘述。<br><br>利用以上三种方法均可以有效地实现数据传递、共享,所有的例子程序均在<br>Delphi 3.0,4.0下调试通过。如需源码,写信至wj_email@yahoo.com索<br>
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
2K
DelphiTeacher的专栏
D
后退
顶部