WPF應用程序使用SendMessage實現進程間通信(含示例代碼)

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;

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章