如何在不同的程序间通信!不是用sendmessage, postmessage.....(100分)

  • 主题发起人 主题发起人 luojun
  • 开始时间 开始时间
L

luojun

Unregistered / Unconfirmed
GUEST, unregistred user!
如何在不同的程序间通信!不是用sendmessage, postmessage.....<br>比如传送string
 
&lt;a href="http://www.gislab.ecnu.edu.cn/delphibbs/DispQ.asp?LID=142451" target="_blank"&gt;这里看我的回答&lt;/a&gt;可以实现不同进程间的通讯,<br>使用全局原子"Atom".
 
在dpr文件中:<br>var<br>&nbsp; hMutex : Thandle;<br>&nbsp; WaitResult : word;<br>&nbsp; Mf : DWORD;<br>&nbsp; S:String;<br>begin<br>&nbsp; &nbsp; &nbsp;hMutex := createMutex(nil,false,pchar(utCommon.SysName));<br>&nbsp; &nbsp; &nbsp;WaitResult := WaitForSingleObject(hMutex,10);<br>&nbsp; &nbsp; &nbsp;if ( waitResult = WAIT_TIMEOUT ) then<br>&nbsp; &nbsp; &nbsp;begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; S:=ParamStr(1);//实际上是您所双击的文件名(含路径)<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Mf:=FindWindow('TMainForm', ‘主窗口的Caption');<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (Mf&lt;&gt;0) and (GlobalFindAtom(PChar(S))=0) then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;SendMessage(Mf, WM_User+1, GlobalAddAtom(PChar(S)), Length(S)+1);//发送Atom句柄<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;WaitForSingleObject(hMutex,10);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SetForegroundWindow (Mf);<br>&nbsp; &nbsp; &nbsp;end<br>&nbsp; &nbsp; &nbsp;else<br>&nbsp; &nbsp; &nbsp;begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Application.Initialize;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Application.CreateForm(TMainForm, MainForm);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Application.Run;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ReleaseMutex(hMutex);<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; CloseHandle(hMutex); // close the mutex handle<br>end.<br><br>主窗口:<br>procedure TMainForm.WndProc(var Message: TMessage);<br>begin<br>&nbsp; &nbsp; &nbsp;if Message.Msg=WM_User+1 then<br>&nbsp; &nbsp; &nbsp;begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FillChar(OpenFileName, Sizeof(OpenFileName),0);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; GlobalGetAtomName(Message.WParam, @OpenFileName, Message.LParam);//读取其他进程发来的Atom中的字符串<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Show;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WindowState := wsMaximized;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Application.BringToFront;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; OpenTest(OpenFileName); &nbsp;//打开一个子窗口显示文件<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; GlobalDeleteAtom(Message.WParam);<br>&nbsp; &nbsp; &nbsp;end<br>&nbsp; &nbsp; &nbsp;else<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Inherited WndProc(Message);<br>end;<br><br>&nbsp;<br><br>
 
简单的方法,在注册表中建立临时的string.
 
发送sString:(FMessage是自定义的一个跟别的不重复的字符串)<br>&nbsp; FMesID:=RegisterWindowMessage(PChar(FMessage));<br><br>&nbsp; BSMRecipients := BSM_APPLICATIONS;<br><br>&nbsp; repeat<br>&nbsp; &nbsp; iResult := BroadCastSystemMessage(BSF_IGNORECURRENTTASK or BSF_POSTMESSAGE,@BSMRecipients, FMesID, -1, 0);<br>&nbsp; until(iResult &lt;&gt; -1);//start post<br><br>&nbsp; for i:=1 to length(ParamStr(1)) do<br>&nbsp; &nbsp; repeat<br>&nbsp; &nbsp; &nbsp; iResult := BroadCastSystemMessage(BSF_IGNORECURRENTTASK or BSF_POSTMESSAGE,@BSMRecipients, FMesID, 1, ord(sString));<br>&nbsp; &nbsp; until (iResult &lt;&gt; -1);<br><br>&nbsp; repeat<br>&nbsp; &nbsp; iResult := BroadCastSystemMessage(BSF_IGNORECURRENTTASK or BSF_POSTMESSAGE,@BSMRecipients, FMesID, -1, 0);<br>&nbsp; until (iResult &lt;&gt; -1);//stop post<br><br>接收sString:全局变量bReceiveFlag初始化为false;<br>procedure TMainForm.WndProc(var M: TMessage);<br>begin<br>&nbsp; if (M.Msg=FMesID) then //our message has arrived<br>&nbsp; begin<br>&nbsp; &nbsp; case M.WParam of<br>&nbsp; &nbsp; -1:<br>&nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; bReceiveFlag := not bReceiveFlag;<br>&nbsp; &nbsp; &nbsp; &nbsp; if(not bReceiveFlag) then//after receive the paramstr(1)<br>&nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(Assigned(FReceiveParam)) then FReceiveParam(Self);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { if main form is minimized, normalize it }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { set focus to application }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if IsIconic(Application.Handle) then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Application.MainForm.WindowState := wsNormal;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Application.Restore;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SetForegroundWindow(Application.MainForm.Handle);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if Text &lt;&gt; '' then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if Title='' then FTitle:=Application.Title;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Application.MessageBox(PChar(FText),PChar(FTitle),MB_OK);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; end<br>&nbsp; &nbsp; &nbsp; &nbsp; else FParam := '';//ready to receive paramstr(1)<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; 1: FParam := FParam + chr(M.LParam);//receiving paramstr(1)<br>&nbsp; &nbsp; end;<br>&nbsp; end<br>&nbsp; else //it's not our message-let app to process it<br>&nbsp; &nbsp; Inherited WndProc(Message);<br>end;<br><br><br>
 
