天天看點

.NET Compact Framework下的程序間通信之Windows Message

在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

.NET Compact Framework下的程式間通信之Windows Message

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);

        }

}

.NET Compact Framework下的程式間通信之Windows Message

首先需要P/Invoke RegisterWindowMessage 函數,每個發送的message都有唯一的UID,這樣接收方才能根據UID進行監聽和接收該Message。

發送之前先create一個Message對象,參數一為接收對象,如果為程序間通信可以使用廣播的形式(MSG_BROADCAST),第二個參數為message的UID,接收方利用這一表示辨識message。第三和第四分别為WParam和LParam,這是标準windows message的傳遞參數。

.NET Compact Framework下的程式間通信之Windows Message

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. 

       }

    }

.NET Compact Framework下的程式間通信之Windows Message

接收消息需要定義一個繼承類,繼承于MessageWindow,同時他同樣需要P/Invoke RegisterWindowMessage 函數,定義接收message的唯一UID。

重寫WndProc,然後通過msg.Msg 來辨識關心的消息。

如果接收方接收到message需要更新到form的話就定義一個form的reference,這樣可以利用form來處理消息。其實不一定使用Form來處理message,使用Form就能比較友善的利用ui來反映message的接收和處理情況。

.NET Compact Framework下的程式間通信之Windows Message

    private MsgWindow MsgWin;

    public MsgForm()

    {

        //pass the form reference to messagewindow

        this.MsgWin = new MsgWindow(this);

    }

     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();

.NET Compact Framework下的程式間通信之Windows Message

MsgWindow 儲存MsgForm 的引用,這樣當MsgWindow 接收到消息就可以使用form來處理。

如果在消息中傳遞對象,就不可以使用.NET Compact Framework裡面的MessageWindow.SendMessage函數了,需要使用P/Invoke來進行發送。發送端的關鍵是把要傳遞的對象封裝到COPYDATASTRUCT Structure裡面,然後通過API SendMessageW進行發送,接收方辨識WM_COPYDATA消息,從LParam中分拆出對象。

.NET Compact Framework下的程式間通信之Windows Message

  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);

        public static extern IntPtr LocalFree(IntPtr p);

        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);

            }

.NET Compact Framework下的程式間通信之Windows Message

上面為發生端的代碼,通過cMsgStrings.SendMsgString進行發送,可以把任何managed的object封裝到COPYDATASTRUCT 進行發送。

.NET Compact Framework下的程式間通信之Windows Message

        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;

.NET Compact Framework下的程式間通信之Windows Message

上面為接收端的代碼,辨識WM_COPYDATA的消息從LParam中取出傳遞的對象。

<a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.message.create.aspx" target="_blank">Message.Create Method</a>

<a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.message.create.aspx" target="_blank">COPYDATASTRUCT Structure</a>

測試環境:Wince 5 + CF.net 2.0

    本文轉自Jake Lin部落格園部落格,原文連結:http://www.cnblogs.com/procoder/archive/2009/03/16/1413176.html,如需轉載請自行聯系原作者