在C#中SendMessage和PostMessage的參數傳遞詳解

來源:互聯網
上載者:User
在C#中可以使用Window API提供的SendMessage和PostMessage來傳遞參數。兩者的區別簡單介紹下:傳回值的不同,我們先看一下 MSDN 裡的聲明:

LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam);BOOL PostMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam);


其中 4 個參數的意義是一樣的,傳回值類型不同(其實從資料上看他們一樣是一個 32 位的數,只是意義不一樣),LRESULT 表示的是訊息被處理後的傳回值,BOOL 表示的是訊息是不是 Post 成功。


2、PostMessage 是非同步,SendMessage 是同步的。
PostMessage 只把訊息放入隊列,不管訊息是否被處理就返回,訊息可能不被處理;而 SendMessage 等待訊息被處理完了之後才返回,如果訊息不被處理,發送訊息的線程將一直被阻塞。


3、如果在同一個線程內,SendMessage 發送訊息時,由 USER32.DLL
模組調用目標視窗的訊息處理常式,並將結果返回。SendMessage 在同一線程中發送訊息並不入線程訊息佇列。PostMessage
發送訊息時,訊息要先放入線程的訊息佇列,然後通過訊息迴圈指派到目標視窗(DispatchMessage)。


如果在不同線程內,SendMessage 發送訊息到目標視窗所屬線程的訊息佇列,然後發送訊息的線程在 USER32.DLL
模組內監視和等待訊息處理,直到目標視窗處理完返回。SendMessage 在返回前還做了很多工作,比如,響應別的線程向它
SendMessage。Post 到別的線程時,最好用 PostThreadMessage 代替
PostMessage,PostMessage 的 hWnd 參數可以是 NULL,等效於 PostThreadMessage +
GetCurrentThreadId。Post WM_QUIT 時,應使用 PostQuitMessage 代替。

4、系統只整編(marshal)系統訊息(0 到 WM_USER 之間的訊息),發送使用者訊息(WM_USER 以上)到別的進程時,需要自己做整編。

用 PostMessage、SendNotifyMessage、SendMessageCallback 等非同步函數發送系統訊息時,參數裡不可以使用指標,因為寄件者並不等待訊息的處理就返回,接受者還沒處理指標就已經被釋放了。 5、在 Windows 2000/XP 裡,每個訊息佇列最多隻能存放 10,000 個 Post 的訊息,超過的還沒被處理的將不會被處理,直接丟掉。這個值可以改得更大:[HKEY_LOCAL_MACHINE/SOFTWARE/ Microsoft/Windows NT/CurrentVersion/Windows] USERPostMessageLimit,最小可以是 4000。 PostMessage只負責將訊息放到訊息佇列中,不確定何時及是否處理 SendMessage要等到受到訊息處理的返回碼(DWord類型)後才繼續 PostMessage執行後馬上返回 SendMessage必須等到訊息被處理後才會返回。 下面通過一個小例子來說明下這2個方法進行參數傳遞的不同點:
//Win32 API 類

using System;using System.Runtime.InteropServices;namespace TestHwnd{    public class Win32API    {                [DllImport("User32.dll", EntryPoint = "FindWindow")]        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);        [DllImport("User32.dll", EntryPoint = "FindWindowEx")]        public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpClassName, string lpWindowName);        /// <summary>        /// 自訂的結構        /// </summary>        public struct My_lParam        {            public int i;            public string s;        }        /// <summary>        /// 使用COPYDATASTRUCT來傳遞字串        /// </summary>        [StructLayout(LayoutKind.Sequential)]        public struct COPYDATASTRUCT        {            public IntPtr dwData;            public int cbData;            [MarshalAs(UnmanagedType.LPStr)]            public string lpData;        }        //訊息發送API        [DllImport("User32.dll", EntryPoint = "SendMessage")]        public static extern int SendMessage(            IntPtr hWnd,        // 資訊發往的視窗的控制代碼            int Msg,            // 訊息ID            int wParam,         // 參數1            int lParam          //參數2        );        //訊息發送API        [DllImport("User32.dll", EntryPoint = "SendMessage")]        public static extern int SendMessage(            IntPtr hWnd,        // 資訊發往的視窗的控制代碼            int Msg,            // 訊息ID            int wParam,         // 參數1            ref My_lParam lParam //參數2        );                //訊息發送API        [DllImport("User32.dll", EntryPoint = "SendMessage")]        public static extern int SendMessage(            IntPtr hWnd,        // 資訊發往的視窗的控制代碼            int Msg,            // 訊息ID            int wParam,         // 參數1            ref  COPYDATASTRUCT lParam  //參數2        );        //訊息發送API        [DllImport("User32.dll", EntryPoint = "PostMessage")]        public static extern int PostMessage(            IntPtr hWnd,        // 資訊發往的視窗的控制代碼            int Msg,            // 訊息ID            int wParam,         // 參數1            int lParam            // 參數2        );                                //訊息發送API        [DllImport("User32.dll", EntryPoint = "PostMessage")]        public static extern int PostMessage(            IntPtr hWnd,        // 資訊發往的視窗的控制代碼            int Msg,            // 訊息ID            int wParam,         // 參數1            ref My_lParam lParam //參數2        );                //非同步訊息發送API        [DllImport("User32.dll", EntryPoint = "PostMessage")]        public static extern int PostMessage(            IntPtr hWnd,        // 資訊發往的視窗的控制代碼            int Msg,            // 訊息ID            int wParam,         // 參數1            ref  COPYDATASTRUCT lParam  // 參數2        );    }}


