C# Winform calls winapi SendMessage method to send and receive messages across processes

Posted by zigojacko on Wed, 15 Dec 2021 02:14:36 +0100

C# Winform inter window message notification uses the Windows API SendMessage method to send messages across processes, rewrites the WndProc method to receive and process messages

The following three methods and functions are mainly used:

  • WndProc: mainly used to intercept and process system messages and custom messages
    • You can override the WndProc function to capture all window messages that occur. In this way, we can "tamper" with the incoming message and artificially make the window change its behavior

  • SendMessage: this function sends the specified message to one or more windows. This function calls the window program for the specified window until the window program finishes processing the message. This function is one of the main means of message passing between applications
    • Function prototype: IntPtr SendMessage(int hWnd, int msg, IntPtr wParam, IntPtr lParam);
    • parameter
      • HWnd: handle to the window whose window program will receive the message. If this parameter is HWND_BROADCAST, the message will be sent to all top-level windows in the system, including invalid or invisible windows not owned by itself, overwritten windows and pop-up windows, but the message will not be sent to child windows
      • Msg: Specifies the message to be sent
      • wParam: specify additional message information
      • IParam: specify additional message information
      • Return value: the return value specifies the result of message processing, which depends on the sent message
    • Note: hWnd is required_ Applications communicating with broadcast should use the function RegisterWindowMessage to obtain a unique message for communication between applications.
  • FindWindow: the function obtains a handle to a top-level form whose class name and form name match the given string. This function does not look for subforms. Do not distinguish between uppercase and lowercase when searching
    • Function prototype: int FindWindow(string lpClassName, string lpWindowName);
    • parameter
      • IpClassName: points to a null terminated string specifying the class name, or a pointer identifying the member of the class name string. Assuming that the parameter is a member, it must be the global member generated by the previous call to the globaladdatom function. The member is 16 bits and must be located in the lower 16 bits of IpClassName, and the upper bit must be 0
      • IpWindowName: points to an empty ending string specifying the form name (form title). If this parameter is empty, all forms match
    • Return value: assuming that the function succeeds, the return value is the form handle with the specified class name and form name; Assuming that the function fails, the return value is NULL

The example code is as follows:

public partial class Form1 : Form
    {
        public const int LOGINFORM_MSG = 0x400;
        protected override void WndProc(ref System.Windows.Forms.Message msg)
        {

            switch (msg.Msg)
            {

                case LOGINFORM_MSG: //Custom message
                    switch ((msg.LParam.ToInt32()))
                    {
                        case 301:
                            {
                                MessageBox.Show("Message received:" + msg.WParam.ToInt32());
                                //if (msg.WParam.ToInt32() == 1)
                                //{
                                //}
                                //else
                                //{
                                //}
                            }
                            break;

                    }
                    break;
            }
            base.WndProc(ref msg);     //Call the base class function to process non custom messages. 
        }
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //Code scanning thread
            Thread m_Thread1 = new Thread(Thread1Handle);
            m_Thread1.IsBackground = true;
            m_Thread1.Start();
        }
        static void Thread1Handle()
        {
            Thread.Sleep(3000);
            new Demo().Test();
        }
    }
public class Demo
    {
        /// <summary>
        ///Send message to specified window
        /// </summary>
        ///< param name = "hWnd" > the handle of the window whose window program will receive the message. If this parameter is HWND_BROADCAST, the message will be sent to all top-level windows in the system,
        ///It includes invalid or invisible non self owned windows, overwritten windows and pop-up windows, but the message is not sent to the child window < / param >
        ///< param name = "MSG" > specify the message to be sent < / param >
        ///< param name = "wParam" > specify additional message assignment information < / param >
        ///< param name = "lParam" > specify additional message assignment information < / param >
        /// <returns></returns>
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        private static extern IntPtr SendMessage(int hWnd, int msg, IntPtr wParam, IntPtr lParam);//Window handle

        /// <summary>
        ///Get form handle
        /// </summary>
        ///< param name = "lpclassname" > points to a null terminated string specifying the class name, or a pointer identifying the member of the class name string. Assuming that the parameter is a member,
        ///Then it must be the global member generated by the previous call to the globafaddatom function. The member is 16 bits and must be in the lower 16 bits of IpClassName, and the high bit must be 0 < / param >
        ///< param name = "lpwindowname" > points to an empty ending string specifying the form name (form title). If this parameter is empty, all forms will match < / param >
        /// <returns></returns>
        [DllImport("User32.dll", EntryPoint = "FindWindow")]
        private static extern int FindWindow(string lpClassName, string lpWindowName);
        public const int LOGINFORM_MSG = 0x400;

        public void Test()
        {
            int WINDOW_HANDLER = FindWindow(null, "Form1");//Send message window handle this Handle. ToInt32()
            if (WINDOW_HANDLER == 0)
            {
                throw new Exception("Could not find Main window!");//Main window not found
            }

            //long result = SendMessage(WINDOW_HANDLER, LOGINFORM_MSG, new IntPtr(MSG), new IntPtr(ID)).ToInt64();
            long result = SendMessage(WINDOW_HANDLER, LOGINFORM_MSG, new IntPtr(0), new IntPtr(301)).ToInt64();
            for (int i = 0; i < 100000; i++)
            {
                Application.DoEvents();
            }
            result = SendMessage(WINDOW_HANDLER, LOGINFORM_MSG, new IntPtr(1), new IntPtr(301)).ToInt64();
        }
    }

Effect achieved:

Example download address:

Use SendMessage message to send interception in C#Winform - C# document class resources - CSDN Download

Topics: C# Back-end winform