WPF應用程序使用SendMessage實現進程間通信(含示例代碼)
1.函數定義
使用WPF框架的C#窗體應用程序可以使用SendMessage方法實現進程間通信,SendMessage屬於Windows API宏,可以將指定的消息發送到一個或多個窗口,直到窗口程序處理完消息再返回,和PostMessage方法不同,PostMessage是將一個消息寄送到一個線程的消息隊列後就立即返回。
2.函數原型
SendMessage的函數原型爲:
LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam)
參數定義爲:
hWnd:其窗口程序將接收消息的窗口的句柄。如果此參數爲HWND_BROADCAST,則消息將被髮送到系統中所有頂層窗口,包括無效或不可見的非自身擁有的窗口、被覆蓋的窗口和彈出式窗口,但消息不被髮送到子窗口。
Msg:指定被髮送的消息。
wParam:指定附加的消息特定信息。
IParam:指定附加的消息特定信息。
返回值:返回值指定消息處理的結果,依賴於所發送的消息。
3.可能需要的引用
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
// 導出SendMessage函數
[DllImport("User32.dll",EntryPoint = "SendMessage")]
private static extern intSendMessage(IntPtr hWnd, int Msg, IntPtrwParam, ref COPYDATASTRUCTlParam);
// 導出FindWindow函數,用於找到目標窗口所在進程
[DllImport("User32.dll",EntryPoint = "FindWindow")]
private static extern intFindWindow(string lpClassName, string lpWindowName);
4.自定義消息結構體
使用SendMessage進行進程間通信時,可以發送具有自定義結構體的消息,從而實現更多的通信功能,例如操縱程序的運行,自定義結構體的示例代碼如下:
const int WM_COPYDATA= 0x004A; // 固定數值,不可更改
public struct COPYDATASTRUCT
{
public IntPtr dwData; // 任意值
public int cbData; // 指定lpData內存區域的字節數
[MarshalAs(UnmanagedType.LPStr)]
public string lpData; // 發送給目標窗口所在進程的數據
}
上述自定義結構體可以將字符串發送給目標進程。
5.發送消息
發送消息的程序先通過枚舉進程獲得目標進程句柄,然後將消息封裝進自定義結構體併發送給目標進程,示例代碼如下:
// 待發送消息
string s = "start";
// 枚舉進程
Process[] procs = Process.GetProcesses();
foreach (Process p in procs)
{
if(p.ProcessName.Equals("Demo"))
{
// 獲取目標進程句柄
IntPtr hWnd = p.MainWindowHandle;
// 封裝消息
byte[] sarr = System.Text.Encoding.Default.GetBytes(s);
int len = sarr.Length;
COPYDATASTRUCT cds2;
cds2.dwData = (IntPtr)0;
cds2.cbData = len + 1;
cds2.lpData = s;
// 發送消息
SendMessage(hWnd, WM_COPYDATA, IntPtr.Zero, refcds2);
}
}
6.接收消息
接收消息的程序需要在MainWindow.xaml.cs文件中重寫OnSourceInitialized函數,設置鉤子,用於截獲消息函數,示例代碼如下:
protected override void OnSourceInitialized(EventArgse)
{
base.OnSourceInitialized(e);
HwndSourcehwndSource = PresentationSource.FromVisual(this) as HwndSource;
if(hwndSource != null)
{
IntPtrhandle = hwndSource.Handle;
hwndSource.AddHook(new HwndSourceHook(WndProc));
}
}
用於接收消息並執行自定義行爲的消息函數示例代碼如下:
IntPtr WndProc(IntPtrhwnd, int msg, IntPtrwParam, IntPtr lParam, ref bool handled)
{
if(msg == WM_COPYDATA)
{
COPYDATASTRUCT cds = (COPYDATASTRUCT)Marshal.PtrToStructure(lParam, typeof(COPYDATASTRUCT)); // 接收封裝的消息
string rece = cds.lpData; // 獲取消息內容
// 自定義行爲
if(rece == "start")
{
…
}
}
return hwnd;
}