>백엔드 개발 >C#.Net 튜토리얼 >C#에서 SendMessage 및 PostMessage의 매개변수 전달에 대한 자세한 설명

C#에서 SendMessage 및 PostMessage의 매개변수 전달에 대한 자세한 설명

黄舟
黄舟원래의
2017-03-14 13:57:514192검색

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

);


네 가지 매개 변수의 의미는 동일합니다. 그러나 반환값의 종류가 다릅니다.(실제로 데이터 관점에서 보면 동일한 32비트 숫자이지만 의미가 다릅니다.) LRESULT는 메시지가 처리된 후의 반환값을 나타내고, BOOL은 메시지가 성공적으로 게시되었습니다.


2. PostMessage는 비동기식이고 SendMessage는 동기식입니다.
PostMessage는 메시지를 대기열에만 넣고 메시지 처리 여부에 관계없이 반환합니다. SendMessage는 메시지가 반환되기 전에 처리될 때까지 기다립니다. 처리되지 않으면 메시지를 보내는 스레드가 항상 차단됩니다.


3. SendMessage가 동일한 스레드에서 메시지를 보내는 경우 USER32.DLL
모듈은 대상 창의 메시지 핸들러를 호출하고 결과를 반환합니다. SendMessage는 동일한 스레드에서 메시지를 보내고 이를 스레드 메시지 대기열에 넣지 않습니다. PostMessage
가 메시지를 보낼 때 메시지는 먼저 스레드의 메시지 대기열에 넣은 다음 메시지 루프를 통해 대상 창(DispatchMessage)으로 전달되어야 합니다.


다른 스레드일 경우 SendMessage는 대상 창이 속한 스레드의 메시지 큐로 메시지를 보내고, 메시지를 보내는 스레드는 USER32.DLL에서 메시지 처리를 모니터링하고 기다립니다.
모듈을 대상 창까지 처리한 후 반환합니다. SendMessage는 또한 반환하기 전에 다른 스레드
SendMessage에 응답하는 등 많은 작업을 수행합니다. 다른 스레드에 게시할 때는
PostMessage 대신 PostThreadMessage를 사용하는 것이 가장 좋습니다. PostMessage의 hWnd 매개변수는 NULL일 수 있으며 이는 PostThreadMessage +
GetCurrent스레드 ID. Post WM_QUIT 시 PostQuitMessage를 대신 사용해야 합니다.
4. 시스템은 시스템 메시지(0과 WM_USER 사이의 메시지)만 마샬링합니다. 사용자 메시지(WM_USER 이상)를 다른 프로세스로 보낼 때는 직접 마샬링해야 합니다.

PostMessage, SendNot
ifyMessage, SendMessageCallback 및 기타 비동기 기능을 사용하여 시스템 메시지를 보낼 때 포인터를 사용할 수 없습니다. 왜냐하면 보낸 사람은 반환하기 전에 메시지가 처리될 때까지 기다리지 않고, 받는 사람이 메시지를 처리하기 전에 포인터가 해제되기 때문입니다. 5. Windows 2000/XP에서는 각 메시지 대기열에 최대 10,000개의 Post 메시지만 저장할 수 있습니다. 처리되지 않은 초과 메시지는 처리되지 않고 바로 삭제됩니다. 이 값은 더 큰 값으로 변경될 수 있습니다: [HKEY_LOCAL_MACHINE/SOFTWARE/ Microsoft/Windows NT/CurrentVersion/Windows] USERPostMessageLimit, 최소값은 4000일 수 있습니다. PostMessage는 메시지 대기열에 메시지를 배치하는 역할만 담당하며 SendMessage를 처리할지 여부는 확실하지 않습니다. PostMessage를 계속하기 전에 메시지 처리 반환 코드(DWord 유형)를 받을 때까지 기다려야 합니다. SendMessage는 메시지가 전송될 때까지 기다려야 합니다. 다음은 매개변수 전달을 위한 두 가지 방법의 차이점을 보여주는 작은 예입니다. //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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.