在Wince和Windows Moblie 下的進程間通信可以由以下幾種技術實現。
1. Windows Message
2. Point-to-Point Message Queues
3. MSMQ
下面使用講述.NET Compact Framework下使用Windows Message進行進程間的 通信。
引用庫
在CF.net下進行Windows Message的開發需要引用Microsoft.WindowsCE.Forms ,該DLL一般存放於C:\Program Files\Microsoft.NET\SDK\CompactFramework\v2.0 \WindowsCE\Microsoft.WindowsCE.Forms.dll
發送消息
using Microsoft.WindowsCE.Forms;
public partial class MsgForm : Form
{
[DllImport("coredll.dll", EntryPoint = "RegisterWindowMessage", SetLastError = true)]
private static extern uint RegisterWindowMessage(string lpString);
private uint msgUid = RegisterWindowMessage ("MESSAGE_UID");
public static int MSG_BROADCAST = 0xFFFF;
private void SendMessage(object sender)
{
Message msg = Message.Create((IntPtr) MSG_BROADCAST, (int)msgUid , IntPtr.Zero, IntPtr.Zero);
MessageWindow.SendMessage(ref msg);
}
}
首先需要P/Invoke RegisterWindowMessage 函數,每個發送的message都有唯 一的UID,這樣接收方才能根據UID進行監聽和接收該Message。
發送之前先create一個Message對象,參數一為接收對象,如果為進程間通信 可以使用廣播的形式(MSG_BROADCAST),第二個參數為message的UID,接收方利 用這一表示辨別message。第三和第四分別為WParam和LParam,這是標准windows message的傳遞參數。
接收消息
using Microsoft.WindowsCE.Forms;
public class MsgWindow : MessageWindow
{
[DllImport("coredll.dll", EntryPoint = "RegisterWindowMessage", SetLastError = true)]
private static extern uint RegisterWindowMessage(string lpString);
private uint msgUid = RegisterWindowMessage ("MESSAGE_UID");
protected override void WndProc(ref Message msg)
{
if (msg.Msg == msgUid )
{
//handle the message.
}
}
}
接收消息需要定義一個繼承類,繼承於MessageWindow,同時他同樣需要 P/Invoke RegisterWindowMessage 函數,定義接收message的唯一UID。
重寫WndProc,然後通過msg.Msg 來辨別關心的消息。
使用Form處理Message
如果接收方接收到message需要更新到form的話就定義一個form的reference, 這樣可以利用form來處理消息。其實不一定使用Form來處理message,使用Form就 能比較方便的利用ui來反映message的接收和處理情況。
public partial class MsgForm : Form
{
private MsgWindow MsgWin;
public MsgForm()
{
//pass the form reference to messagewindow
this.MsgWin = new MsgWindow(this);
}
}
public class MsgWindow : MessageWindow
{
private MsgForm msgForm;
public MsgWindow(MsgForm msgForm)
{
this.msgForm= msgForm;
}
protected override void WndProc(ref Message msg)
{
if (msg.Msg == msgUid )
{
//call form to handle the message.
msgForm.HandleMsg();
}
}
}
MsgWindow 保存MsgForm 的引用,這樣當MsgWindow 接收到消息就可以使用 form來處理。
消息中傳遞對象
如果在消息中傳遞對象,就不可以使用.NET Compact Framework裡面的 MessageWindow.SendMessage函數了,需要使用P/Invoke來進行發送。發送端的關 鍵是把要傳遞的對象封裝到COPYDATASTRUCT Structure裡面,然後通過API SendMessageW進行發送,接收方辨別WM_COPYDATA消息,從LParam中分拆出對象。
public struct COPYDATASTRUCT
{
public int dwData;
public int cbData;
public IntPtr lpData;
}
class cMsgStrings
{
const int LMEM_FIXED = 0x0000;
const int LMEM_ZEROINIT = 0x0040;
const int LPTR = (LMEM_FIXED | LMEM_ZEROINIT);
const int WM_COPYDATA = 0x004A;
[DllImport("coredll.dll")]
public static extern IntPtr LocalAlloc(int flag, int size);
[DllImport("coredll.dll")]
public static extern IntPtr LocalFree(IntPtr p);
[DllImport("coredll.dll")]
public static extern int SendMessageW(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
public static IntPtr AllocHGlobal(int cb)
{
IntPtr hMemory = new IntPtr();
hMemory = LocalAlloc(LPTR, cb);
return hMemory;
}
public static void FreeHGlobal (IntPtr hMemory)
{
if (hMemory != IntPtr.Zero)
LocalFree(hMemory);
}
public static void SendMsgString(IntPtr hWndDest, string sScript)
{
COPYDATASTRUCT oCDS = new COPYDATASTRUCT();
oCDS.cbData = (sScript.Length + 1) * 2;
oCDS.lpData = LocalAlloc(LPTR, oCDS.cbData);
Marshal.Copy(sScript.ToCharArray(), 0, oCDS.lpData, sScript.Length);
oCDS.dwData = 1;
IntPtr lParam = AllocHGlobal(oCDS.cbData);
Marshal.StructureToPtr(oCDS, lParam, false);
SendMessageW(hWndDest, WM_COPYDATA, IntPtr.Zero, lParam);
LocalFree(oCDS.lpData);
FreeHGlobal(lParam);
}
}
//send the message with string
private void button1_Click(object sender, EventArgs e)
{
unsafe
{
cMsgStrings.SendMsgString((IntPtr) MSG_BROADCAST, textBoxMsg.Text);
}
}
上面為發生端的代碼,通過cMsgStrings.SendMsgString進行發送,可以把任 何managed的object封裝到COPYDATASTRUCT 進行發送。
public class MsgWindow : MessageWindow
{
const int WM_COPYDATA = 0x004A;
private FormReceiver msgForm;
public MsgWindow (FormReceiver msgForm)
{
this.msgForm = msgForm;
}
protected override void WndProc (ref Message msg)
{
if (msg.Msg == WM_COPYDATA)
{
string str = GetMsgString (msg.LParam);
msgForm.HandleMsg(str);
}
}
public static string GetMsgString(IntPtr lParam)
{
if (lParam != IntPtr.Zero)
{
COPYDATASTRUCT st = (COPYDATASTRUCT) Marshal.PtrToStructure(lParam, typeof(COPYDATASTRUCT));
string str = Marshal.PtrToStringUni (st.lpData);
return str;
}
else
{
return null;
}
}
}
上面為接收端的代碼,辨別WM_COPYDATA的消息從LParam中取出傳遞的對象。