程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> .NET Compact Framework下的進程間通信之Windows Message

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

編輯:關於.NET

在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中取出傳遞的對象。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved