c# winproc重写-消息机制使用-SendMessage和PostMessage的区别

SendMessage和PostMessage的区别

SendMessage是将消息发送到窗口函数,在窗口函数处理完消息后才返回。    

PostMessage   是将消息发送到窗口的消息队列中,然后立即返回   
 
SendMessage是同步处理 

PostMessage是异步处理

 

 

BOOL   PostMessage(   
      HWND   hWnd,             //   handle   of   destination   window   
      UINT   Msg,               //   message   to   post   
      WPARAM   wParam,     //   first   message   parameter   
      LPARAM   lParam       //   second   message   parameter   
  );   
  消息就是发到hWnd这个窗口

----------------------------------------------------------------------------------------------------------------------------------------------------

PostMessage   和SendMessage的区别主要在于是否等待其他程序消息处理。PostMessage只是把消息放入队列,不管其他程序是否处理都返回,然后继续执行;而SendMessage必须等待其他程序处理消息后才返回,继续执行。这两个函数的返回值也不同,PostMessage的返回值表示PostMessage函数执行是否正确,而SendMessage的返回值表示其他程序处理消息后的返回值。

---------------------------------------------------------------------------------------------

  前者需要马上返回   
  后者要阻塞等待   
  凡是由你设计而却由Windows系统调用的函数,统称callback函数。这些函数都有一定的类型,以配合Windows的调用操作

---------------------------------------------------------------------------------------------

  注意在实际使用中才有可能体会异同点,   
  以前我写程序的时候发现post到消息队列的消息可能会丢失,   
  尤其你的消息特别多,例如用timer发送的时候容易出错   
  仅供参考!

---------------------------------------------------------------------------------------------

1   对于消息映射机制的理解。表面上看是A发消息到B,然后B收到消息执行相应的操作。实际上呢?消息映射的原理是:B预先设定,假如A执行了发某个消息的过程,那么B就做某一个操作。可以看出,实际上并没有什么“消息”在传递,消息映射的实质是A对B的一种函数调用。   
2   进一步理解消息映射,A调用B的函数,那么A要不要等到B的过程执行完再继续呢?这就是消息队列机制了。PostMessage只是把调用要求放进一个等待队列里(消息队列),而SendMessage一定要等到B执行完消息映射函数才能继续,这就是两个函数的本质区别。

 

补充一下:   很多人会被“消息”的假象迷惑,一定要记住,其实并不存在什么消息,消息映射机制只不过是一种跨对象的函数调用,不是A“发消息”让B做什么,而是B“自己决定”在A“执行发消息函数”的时候做什么!

---------------------------------------------------------------------------------------------

 
    
  CALLBACK是回调的意思,即由应用程序定义,供系统调用的函数.   
  就实质而言,CALLBACK是一种调用方式,即__stdcall   
  而C/C++的默认调用方式是__cdecl

 

子线程向主线程窗口发消息

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SendPostMessageTest
{
   

    
    public partial class Form1 : Form
    {
        [DllImport("user32.dll", EntryPoint = "SendMessage")]
        public static extern int SendMessage(int hWnd, int Msg,int wParam,ref COPYDATASTRUCT lParam);
        [DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
        public static extern int FindWindow(string lpClassName, string lpWindowName);
        private static int WM_COPYDATA = 0x004A; //固定值
        public Form1()
        {
            InitializeComponent();
        }
       
        public struct COPYDATASTRUCT
        {
            public IntPtr dwData;
            public int cbData;
            [MarshalAs(UnmanagedType.LPStr)]
            public string lpData;
        }

        protected override void DefWndProc(ref Message m)
        {
            if(m.Msg== WM_COPYDATA)
            {
                COPYDATASTRUCT cds = new COPYDATASTRUCT();
                Type t = cds.GetType();
                cds = (COPYDATASTRUCT)m.GetLParam(t);
                string receiveInfo = cds.lpData;
            }
            else
            {
                base.DefWndProc(ref m);
            }
           
        }
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == WM_COPYDATA)
            {
                COPYDATASTRUCT cds = new COPYDATASTRUCT();
                Type t = cds.GetType();
                cds = (COPYDATASTRUCT)m.GetLParam(t);
                string receiveInfo = cds.lpData;
                MessageBox.Show(receiveInfo);
            }


            //const int WM_SYSCOMMAND = 0x0112;
            //const int SC_CLOSE = 0xF060;
            //if (m.Msg == WM_SYSCOMMAND && (int)m.WParam == SC_CLOSE)
            //{
            //    // 屏蔽传入的消息事件
            //    this.WindowState = FormWindowState.Minimized;
            //    return;
            //}
            base.WndProc(ref m);
        }
        private void button1_Click(object sender, EventArgs e)
        {
            Thread thead_test = new Thread(test_show);
            thead_test.IsBackground = true;
            thead_test.Start();

        }
        private void test_show()
        {
            //OQA测试接收消息窗口
            while(true)
            {
                int hWnd = FindWindow(null, "OQA测试接收消息窗口");
                if (hWnd == 0)
                {
                    MessageBox.Show("未找到:OQA测试接收消息窗口");
                }
                else
                {
                    string sendMsg = "子线程发送数据到指定窗口";
                    byte[] str_array = System.Text.Encoding.Default.GetBytes(sendMsg);
                    int length = str_array.Length;
                    COPYDATASTRUCT cds;
                    cds.dwData = (IntPtr)0;
                    cds.cbData = length + 1;
                    cds.lpData = sendMsg;
                    SendMessage(hWnd, WM_COPYDATA, 0, ref cds);
                }
                Thread.Sleep(3000);
            }
        }
           
    }
}

 

posted @ 2022-05-06 16:14  txwtech  阅读(709)  评论(0编辑  收藏  举报