如何向别的窗口发消息(300分)

  • 主题发起人 主题发起人 cw2
  • 开始时间 开始时间
C

cw2

Unregistered / Unconfirmed
GUEST, unregistred user!
要向另一个程序发送一个字符串,怎么实现?
我用下面的代码,出现access violation错误:
send:
msg := '1234';
PostMessage(handle2, WM_MYMESSAGE, 0, integer(@msg));
receive:
smsg: string;
smsg := strpas(pchar(msg.LParam));
谢谢!
 
消息的处理函数的定义
MyMessageControl(WPARAM wParam,LPARAM lParam)
{
LPCTSTR lpstr=(LPCTSTR)wParam;
//得到传来的字符串
add another controls
....................
}
发消息:
CString strMessage;
PostMessage(hWnd2,WM_MYMESSAGE,(LPCTSTR)strMessage,NULL);
这是VC的写法,可适当修改成Delphi的
 
用WM_COPYDATA
 
用Delphi实现程序间的数据传递
西安市西北电力设计院计算机处
王靖
---- [本文为摘略,全文可下载,Zip 14 KB]
---- 在实际应用中,我们经常需要多个程序相互配合来完成某些特定功能。例如两个应用程序间的同步、互斥;
应用程序在起第二份实例时的参数自动传递…。要实现这些功能,就必须能实现程序间的数据传递。
---- 有些特殊的高级技术可在不同的程序间传递数据,如剪贴板、动态数据交换以及OLE自动化,但有条件限制
并且相对较复杂。这里,我介绍三种有效的底层技术,希望对编程爱好者有所帮助。
利用WM_COPYDATA消息
---- 使用该消息涉及一个TcopyDataStruct结构类型的指针。该结构中有三个成员:
dwData 是一个32位的附加参数
cbData 表示要传递的数据区的大小
lpData 表示要传递的数据区的指针
---- 下面举个例子。该例子由两个程序构成,分别为SendData和GetData。
---- SendData程序向GetData程序发送消息,并传递edit1中的字符串;GetData在收到消息后,把SendData发送的字符串接受下来,并显示在相应的edit1中。
---- 1. SendData程序:
... ...
---- 2. GetData程序:
... ...
---- 使用这种方法是WIN32应用程序进行交互的最简单的方法。
使用全局原子
---- Win32系统中,为了实现信息共享,系统维护了一张全局原子表。每个原子中存放了一些共享数据。关于对原子的操作,有一组专门的API函数:
GlobalAddAtom 在表中增加全局原子
GlobalDeleteAtom 在表中删除全局原子
GlobalFindAtom 在表中搜索全局原子
GlobalGetAtomName 从表中获取全局原子
---- 笔者用这种方法实现了避免程序二次启动,但把第二次启动所带的参数传到第一个实例中以进行相应的处理的程序。基本处理如下:
... ...

---- 在相应的窗口单元dde.pas增加对自定义消息WM_MYMESSAGE的处理:
... ...

使用存储映象文件
---- 这种方法相对较复杂一些。当Win95与Winows Nt向内存中装载文件时,使用了特殊的全局内存区。在该区域内,应用程序的虚拟内存地址和文件中的相应位置一一对应。由于所有进程共享了一个用于存储映象文件的全局内存区域,因而当两个进程装载相同模块(应用程序或DLL文件)时,它们实际可以在内存中共享其执行代码。
---- 笔者通过调用一个带有特殊参数的CreateFileMapping函数,来间接达到程序间共享内存的目的。下面简要解释一下该函数。
HANDLE CreateFileMapping(
HANDLE hFile, //文件句柄
LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
// 可选安全属性
DWORD flProtect, // 映象文件保护方式
DWORD dwMaximumSizeHigh, // 映象文件区域的底值
DWORD dwMaximumSizeLow, // 映象文件区域的顶值
LPCTSTR lpName // 映象文件的名字
);

... ...

---- 以下举例说明:
... ...

---- 用这种方法,不但可以在不同的程序之间共享数据,还可以在同一程序的不同实例间共享数据。为了及时通知其它进程共享数据的变化,可以自定义一条用户消息,通过发消息来实现,这里不再赘述。
---- 利用以上三种方法均可以有效地实现数据传递、共享,所有的例子程序均在Delphi 3.0,4.0下调试通过。
 
到哪下载?
 
不同进程之间是不同的地址空间,不能用指针。
你的字符串比较短(小于255字节)可以在本进程GlobalAddAtom,
把ATOM发给对方,对方GlobalGetAtomName、 GlobalDeleteAtom
或者用 WM_COPYDATA
COPYDATASTRUCT.dwData 自己随便给的id号,对方得到id号有什么用是你自己定的
cbData 是数据长度
lpData 指向要发的数据的buffer
 
其实还是o*o的方法好,用wm_copydata比较简单。
 
<a href="http://www.ccw.com.cn/99/tips/9906/060702-05.zip">到这儿下载</a>
 
WM_COPYDATA怎么用?
给个例子吧
 
youproject.dpr
var
MyWindow: THandle;
CDS: TCopyDataStruct;
s: PChar;

begin
MyWindow := FindWindow('TMXMainForm', nil);
if (MyWindow > 0) and (ParamCount > 0) then
begin
s := PChar(ExpandToFullPath(ParamStr(1)));
FillChar(CDS, SizeOf(TCopyDataStruct), #0);
CDS.cbData := StrLen(s) + 1;
CDS.lpData := s;
SendMessage(MyWindow, WM_COPYDATA, 0, LParam(@CDS));
Halt;
end;

yourmaiform.pas
public
procedure WMCopyData(var msg: TWMCopyData);
message WM_COPYDATA;

procedure TMXMainForm.WMCopyData(var msg: TWMCopyData);
begin
OpenFile(String(PChar(msg.CopyDataStruct^.lpData)));
end;
 
如果在同一个进程内部可以用你的方法,不在同一个进程用WM_COPYDATA着是微软的
解决方法,因为一个进程不能访问另一个进程的内存。
 
请问SuperMMX,调用OpenFile(String(PChar(msg.CopyDataStruct^.lpData))以后,怎么知道传过来的是什么? 谢谢!
 
COPYDATASTRUCT.dwData 可以设定一些数字,每个数字表示什么是自己定的,
接收后根据这个值可以确定传过来的数据是什么
 
可以进行类型转换, 随你的便
 
每一个应用程序都有自己的消息循环,所以想要给其它的应用程序发送消息就需要通过
FindWindow或EnumWindows函数得到其句柄,然后再使用SendMessage或者PostMessage
向其发送消息。
 
多人接受答案了。
 

Similar threads

I
回复
0
查看
588
import
I
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
后退
顶部