看你的信息量有多大了,大的话还可以用WM_COPYDATA消息,map file等.
 
我对WM_COPYDATA有个疑问,如果两个程序都在截获WM_COPYDATA消息,<br>是不是就冲突了?<br><br>map file怎么用?
 
可以用内存文件<br>这样可以多个程序公用一块内存区域<br>具体做法在机械工业出版社出版的高级编程里面讲过,用来传递数据还是相当不错<br>就是比较复杂,但是对数据没有什么限制呀<br><br>只能给个思路了,我一时找不到那份资料了,抱歉抱歉<br>
 
我这正好有个例子:<br>&nbsp; RPtValue &nbsp; &nbsp; =record<br>// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x,y:double;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Pt_id:integer;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;pt_value:single;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;pt_state:integer;<br>// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pt_unit:string[10];<br>&nbsp; end;<br><br>procedure TForm1.Button1Click(Sender: TObject);<br>var<br>&nbsp; hMap:THandle;<br>&nbsp; data,d:^RPtValue;<br>&nbsp; i:integer;<br>begin<br>&nbsp; hMap:=CreateFileMapping(-1,nil,PAGE_READONLY,0,1024,'SHARE_MEMORY');<br>&nbsp; if hMap=NULL then exit;<br>&nbsp; data:=Mapviewoffile(hMap,FILE_MAP_READ,0,0,0);<br>&nbsp; d:=data;<br>&nbsp; for i:=0 to 25 do<br>&nbsp; begin<br>&nbsp; &nbsp; memo1.Lines.Add(inttostr(d^.Pt_id)+':'+floattostr(d^.pt_value)+':'+inttostr(d^.pt_state));<br>&nbsp; &nbsp; inc(d);<br>&nbsp; end;<br>end;<br><br>procedure TForm1.Button2Click(Sender: TObject);<br>var<br>&nbsp; hFile:THandle;<br>&nbsp; hMapping:THandle;<br>&nbsp; data,d:^integer;<br>&nbsp; i:integer;<br>begin<br>&nbsp; hMapping:=CreateFileMapping(-1,nil,PAGE_READWRITE ,0,1024,pchar('SHARE_MEMORY'));<br>&nbsp; data:=MapViewOfFile(hMapping,FILE_MAP_WRITE,0,0,0);<br><br>&nbsp; &nbsp; d:=data;<br>&nbsp; for i:=0 to 25 do<br>&nbsp; begin<br>&nbsp; &nbsp; d^:=ord('a')+i;<br>&nbsp; &nbsp; inc(d);<br>&nbsp; end;<br><br>end;<br>
 
amao:<br>我用你的例子,下面这句出现编译错误:<br>hMap:=CreateFileMapping(-1,nil,PAGE_READONLY,0,1024,'SHARE_MEMORY');<br>错误信息:<br>26. Constant expression violates subrange bounds<br>我看了帮助,把-1改成0xFFFFFFFF,出错变为:<br>36. Not enough actual parameters<br>改成0就好了。我不知道这是怎么回事。<br><br>另外如果先运行Button1.Click,再运行Button2.Click就出错。<br>把PAGE_READONLY改成PAGE_READWRITE就可以了。
 
我还有个疑问:用CreateFileMapping创建的共享区,<br>是否需要释放?如何释放?<br>另外,我觉得用<br>hMap:=OpenFileMapping(FILE_MAP_READ,false,'SHARE_MEMORY');<br>if hMap=0 then exit;<br>来读取数据可能更好一些。<br>
 
Delphi的demos目录下有一个IpcDemos程序,写的极好,你可以看看,绝对受益非浅!<br>--别说你怕累!
 
呵呵,<br>不好意思,<br>咋天太急了,<br>忘了说明了,<br>button2.click是创建memfile,<br>button1.click是读memfile的内容。<br>第一个参数表示内存共享文件的一个句柄,<br>-1就是0xffffffff,<br>不过delphi中十六进制的数是这样表示的:$ffffffff.<br>
 
我看了CreateFileMapping的说明,也看了看IpcDemos,里面都没有提到<br>CreateFileMapping对应的释放过程,是不是就不需要释放?另外,能不<br>能在程序中动态调整它的大小?
 
cakk的答案写起来最简单
 
后退
顶部