参考了这位仁兄的做法,针对wpf做了修改:
http://www.cnblogs.com/speeding/archive/2004/10/24/56033.aspx
准备:
使用COPYDATA,WM_USER只能用于应用程序内部的通讯,跨进程用COPYDATA
public const int WM_COPYDATA = 0x004A;
查找目标发送窗体:
[DllImport("User32.dll", EntryPoint = "FindWindow")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
定义一个结构体
[StructLayout(LayoutKind.Sequential)]
public struct CopyDataStruct
{
public IntPtr dwData;
public int cbData;//字符串长度
[MarshalAs(UnmanagedType.LPStr)]
public string lpData;//字符串
}
发送消息方法
[DllImport("User32.dll", EntryPoint = "SendMessage")]
private static extern int SendMessage
(
IntPtr hWnd, //目标窗体句柄
int Msg, //WM_COPYDATA
int wParam, //自定义数值
ref CopyDataStruct lParam //结构体
);
封装方法:
/// <summary>
/// SendMessage To Window
/// </summary>
/// <param name="windowName">window的title,建议加上GUID,不会重复</param>
/// <param name="strMsg">要发送的字符串</param>
public static void SendMessage(string windowName, string strMsg)
{
if (strMsg == null) return;
IntPtr hwnd = FindWindow(null, windowName);
if (hwnd != IntPtr.Zero)
{
CopyDataStruct cds;
cds.dwData = IntPtr.Zero;
cds.lpData = strMsg;
//注意:长度为字节数
cds.cbData = System.Text.Encoding.Default.GetBytes(strMsg).Length + 1;
// 消息来源窗体
int fromWindowHandler = 0;
SendMessage(hwnd, WM_COPYDATA, fromWindowHandler, ref cds);
}
}
发送举例:
MessageHelper.SendMessage("PopupNotify_06f777cb-958e-4cfb-ba80-b311c8cf94e1",”MMessage”);
接收:
在MainWindow中注册Hook
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
(PresentationSource.FromVisual(this) as HwndSource).AddHook(new HwndSourceHook(this.WndProc));
}
接收消息:
IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == MessageHelper.WM_COPYDATA)
{
CopyDataStruct cds = (CopyDataStruct)System.Runtime.InteropServices.Marshal.PtrToStructure(lParam, typeof(CopyDataStruct));
MessageBox.Show(cds.lpData);
}
return hwnd;
}
另外:获取目标窗体的句柄时,可以先获取目标process,然后process.MainWIndowHandle就是目标窗体的句柄。但是如果MainWindow的ShowInTaskBar=false,这个办法就失效了,只能用FindWindow。