c++builder利用wm_copydata消息在不同程序间传数据...
时间:2010-08-06 来源:luoshupeng
C++Builder利用WM_COPYDATA消息在不同程序间传数据
罗树鹏 2010-8-7
WM_COPYDATA消息就是为了从一个应用程序向另外一个应用程序传递数据。其用法是使用SendMessage将消息发送到目的应用程序,消息原型为:
SendMessage(
(HWND) hWnd, // handle to destination window
WM_COPYDATA, // message to send
(WPARAM) wParam, // handle to window (HWND)
(LPARAM) lParam // data (PCOPYDATASTRUCT)
);
参数说明:
hWnd是接收数据的窗口句柄,即目的应用程序句柄
wParam是发送数据的窗口句柄,即源应用程序句柄
lParam是指向COPYDATASTRUCT结构体的一个指针,在此结构体数据中包含了要被传递的数据
如果接收应用程序处理了此消息,则返回TRUE;否则将会返回FALSE。
这里要注意的是发送此消息只能使用SendMessage,不能使用PostMessage。
接下来就要说说如何把要被传递的数据绑定到COPYDATASTRUCT结构体上了,即如何为COPYDATASTRUCT结构体赋值的问题。首先看看COPYDATASTRUCT结构体的定义:
typedef struct tagCOPYDATASTRUCT {
ULONG_PTR dwData;
DWORD cbData;
PVOID lpData;
} COPYDATASTRUCT, *PCOPYDATASTRUCT;
参数说明:
dwData指定被传递数据的标识
cbData是用位表示的被传递数据的长度
lpData是被传递数据的指针,此参数可以为NULL
我们只需要把需要传递的数据的地址赋值给lpData并且设定好被传递数据的长度,然后使用SendMessage发送消息即完成了发送,在接收方接收来自WM_COPYDATA消息的数据即完成了在不同应用程序间数据的传递。
下面是我使用BCB6.0这个IDE做的一个例子,希望能给大家做一点说明。
程序一,发送方:
1.头文件
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//自定义结构体 要传递的数据
typedef struct
{
int a;
int b;
//AnsiString str;
}TS;
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
void __fastcall Button1Click(TObject *Sender);
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
2.实现文件
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//------------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
HANDLE fm;
fm = FindWindow(NULL,"TestForm");
TS a;
a.a = 12;
a.b = 13;
//a.str = "Hello";
COPYDATASTRUCT cds;
if (fm != NULL)
{
cds.dwData = 0;
cds.cbData = sizeof(a);
cds.lpData = (void *)&a;
SendMessage(fm,WM_COPYDATA,0,(LPARAM)&cds);
}
}
//---------------------------------------------------------------------------
程序二,接收方:
1.头文件
//---------------------------------------------------------------------------
#ifndef TestFormH
#define TestFormH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include "trayicon.h"
//自定义结构体 与发送方定义的要一致
typedef struct
{
int a;
int b;
//AnsiString str;
}TS;
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TMemo *mmo1;
TTrayIcon *TrayIcon1;
private: // User declarations
public: // User declarations
void __fastcall OnCopyData(TMessage &msg);
__fastcall TForm1(TComponent* Owner);
BEGIN_MESSAGE_MAP
VCL_MESSAGE_HANDLER(WM_COPYDATA,TMessage,OnCopyData);
END_MESSAGE_MAP(TForm)
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
2.实现文件
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "TestForm.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "trayicon"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
this->Caption = "TestForm";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OnCopyData(TMessage &msg)
{
bool flag = false ;
if ( msg.Msg == WM_COPYDATA )
{
COPYDATASTRUCT* pCopyData = (COPYDATASTRUCT* )msg.LParam ;
int dataLen = pCopyData->cbData ;
TS *a;
a = (TS *)pCopyData->lpData;
mmo1->Lines->Add(a->a);
mmo1->Lines->Add(a->b);
//mmo1->Lines->Add(a->str);
flag = true ;
}
if (!flag)
{
TForm::WndProc(msg);
}
}
//------------------------------------------------------------------------------
总结一下:
发送WM_COPYDATA消息只能用SendMessage而不能用PostMessage,原因是WM_COPYDATA发送的数据是以内存映射文件形式发送的,用PostMessage后内存映射文件的句柄就无失效了,会造成数据丢失。
被传递的数据中不能带有对象的指针或引用之类的指针型数据,否则这些数据不会被接收应用程序获取到。
被传递的数据在传递过程中,它不能被发送应用程序修改。
接收方认为被传递的数据是只读的,lParam只在消息处理函数中可见,因此接收应用程序不应该释放lParam所占用的程序空间。如果接收应用程序需要在消息处理函数返回后再对传递的数据有处理,可以把传递数据复制到本地的缓冲区中。