//主表單,發送訊息

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Runtime.InteropServices;namespace TestHwnd{    public partial class Main : Form    {        public IntPtr hwndTest;        public int IwndTest;        public IntPtr hwndfrmTest;                public Main()        {            InitializeComponent();        }        private void button1_Click(object sender, EventArgs e)        {            Test test = new Test();            test.Show(this);        }        private void timer1_Tick(object sender, EventArgs e)        {            string strTest = "25425";            Win32API.COPYDATASTRUCT cds;            cds.dwData = (IntPtr)100;            cds.lpData = strTest;            byte[] sarr = System.Text.Encoding.UTF8.GetBytes(strTest);            int len = sarr.Length;            cds.cbData = len + 1;                        Win32API.My_lParam lp=new Win32API.My_lParam();            lp.i=3;            lp.s="test";                        if(hwndTest!=(IntPtr)0)            {                if (DateTime.Now.Second % 2 == 0)                {                    Win32API.SendMessage(hwndTest, 0x60, 1, 3);//傳遞2個整型參數成功                }                if(DateTime.Now.Second % 3 == 0)                {                    Win32API.SendMessage(hwndTest, 0x61, 5, ref lp);//傳遞整型參數和結構類型成功,這個方法加以改變後可以傳遞對象                }                if(DateTime.Now.Second % 5 == 0)                {                    Win32API.SendMessage(hwndTest, 0x62, 5, ref cds);//傳遞整型參數和不定長的字串成功                }                if(DateTime.Now.Second % 7 == 0)                {                    Win32API.PostMessage(hwndTest, 0x63, 5, 6);//傳遞2個整型參數成功                }                if(DateTime.Now.Second % 9 == 0)                {                    Win32API.PostMessage(hwndTest, 0x64, 3, ref lp);//傳遞整型參數成功,但是傳遞參數lp失敗,3可以傳遞成功。                }                if(DateTime.Now.Second % 11 == 0)                {                    Win32API.PostMessage(hwndTest, 0x65, 3, ref cds);//傳遞整型參數成功,傳遞參數cds失敗,3可以傳遞成功。                }            }                                }    }}


//子表單接收訊息以及參數

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Runtime.InteropServices;namespace TestHwnd{    public partial class Test : Form    {        Main main;        public Test()        {            InitializeComponent();        }        private void Test_Load(object sender, EventArgs e)        {            main = this.Owner as Main;            main.hwndTest = this.Handle;                    }        ///重寫表單的訊息處理函數DefWndProc,從中加入自己定義訊息的檢測的處理入口        protected override void DefWndProc(ref Message m)        {            switch (m.Msg)            {                    //接收自訂訊息MYMESSAGE,並顯示其參數                case 0x60:                    {                        label1.Text = DateTime.Now.ToString() + "-" + m.WParam.ToInt32().ToString() + "-" + m.LParam.ToInt32().ToString();                    }                    break;                case 0x61:                    {                        Win32API.My_lParam ml = new Win32API.My_lParam();                        Type t = ml.GetType();                        ml = (Win32API.My_lParam)m.GetLParam(t);                        label2.Text = DateTime.Now.ToString() + "-" + m.WParam.ToInt32().ToString() + "-" + ml.i.ToString()+":"+ml.s;                    }                    break;                    case 0x62:                    {                        Win32API.COPYDATASTRUCT mystr = new Win32API.COPYDATASTRUCT();                        Type mytype = mystr.GetType();                        mystr = (Win32API.COPYDATASTRUCT)m.GetLParam(mytype);                        string str2 = mystr.lpData;                        label3.Text = DateTime.Now.ToString() + "-" + m.WParam.ToInt32().ToString() + "-" + str2;                    }                    break;                    case 0x63:                    {                        label4.Text = DateTime.Now.ToString() + "-" + m.WParam.ToInt32().ToString() + "-" + m.LParam.ToInt32().ToString();                    }                    break;                    case 0x64:                    {                        Win32API.My_lParam ml = new Win32API.My_lParam();                        Type t = ml.GetType();                        ml = (Win32API.My_lParam)m.GetLParam(t);                        label5.Text = DateTime.Now.ToString() + "-" + m.WParam.ToInt32().ToString() + "-" + ml.i.ToString()+":"+ml.s;                    }                    break;                    case 0x65:                    {                        Win32API.COPYDATASTRUCT mystr = new Win32API.COPYDATASTRUCT();                        Type mytype = mystr.GetType();                        mystr = (Win32API.COPYDATASTRUCT)m.GetLParam(mytype);                        string str2 = mystr.lpData;                        label6.Text = DateTime.Now.ToString() + "-" + m.WParam.ToInt32().ToString() + "-" + str2;                    }                    break;                default:                    base.DefWndProc(ref m);                    break;            }        }        private void button1_Click(object sender, EventArgs e)        {            main.hwndTest = (IntPtr) (0);            this.Close();        }    }}
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.