ホームページ  >  記事  >  バックエンド開発  >  C#のSendMessageとPostMessageでのパラメータ受け渡しの詳細説明

C#のSendMessageとPostMessageでのパラメータ受け渡しの詳細説明

黄舟
黄舟オリジナル
2017-03-14 13:57:513917ブラウズ

C#では、WindowAPIが提供するSendMessageとPostMessageを使用してパラメータを渡すことができます。 2 つの違いを簡単に紹介します。戻り値が異なります。まず 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 はメッセージが正常に投稿されたかどうかを表します。


2. PostMessage は非同期であり、SendMessage は同期です。
PostMessage はメッセージを
キュー に入れるだけで、メッセージが処理されているかどうかに関係なく戻ります。メッセージが処理されていない場合、SendMessage はメッセージが処理されるまで待機します。メッセージの送信は引き続きブロックされます。
3. SendMessage が同じスレッドでメッセージを送信する場合、USER32.
DL
L モジュールはターゲット ウィンドウのメッセージ ハンドラーを呼び出し、結果を返します。 SendMessage は、同じスレッドでメッセージを送信しますが、スレッドのメッセージ キューには入れません。 PostMessage がメッセージを送信する場合、メッセージはまずスレッドのメッセージ キューに入れられ、次にメッセージ
ループ
を通じてターゲット ウィンドウ (DispatchMessage) にディスパッチされる必要があります。
異なるスレッドの場合、SendMessageはターゲットウィンドウが属するスレッドのメッセージキューにメッセージを送信し、メッセージを送信するスレッドはターゲットウィンドウが属するまでUSER32.DLL
モジュールでのメッセージ処理を監視して待機します。処理後に戻ります。 SendMessage は、メッセージを送信する他のスレッドに応答するなど、戻る前に多くの作業を実行します。他のスレッドに投稿する場合は、
PostMessage の代わりに PostThreadMessage を使用するのが最善です。PostMessage の hWnd パラメーターには、PostThreadMessage +
Get
Current
ThreadId と同等の NULL を指定できます。 WM_QUIT をポストする場合は、代わりに PostQuitMessage を使用する必要があります。
4. システムはシステム メッセージ (0 から WM_USER までのメッセージ) のみをマーシャリングします。ユーザー メッセージ (WM_USER 以降) を他のプロセスに送信する場合は、自分でメッセージをマーシャリングする必要があります。
PostMessage、SendNot
if
yMessage、SendMessageC
allback、およびその他の非同期関数を使用してシステムメッセージを送信する場合、送信者はメッセージが処理されるのを待たずに返されるため、パラメーターにポインターを使用できません。 、受信側はまだそれを処理していません。ポインタは解放されています。 5. Windows 2000/XP では、各メッセージ キューには最大 10,000 個の Post メッセージしか保存できません。処理されなかった超過メッセージは処理されず、直接破棄されます。この値は、より大きな値に変更できます: [HKEY_LOCAL_MACHINE/SOFTWARE/ Microsoft/Windows NT/CurrentVersion/Windows] USERPostMessageLimit、最小値は 4000 です。 PostMessage は、メッセージをメッセージ キューに入れることのみを担当します。SendMessage をいつ処理するかどうかは不明です。PostMessage は、メッセージ処理の戻りコード (DWordtype) を受信するまで待機する必要があります。 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();
        }

    }

}

以上がC#のSendMessageとPostMessageでのパラメータ受け渡しの詳細説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。