参考了两篇文章,写得很好。感谢。
python https://blog.csdn.net/ndd1996/article/details/107882856
C# https://blog.csdn.net/liang08114/article/details/108644659
# -*- codeing = utf-8 -*-
# @Time : 2022/5/17 11:30
# @Author: CXZ
# @Flie : received.py
# @Software: PyCharm
import threading
import time
import ctypes
import ctypes.wintypes
import win32api
import win32con
import win32gui
class COPYDATASTRUCT(ctypes.Structure):
_fields_ = [
('dwData', ctypes.wintypes.LPARAM),
('cbData', ctypes.wintypes.DWORD),
('lpData', ctypes.c_void_p)
]
PCOPYDATASTRUCT = ctypes.POINTER(COPYDATASTRUCT)
class EndOfTime(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
while 1:
print(1)
time.sleep(3)
class Listener:
def __init__(self):
WindowName ="CopyDataName" #class name
message_map = {
win32con.WM_COPYDATA: self.OnCopyData
}
wc = win32gui.WNDCLASS()
wc.lpfnWndProc = message_map
wc.lpszClassName = WindowName
hinst = wc.hInstance = win32api.GetModuleHandle(None)
classAtom = win32gui.RegisterClass(wc) #把上面的class name 等相关参数注册 再传入到下面的CreateWindow
self.hwnd = win32gui.CreateWindow( #这里是python 创建窗体用的
classAtom,
"WMSGReceiver1", #这个是窗体name
0,
0,
0,
win32con.CW_USEDEFAULT,
win32con.CW_USEDEFAULT,
0,
0,
hinst,
None
)
print("当前句柄", self.hwnd)
def OnCopyData(self, hwnd, msg, wparam, lparam):
pCDS = ctypes.cast(lparam, PCOPYDATASTRUCT)
s = ctypes.string_at(pCDS.contents.lpData).decode()
print(f"收到来自句柄{hwnd}的消息:{s}")
return 1
l = Listener()
win32gui.PumpMessages()
上面是接收端的python代码 直接可用 是上面参考python博客的基础上做些注脚
# -*- codeing = utf-8 -*-
# @Time : 2022/5/17 15:44
# @Author: CXZ
# @Flie : send.py
# @Software: PyCharm
import ctypes.wintypes
import win32con
FindWindow = ctypes.windll.user32.FindWindowW
SendMessage = ctypes.windll.user32.SendMessageW
class COPYDATASTRUCT(ctypes.Structure):
_fields_ = [
('dwData', ctypes.wintypes.LPARAM),
('cbData', ctypes.wintypes.DWORD),
('lpData', ctypes.c_char_p)
]
# 通过寻找窗口名获取句柄
#hwnd = FindWindow('CopyDataName', None)
hwnd = FindWindow(None, 'WMSGReceiver')#第一个参数是class name 第二个是窗体应用name
# 或者直接根据句柄来发送
# hwnd = 1707560
cds = COPYDATASTRUCT()
cds.dwData = 0
msg = "22233311"
msg_bytes = msg.encode('utf-8')
cds.cbData = ctypes.sizeof(ctypes.create_string_buffer(msg_bytes))
cds.lpData = ctypes.c_char_p(msg_bytes)
SendMessage(hwnd, win32con.WM_COPYDATA, 0, ctypes.byref(cds))
print("已发送CopyData数据", msg)
print(hwnd)
发送端python代码
下面是C# 的代码 也是直接可以用 点击button1 会发送message 发送成功 label1会对应变成hello 发送失败变成hello2 看对应的代码很简单。 当其他程序发送信息过来,成功的话,就会在textbox上面显示。个人觉得整个过程中需要注意的地方是怎么找到对应的句柄。一个是通过classname 一个是通过windowsname 这个是窗体应用名字 如果是通过windowsname 那就会自顶层往下找,看有没有对得上号的窗体名。如果有填classname的信息 那优先是配对classname信息。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[DllImport("user32.dll", EntryPoint = "FindWindow")]
private 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;
string FormText = "WMSGReceiver1";
//IntPtr hdl = FindWindow(null, FormText);
IntPtr hdl = FindWindow("CopyDataName", null);
private void button1_Click(object sender, EventArgs e)
{
//string ClassName = "WindowsForms10.Window.8.app.0.3ee13a2_r13_ad1";
// string FormText = "WMSGReceiver1";
//IntPtr hdl = FindWindow(null, FormText);
//IntPtr hdl = FindWindow("CopyDataName",null);
if (hdl != IntPtr.Zero)
{
string msg = "asdf";
byte[] sarr = Encoding.Default.GetBytes(msg);
COPYDATASTRUCT cds;
cds.dwData = IntPtr.Zero; //可以是任意值
cds.cbData = sarr.Length + 1; //指定lpData内存区域的字节数
cds.lpData = msg; //发送给目标窗口所在进程的数据
SendMessage(hdl, WM_COPYDATA, 0, ref cds);
label1.Text = "hello";
return;
}
label1.Text = "Hello2";
}
private void label1_Click(object sender, EventArgs e)
{
}
#region Windows Form Designer generated code
[STAThread]
protected override void DefWndProc(ref
System.Windows.Forms.Message m)
{
switch (m.Msg)
{
//接收自定义消息 USER,并显示其参数
case WM_COPYDATA:
COPYDATASTRUCT mystr = new COPYDATASTRUCT();
Type mytype = mystr.GetType();
mystr = (COPYDATASTRUCT)m.GetLParam(mytype);
this.textBox1.Text = mystr.lpData;
break;
default:
base.DefWndProc(ref m);
break;
}
}
/// <summary>
/// WM_COPYDATA消息,进程间传输信息专用结构
/// </summary>
public struct COPYDATASTRUCT
{
public IntPtr dwData;
public int cbData;
[MarshalAs(UnmanagedType.LPStr)]
public string lpData;
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
}
}
#endregion```