Wm_copydata message is used to transmit data between two processes.

Source: Internet
Author: User

Several methods for communication between processes:

In Windows, processes often need to exchange data for data communication. Common methods include:

Use memory ing files
Share memory through DLL
Use sendmessage to send the wm_copydata message to another process.

Compared with the previous two complex implementations, wm_copydata is undoubtedly a cost-effective method.

The main purpose of a wm_copydata message is to allow the transfer of read-only data between processes. During wm_copydata message transmission, Windows does not provide the inheritance synchronization mode. We recommend that you use the sendmessage function in the SDK documentation. The receiver does not return the message before the data copy is completed, so that the sender cannot delete or modify the data:

The prototype of this function and the structure to be used are as follows:

Sendmessage (hwnd, wm_copydata, wparam, lparam );
The hexadecimal number of wm_copydata is 0x004a.

Wparam is set to the handle of the window containing data. Lparam points to a copydatastruct structure:
Typedef struct tagcopydatastruct {
DWORD dwdata; // user-defined data
DWORD cbdata; // data size
Pvoid lpdata; // pointer to data
} Copydatastruct;
This structure is used to define user data.

The specific process is as follows:

First, find the receiver's handle using findwindow on the sender, and then send the wm_copydata message to the receiver.

The receiver processes the message in the defwndproc event. Because the Chinese encoding is two bytes, the length of the byte must be clear when the Chinese character is passed.

There is a proper amount of explanation in the Code. Please take a look.

Prerequisites for using wm_copydata:

1. Know the handle of the message receiving process.

