【小沐学C++】C++实现进程通信(WM_COPYDATA,MFC,C#)

10 篇文章 6 订阅
5 篇文章 0 订阅

1、简介

当应用程序将数据传递给另一个应用程序时发送此消息。
This message is sent when an application passes data to another application.

应用程序必须使用SendMessage函数来发送此消息,而不是PostMessage函数。传递的数据不得包含指向接收数据的应用程序无法访问的对象的指针或其他引用。在发送此消息时,所引用的数据不得被发送进程的另一个线程更改。

接收应用程序应将数据视为只读。在个人通讯装置参数仅该消息的处理过程中是有效的。接收应用程序不应释放pcds引用的内存。如果接收应用程序必须在SendMessage返回后访问数据,它必须将数据复制到本地缓冲区中。

通过消息实现进程间通信有如下两种方法:
(1)另一种是通过使用WM_COPYDATA消息进行进程间的通信。
(2)一种通过自定义消息进行进程间的通信.

2、WM_COPYDATA消息通信(C++)

2.1 功能描述

https://docs.microsoft.com/en-us/previous-versions/aa928292(v=msdn.10)?redirectedfrom=MSDN

WM_COPYDATA
wParam = (WPARAM)(HWND) hwnd;
lParam = (LPARAM)(PCOPYDATASTRUCT) pcds;

可以通过工具Spy++获取目标窗口的标题文本和窗口类名。
在这里插入图片描述

  • 发送端部分
LPCTSTR lpszString = ...;
COPYDATASTRUCT cds;
cds.dwData = 1; // can be anything
cds.cbData = sizeof(TCHAR) * (_tcslen(lpszString) + 1);
cds.lpData = lpszString;
SendMessage(hwnd, WM_COPYDATA, (WPARAM)hwnd, (LPARAM)(LPVOID)&cds);
  • 接收端部分
COPYDATASTRUCT* pcds = (COPYDATASTRUCT*)lParam;
if (pcds->dwData == 1)
{
    LPCTSTR lpszString = (LPCTSTR)(pcds->lpData);
    // do something with lpszString...
}

2.2 发送端

//***********************************************************************
//   Purpose:   MFC实现WM_COPYDATA进程通信(发送端部分)
//   Author:    爱看书的小沐
//   Date:      2022-4-29
//   Languages: VC++、MFC
//   Platform:  Visual Studio 2017
//   OS:        Win10 win64
// ***********************************************************************

void CDlgSendMessage::OnBnClickedButtonSend()
{
	USES_CONVERSION;

	CString strReceiveWndTitle;
	CString strReceiveClassName;
	CString strMsg;

	GetDlgItemText(IDC_EDIT_WIN_NAME, strReceiveWndTitle);
	GetDlgItemText(IDC_EDIT_CLASS_NAME, strReceiveClassName);
	GetDlgItemText(IDC_EDIT_MSG, strMsg);

	HRESULT hResult = 0;
	HWND hWndReceive = ::FindWindow(strReceiveClassName.GetBuffer(), strReceiveWndTitle.GetBuffer());
	if (hWndReceive != NULL && ::IsWindow(hWndReceive))
	{
		COPYDATASTRUCT cdsSend;
		cdsSend.dwData = 0;
		cdsSend.cbData = strMsg.GetLength() * sizeof(TCHAR);
		cdsSend.lpData = (void*)strMsg.GetBuffer();
		hResult = ::SendMessage(hWndReceive, WM_COPYDATA, (WPARAM)(AfxGetApp()->m_pMainWnd), (LPARAM)&cdsSend);
	}

	strReceiveWndTitle.ReleaseBuffer();
	strReceiveClassName.ReleaseBuffer();
	strMsg.ReleaseBuffer();
}

2.2 接收端

//***********************************************************************
//   Purpose:   MFC实现WM_COPYDATA进程通信(接收端部分)
//   Author:    爱看书的小沐
//   Date:      2022-4-29
//   Languages: VC++、MFC
//   Platform:  Visual Studio 2017
//   OS:        Win10 win64
// ***********************************************************************

BEGIN_MESSAGE_MAP(CDlgSendMessage, CDialogEx)
	ON_BN_CLICKED(IDC_BUTTON_SEND, &CDlgSendMessage::OnBnClickedButtonSend)
	ON_WM_CTLCOLOR()
	ON_WM_COPYDATA()
END_MESSAGE_MAP()

BOOL CDlgSendMessage::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
	if (pCopyDataStruct->cbData > 0)
	{
		TCHAR recvData[1024] = { 0 };
		memcpy(recvData, (TCHAR*)pCopyDataStruct->lpData, pCopyDataStruct->cbData);
		CString str;
		str.Format(_T("%s"), recvData);
		SetDlgItemText(IDC_EDIT_LOG, str);
	}

	return CDialogEx::OnCopyData(pWnd, pCopyDataStruct);
}

运行界面截图如下:
在这里插入图片描述

