進程通信-SendMessage的使用方法
用過SendMessage進行進程通信的同學都知道,這個函數一般都搭配FindWindow使用。通過FindWindow查找進程句柄,然后使用SendMessage 向這個句柄發送信息。這接口使用起來比較簡單,但是當初也是費了好大的勁,只為用作記錄。
第一步:設計用戶界面
用戶界面需要有一下幾個元素,設置本地的窗口名稱,目標的窗口名稱,發送數據,以及接受數據。
第二步:引用接口
//Win32 API函數
[DllImport("User32.dll", EntryPoint = "SendMessage")]
private static extern int SendMessage(int hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);
[DllImport("User32.dll", EntryPoint = "FindWindow")]
private static extern int FindWindow(string lpClassName, string lpWindowName);
const int WM_COPYDATA = 0x004A;
public struct COPYDATASTRUCT
{
public IntPtr dwData;
public int cbData;
[MarshalAs(UnmanagedType.LPStr)]
public string lpData;
}
當初做的時候,將WM_COPYDATA 改為其他值,像c++ 一樣,我只需要通過消息定義為WM_USER+1 即可向該消息發送數據。但是做的時候,發現不對,剛接觸c# 不知道是我哪里理解不對還是怎么。改成其他值不行的。只能設置成0x004A;
第三步:發送消息
private void buttonSend_Click(object sender, EventArgs e)
{
string wndName = textBoxDestWindowName.Text;
string message = textBoxSendData.Text;
int hWnd = FindWindow(null, wndName);
if(hWnd != 0)
{
byte[] sarr = System.Text.Encoding.Default.GetBytes(message);
int len = sarr.Length;
COPYDATASTRUCT cds;
cds.dwData = (IntPtr)Convert.ToInt16(1);//可以是任意值
cds.cbData = len + 1;//指定lpData內存區域的字節數
cds.lpData = message;//發送給目標窗口所在進程的數據
SendMessage(hWnd, WM_COPYDATA, 0, ref cds);
}
}
第四步:接受消息
protected override void DefWndProc(ref Message m)
{
switch (m.Msg)
{
case WM_COPYDATA:
COPYDATASTRUCT cds = new COPYDATASTRUCT();
Type t = cds.GetType();
cds = (COPYDATASTRUCT)m.GetLParam(t);
string strResult = cds.lpData;
string strType = cds.dwData.ToString();
RecvOneDataPacket(strResult, strType);
break;
default:
base.DefWndProc(ref m);
break;
}
}
private void RecvOneDataPacket(string strResult, string strType)
{
//throw new NotImplementedException();
listBoxRecv.Items.Add(strResult);
}
這個接口在當初做的時候,老是出錯,就在這個地方。
cds = (COPYDATASTRUCT)m.GetLParam(t);
我也不知道為什么,也許是因為消息值的定義吧。不清楚,反正以后得注意了。
代碼地址:https://github.com/liningg/sendmessage