2. The receiving message process reloads the wm_copydata message ing to respond to the message (otherwise, it is not the sender's self-Empathy ?)

After reading the premise, I came to the conclusion that it would be better to use wm_copydata between the two processes I wrote.

The following code lines illustrate everything.

The easiest way to obtain the handle is to use findwindow, find the window class, or name. If you think you are unsure of this, use setprop to mark the window .... (If you don't talk about this, you can get started)

OK, start to write the sending code:

Hwnd = findwindow (null, "MyApp ");

If (hwnd! = NULL)

{

Copydatastruct CPD;/* assign a value to the copydatastruct structure */

CPD. dwdata = 0;

CPD. cbdata = strlen ("string ");

CPD. lpdata = (void *) "string ";

: Sendmessage (hwnd, wm_copydatanull, (lparam) & CPD); // send!

/* It's over !! */

}

The receiving end reloads the on_wm_copydata message ing function (the following is what you want to add manually. You 'd better use classwizard)

Afx_msg bool oncopydata (cwnd * pwnd, copydatastruct * pcopydatastruct );

On_wm_copydata ()/* message ing */

Bool cmainframe: oncopydata (cwnd * pwnd, copydatastruct * pcopydatastruct)
{
Afxmessagebox (lpcstr) (pcopydatastruct-> lpdata);/* Indicates receiving a message using the dialog box */

Return cwnd: oncopydata (pwnd, pcopydatastruct );
}

There are other methods for Process Communication, which are relatively troublesome, but the limitations are smaller than wm_copydata. Of course, you can also register a message at both ends for communication.

A problem of using wm_copydata for inter-process communication

 

During development, data is sometimes required to be transmitted between processes. For example, if a program only allows a single instance to run, open the program again when an existing instance is running, you may need to pass information to the currently running instance for special processing. When a small amount of data is transmitted, the simplest thing is to use sendmessage to send the wm_copydata message. The wparam and lparam parameters can carry the relevant data. Because sendmessage is blocked, it will not be returned before the receiving data process completes data processing, and the sender will not delete or modify data. Therefore, this method is simple and secure, but the data volume cannot be too large, otherwise, the processing time is too long, leading to blocking and false positives.

Use sendmessage to send wm_copydata as follows:

 

 

Lresult = sendmessage (// returns lresult in lresult
(Hwnd) hwndcontrol, // handle to destination control
(Uint) wm_copydata, // Message ID
(Wparam) wparam, // = (wparam) () wparam;
(Lparam) lparam // = (lparam) () lparam;
);

 

Wparam is the window handle of the sender, and lparam is the pointer to a copydatastruct type struct, which contains transmitted data information. Copydatastruct is defined as follows:

Typedef struct tagcopydatastruct {
Ulong_ptr dwdata;
DWORD cbdata;
Pvoid lpdata;
} Copydatastruct, * pcopydatastruct;

Where, dwdata is the custom data, cbdata specifies the size of lpdata pointing to the data, and lpdata is the pointer to the data. As mentioned above, when using wm_copydata, you must ensure the read-only attribute of the data, that is, there cannot be other threads of the sender to rewrite the transmitted data. (This also explains why postmessage is not allowed to send wm_copydata, because the postmessage function is asynchronous. Note that because sendmessage is blocked, it is easy to cause a deadlock. You can use sendmessagetimeout instead .) In addition, if the transmitted data involves objects or system resources, you must ensure that the receiver can process them. resources such as HDC and hbitmap are invalid and belong to different processes.

In use, use findwindow and other APIs to find the receiver's window handle. In the receiver's program, add a response to the wm_copydata message.

A program written a few days ago used wm_copydata for inter-process communication, but the receiver could not receive messages. There is no problem with the window handle found during debugging, and there is no prompt to check msdn, which cannot be solved.

After reading some sample code, I found that the wparam and lparam parameters in my sendmessage call are both 0, because I just need to notify the receiving program through the wm_copydata message, no data is required. Try to change the two parameters to a non-empty value so that the receiver can receive the message. Conclusion: whether the wparam parameter is 0 has no effect, but the lparam parameter must be non-empty, that is, it must point to a valid copydatastruct struct.

Why? After checking some data, we found that the bottom layer of sendmessage (wm_copydata) is completed through file mapping. The general process is that the sender thread transmits data information according to the copydatastruct structure, data is replicated in the shared memory, and the receiver thread reads data from the shared memory for processing. Therefore, if the pointer to the copydatastruct structure is null, the process cannot be performed, so the receiver cannot receive the message.

An example of wm_copydata:

//////////////////////////////////////// //////////////////////////////////////// //////////////////////////////////////// //////////////////////////////////////// //////

//////////////////////////////////////// //////////////////////////////////////// //////////////////////////////////////// //////////////////////////////////////// //////

There are multiple methods for inter-process communication. For a small amount of data, wm_copydata can be used for convenient communication. (For a large amount of data, because sendmessage is blocked, only the receiver responds to the message, only sendmessage can be returned, otherwise it will be blocked all the time. Therefore, for a large amount of data, using sendmessage may easily cause the window to be suspended ).

In this example, wm_copydata is used to implement two data types: cstring and custom student:

//************************************** ********************

# Pragma pack (1)

Struct student {

Char ID [10];

Tchar name [20];

Uint age;

Uint grade;

Char room [5];

Char Tel [12];

};

# Pragma pack ()

//************************************** ********************

Because the oncopydata () function of the receiver needs to distinguish two different types of data sent. Therefore, the following two constants are defined:

# Define string 1

# Define STUDENT 2

 

 

Sender:

Void csenddatadlg: onbtsend () // implement cstring Data Transmission

{

Updatedata (true );

If (m_szdata.isempty ()){

M_szdata = _ T ("hello ");

Updatedata (false );

}

// M_szdata + = '\ 0 ';

Hwnd hwndrcv =: findwindow (null, "Cycler ");

If (hwndrcv = NULL ){

Afxmessagebox (_ T ("unable to find the Receiving Window, failed to send "));

Return;

}

Copydatastruct CPD;

CPD. dwdata = string; // The flag is of the cstring type.

CPD. cbdata = m_szdata.getlength () + 1;

// Getlength () is only the length of the actual character, not including '\ 0 '.

CPD. lpdata = (void *) m_szdata.getbuffer (CPD. cbdata );

: Sendmessage (hwndrcv, wm_copydata, (wparam) This-> m_hwnd, (lparam) & CPD );

M_szdata.releasebuffer ();

Afxmessagebox (_ T ("sent successfully "));

}

Void csenddatadlg: onbtstu () // implement student Data Transmission

{

Updatedata ();

M_szid + = '\ 0 ';

M_szname + = '\ 0 ';

M_szrom + = '\ 0 ';

M_sztel + = '\ 0 ';

M_pstu = new student ();

Strcpy (m_pstu-> ID, m_szid.getbuffer (m_szid.getlength ()));

_ Tcscpy (m_pstu-> name, m_szname.getbuffer (m_szname.getlength ()));

Strcpy (m_pstu-> room, m_sroom.getbuffer (m_sroom.getlength ()));

Strcpy (m_pstu-> Tel, m_sztel.getbuffer (m_sztel.getlength ()));

M_szid.releasebuffer (); m_szname.releasebuffer ();

M_srorom.releasebuffer (); m_sztel.releasebuffer ();

M_pstu-> age = m_nage;

M_pstu-> grade = m_ngrade;

Hwnd hwndrcv =: findwindow (null, "Cycler ");

If (hwndrcv = NULL ){

Afxmessagebox (_ T ("unable to find the Receiving Window, failed to send "));

Return;

}

Copydatastruct CPD;

CPD. dwdata = student; // The flag is of the student type.

CPD. cbdata = sizeof (student );

CPD. lpdata = (pvoid) m_pstu;

: Sendmessage (hwndrcv, wm_copydata, (wparam) This-> m_hwnd, (lparam) & CPD );

Delete m_pstu;

Afxmessagebox (_ T ("sent successfully "));

}

Receiver:

In the oninitdialog method:

//************************************** *************************

// Initialize the listctrl Control

Lvcolumn column;

Column. Mask = lvcf_text | lvcf_subitem | lvcf_width;

Column. Cx = 80;

Column. isubitem = 0;

Column. psztext = _ T ("ID ");

M_listctl.insertcolumn (0, & Column );

Column. Cx = 80;

Column. psztext = _ T ("name ");

Column. isubitem = 1;

M_listctl.insertcolumn (1, & Column );

Column. Cx = 55;

Column. psztext = _ T ("Age ");

Column. isubitem = 2;

M_listctl.insertcolumn (2, & Column );

Column. Cx = 55;

Column. psztext = _ T ("Grade ");

Column. isubitem = 3;

M_listctl.insertcolumn (3, & Column );

Column. Cx = 55;

Column. psztext = _ T ("room ");

Column. isubitem = 4;

M_listctl.insertcolumn (4, & Column );

Column. Cx = 80;

Column. psztext = _ T ("tel ");

Column. isubitem = 5;

M_listctl.insertcolumn (5, & Column );

 

 

 

 

 

Bool creceiverdlg: oncopydata (cwnd * pwnd, copydatastruct * pcopydatastruct)

{

Switch (pcopydatastruct-> dwdata) {// The cstring type is received

Case string:

M_szdata + = (lpcstr) (pcopydatastruct-> lpdata );

Updatedata (false );

Break;

Case Student: // The student type is received.

Cstring ID, name, room, Tel;

Uint age, grade;

Cstring STR;

Student * pstu = (student *) (pcopydatastruct-> lpdata );

Id = pstu-> ID;

Name = pstu-> name;

Room = pstu-> room;

Tel = pstu-> Tel;

Age = pstu-> age;

Grade = pstu-> grade;

Lvitem item;

// Display the received data to the listctrl control.

Item. Mask = lvif_text;

Int n = m_listctl.getitemcount ();

Item. iItem = N;

Item. isubitem = 0;

Item. psztext = ID. getbuffer (Id. getlength ());

Id. releasebuffer ();

M_listctl.insertitem (& item );

M_listctl.setitemtext (n, 1, name );

Str. Format ("% d", age );

M_listctl.setitemtext (n, 2, STR );

Str. Format ("% d", grade );

M_listctl.setitemtext (n, 3, STR );

M_listctl.setitemtext (n, 4, room );

M_listctl.setitemtext (n, 5, TEL );

Updatedata (false );

// Delete pstu;

Break;

}

// Return cdialog: oncopydata (pwnd, pcopydatastruct );

Return true;

}

 

The msdn help contains an example of the message, which is also clear.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.