3、WM_COPYDATA消息通信(C#)

3.1 结构体定义

CommonApi.cs:

//***********************************************************************
//   Purpose:   C#实现WM_COPYDATA进程通信(公共代码部分)
//   Author:    爱看书的小沐
//   Date:      2022-4-29
//   Languages: C#
//   Platform:  Visual Studio 2017
//   OS:        Win10 win64
// ***********************************************************************

using System;
using System.Runtime.InteropServices;

namespace WindowsFormsApp4
{
    public class CommonApi
    {
        [DllImport("user32.dll", EntryPoint = "FindWindow")]
        public extern static IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("User32.dll")]
        public static extern int SendMessage(IntPtr hwnd, int msg, int wParam, ref COPYDATASTRUCT lParam);

        public const int WM_COPYDATA = 0x004A;

        /// <summary>
        /// WM_COPYDATA消息,进程间传输信息的固定结构
        /// </summary>
        public struct COPYDATASTRUCT
        {
            public IntPtr dwData;
            public int cbData;

            [MarshalAs(UnmanagedType.LPStr)]
            public string lpData;
    }
}

3.2 发送端

//***********************************************************************
//   Purpose:   C#实现WM_COPYDATA进程通信(发送端部分)
//   Author:    爱看书的小沐
//   Date:      2022-4-29
//   Languages: C#
//   Platform:  Visual Studio 2017
//   OS:        Win10 win64
// ***********************************************************************

using System;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApp4
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            string className = txtReceiveWinClass.Text;
            string captionName = txtReceiveWinCaption.Text;
            string message = txtMessage.Text;
            IntPtr hWndReceive = CommonApi.FindWindow(className, captionName);

            if (hWndReceive != IntPtr.Zero)
            {
                byte[] arr = Encoding.Default.GetBytes(message);
                CommonApi.COPYDATASTRUCT cds;
                cds.dwData = IntPtr.Zero;  
                cds.cbData = arr.Length + 1;
                cds.lpData = message;

                CommonApi.SendMessage(hWndReceive, CommonApi.WM_COPYDATA, 0, ref cds);
            }
        }
    }
}    

运行结果如下:
在这里插入图片描述

3.3 接收端

//***********************************************************************
//   Purpose:   C#实现WM_COPYDATA进程通信(接收端部分)
//   Author:    爱看书的小沐
//   Date:      2022-4-29
//   Languages: C#
//   Platform:  Visual Studio 2017
//   OS:        Win10 win64
// ***********************************************************************

using System;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApp4
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        protected override void DefWndProc(ref System.Windows.Forms.Message message)
        {
            switch (message.Msg)
            {
                case CommonApi.WM_COPYDATA:
                    ReadCopyDataMessage(ref message);
                    break;
                default:
                    base.DefWndProc(ref message);
                    break;
            }
        }

        private void ReadCopyDataMessage(ref System.Windows.Forms.Message m)
        {
            CommonApi.COPYDATASTRUCT cdata = new CommonApi.COPYDATASTRUCT();
            Type mytype = cdata.GetType();
            cdata = (CommonApi.COPYDATASTRUCT)m.GetLParam(mytype);
            string msg = cdata.lpData;
            MessageBox.Show(msg);
        }
    }
}

运行结果如下:
在这里插入图片描述
在这里插入图片描述

3、自定义消息通信

3.1 功能描述

消息分为两种,一种是系统已经定义的消息,另一种是用户自定义的消息。系统已经定义的消息是从0到0x3ff,用户自定义的消息可以从0x400开始。系统中提供了一个宏WM_USER,在进行自定义消息时,在WM_USER的基础上加一个值就可以了。
在这里插入图片描述

3.2 示例说明

#define WM_MY_MSG WM_USER + 1
afx_msg LRESULT OnUserAdo(WPARAM wParam, LPARAM lParam);
BEGIN_MESSAGE_MAP(CRenderView, CView)
ON_MESSAGE(WM_MY_MSG , OnUserAdo)
END_MESSAGE_MAP()
LRESULT CRenderView::OnUserAdo(WPARAM wParam, LPARAM lParam)
{
	AdoDbParam* pParam = (AdoDbParam *)lParam;

	return 0;
}

结语

如果您觉得该方法或代码有一点点用处,可以给作者点个赞,或打赏杯咖啡;╮( ̄▽ ̄)╭
如果您感觉方法或代码不咋地//(ㄒoㄒ)//,就在评论处留言,作者继续改进。o_O???
如果您需要相关功能的代码定制化开发,可以私聊留言作者。(✿◡‿◡)
感谢各位童鞋们的支持!( ´ ▽´ )ノ ( ´ ▽´)っ!!!

在这里插入图片描述

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Delphi获取WM_COPYDATA消息的方法如下: 1. 首先需要创建一个窗口来接收这个消息。可以使用TForm或TApplication等Delphi窗口类来创建窗口。 2. 在窗口类中,重写WndProc方法。WndProc方法是窗口消息处理程序,用于接收和处理所有窗口消息,包括WM_COPYDATA消息。 3. 在WndProc方法中,判断接收到的消息类型是否为WM_COPYDATA消息。如果是,则通过指针参数lpCopyDataStruct获取传递过来的数据。lpCopyDataStruct是一个指向COPYDATASTRUCT结构体的指针,里面包含了传递过来的数据。 4. 在获取到数据之后,就可以对其进行处理了。处理方式根据具体需求而定,可以将数据显示在窗口上,或者进行其他操作。 示例代码: interface type TForm1 = class(TForm) private { Private declarations } procedure WMCopyData(var Msg: TWMCopyData); message WM_COPYDATA; public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.WMCopyData(var Msg: TWMCopyData); var CopyDataStruct: PCOPYDATASTRUCT; begin CopyDataStruct := Msg.CopyDataStruct; if (CopyDataStruct^.dwData = 12345) then //假设这里传递的是一个整数型数据,值为12345 begin //处理传递过来的数据 end; end; end. 在上面的示例代码中,当接收到WM_COPYDATA消息时,会判断传递过来的数据是否为整数型数据,并进行相应处理。在实际应用中,可以根据具体情况来修改代码,实现自己想要的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值