none
Getting the addressed system message to a thread RRS feed

  • Question

  • When we CreateThread using WinAPI, one of the parameter is the address of the procedure that will receive system messages from Windows kernel. The messages that are sent with SendMessage PostMessage...

    Is it possible to do the same in C#? How to subscribe to system messages inside a NET thread?


    "I = I + 1" .. Isn't it boolshit?

    Saturday, October 26, 2019 2:08 AM

Answers

  • static uint nativeThreadId = 0;
    ....
    AutoResetEvent threadInit = new AutoResetEvent(false);
    Thread t = new Thread(new ThreadStart(ThreadProcedure));
    t.Start();
    threadInit.WaitOne();
    ....
    
    // And thread Proc
    
    [StructLayout(LayoutKind.Sequential)]
    public struct MSG {
       IntPtr hwnd;
       public uint message;
       public IntPtr wParam;
       public IntPtr lParam;
       int time;
       POINT pt;
       };
    [StructLayout(LayoutKind.Sequential)]
    public struct POINT {
       public int X;
       public int Y;
       };
    
    [DllImport("user32.dll")]
    static extern int GetMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);
    [DllImport("kernel32.dll")]
        public static extern uint GetCurrentThreadId();
    
        void ThreadProcedure()
        {
          MSG uMsg;
          int ret;
          nativeThreadId = GetCurrentThreadId();
          threadInit.Set();
                while ((ret = GetMessage(out uMsg, IntPtr.Zero, 0, 0)) != 0)
                {
                    if (ret == -1)
                    {
                        //-1 indicates an error
                    }
                    else
                    {
                        switch (uMsg.message)
                        {
                            case WIM_COOKIE:
                                // do cookies
                                break;
                            case WIM_CAKE:
                                // do cakes
                                break;
                        }
                    }
                }
    }
    
    


    "I = I + 1" .. Isn't it boolshit?

    • Marked as answer by RobbKirk Tuesday, October 29, 2019 4:35 AM
    Tuesday, October 29, 2019 4:24 AM

All replies

  • I am confused by your use of "system messages", "SendMessage" (so you mean Window messages?)
    and the procedure adress.
    What parameter in CreateThread are you refering to?
    LPTHREAD_START_ROUTINE in the Win32 api matches the ParameterizedThreadStart parameter to System.Threading.Thread constructor
    lpParameter in the Win32 api matches the Object obj parameter passed to ParameterizedThreadStart 

    when you want to get Window messages: getting them depends on what UI framwork you use (Windows Forms, WPF, UWP)
    Saturday, October 26, 2019 10:16 AM
  • As EckiS said, please be specific. What exactly about CreateThread are you asking about?

    If you are asking about receiving Windows messages then you must do that in a Windows Procedure, not something specified in CreateThread. The only message you can receive without a window is PostThreadMessage, as in my PostThreadMessage. I also have a sample C# program that uses C# to show how the Windows API works without .Net but I assume it will only confuse you.

    There are a couple of ways to process Windows messages using .Net. I will not be specific until I know more about what you need to do. What type of UI are you doing this for? Windows Forms or WPF or something else?



    Sam Hobbs
    SimpleSamples.Info

    Saturday, October 26, 2019 8:00 PM
  • Post the docs you're looking at because the MSDN docs have no such parameter.

    I think you misunderstand how messaging works in Windows. In order to "receive" messages you need a message queue. A message queue is created on the thread when it makes its first call to User32. To handle messages in the queue you need a message pump (aka the message procedure). Each window can have a single message pump. When you create a window using CreateWindow you specify the window class. The window class must already be registered with RegisterClass. When you register a window class you specify the message pump (procedure) to call. 

    SendMessage accepts the handle to the window to send the message to. Windows uses the handle to get to the window class which tells it which message pump to call. SendMessage then calls that function directly. PostMessage works similarly, ignoring same thread optimizations.

    If you want to hook into the message pump of a thread there are hooks available that don't have anything to do with threading. If you want a thread you created to have a message pump then you need only call into User32.


    Michael Taylor http://www.michaeltaylorp3.net

    Monday, October 28, 2019 2:15 PM
    Moderator
  • If you wish to read about how the Windows API works with respect to threads, messages and message queues I suggest you refer to https://docs.microsoft.com/en-us/windows/win32/winmsg/about-messages-and-message-queues
    • Edited by RLWA32 Monday, October 28, 2019 2:40 PM
    Monday, October 28, 2019 2:40 PM
  • As I indicated previously, it might be too advanced to get into the details of the message loop and such. If RobbKirk is interested in the details then my Windows API Window Using C# shows all the details using C#.

    I think you misunderstand how messaging works in Windows. In order to "receive" messages you need a message queue. A message queue is created on the thread when it makes its first call to User32. To handle messages in the queue you need a message pump (aka the message procedure). Each window can have a single message pump. When you create a window using CreateWindow you specify the window class. The window class must already be registered with RegisterClass. When you register a window class you specify the message pump (procedure) to call.

    The message pump is often called a message loop but I am not sure it is called a message procedure.

    SendMessage accepts the handle to the window to send the message to. Windows uses the handle to get to the window class which tells it which message pump to call. SendMessage then calls that function directly. PostMessage works similarly, ignoring same thread optimizations.

    The (main) difference between PostMessage and SendMessage is that the caller of SendMessage blocks until the message is processed whereas PostMessage posts the message to the message loop then returns to the caller before the message is processed.

    If you want to hook into the message pump of a thread there are hooks available that don't have anything to do with threading. If you want a thread you created to have a message pump then you need only call into User32.

    My Detecting When an Application Has Been Idle shows use of IMessageFilter. Another possibility is to override the Form's class DefWndProc. I am waiting for the details of the requirements before proceeding with the detaisl of suggested solutions.



    Sam Hobbs
    SimpleSamples.Info

    Monday, October 28, 2019 5:45 PM
  • Hello Sam and others.

    Thanks for your efforts to help.. very appreciate that guys.
    Well, yes, I should've been more specific.. sorry for that.
    I am still having problems with WaveInAudio under WinForms CLR.
    Works unstable and only as the Console App controlled through pipelines it would stay in recording for affordable long time. Usually it is non stop sound transfer from local server to very far located remote server. I need to make it robust and stable.
    I can write it under C++ MFC App, but all code's been written in C#, and my goal to do not use any other third party libs, just pure C#.NET App with original Windows controls set.

    The question about the Thread and messaging came to me after I decided to try the last way - using CALLBACK_THREAD in WaveInOpen.

    CALLBACK_WINDOW and callbackFunc.. I can't count on them.. tried nearly everything..recording is freezing after certain time.. always.. and anyway.
    If you like to try I could publish the extracted part of that code for you to make sure it works unstable on your PC also.

    But.. my question was actually how to implement that construction in C$ - CALLBACK_THREAD.So, I pass the Thread System ID and the WaveAudio will send or Post messages to where? How do I receive that messages inside the original Thread? Is it possible to implement under C#?

    I remember I was writing Win32 Apps, and there were window_proc and lParm + rParm + Message Id..
    That's what confused me.. what technique should I use to Dequeue messages from system message queue?

    UPDATE:

    Seems I found the solution, will publish nest div..below..


    "I = I + 1" .. Isn't it boolshit?


    • Edited by RobbKirk Tuesday, October 29, 2019 4:13 AM
    Tuesday, October 29, 2019 1:25 AM
  • static uint nativeThreadId = 0;
    ....
    AutoResetEvent threadInit = new AutoResetEvent(false);
    Thread t = new Thread(new ThreadStart(ThreadProcedure));
    t.Start();
    threadInit.WaitOne();
    ....
    
    // And thread Proc
    
    [StructLayout(LayoutKind.Sequential)]
    public struct MSG {
       IntPtr hwnd;
       public uint message;
       public IntPtr wParam;
       public IntPtr lParam;
       int time;
       POINT pt;
       };
    [StructLayout(LayoutKind.Sequential)]
    public struct POINT {
       public int X;
       public int Y;
       };
    
    [DllImport("user32.dll")]
    static extern int GetMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);
    [DllImport("kernel32.dll")]
        public static extern uint GetCurrentThreadId();
    
        void ThreadProcedure()
        {
          MSG uMsg;
          int ret;
          nativeThreadId = GetCurrentThreadId();
          threadInit.Set();
                while ((ret = GetMessage(out uMsg, IntPtr.Zero, 0, 0)) != 0)
                {
                    if (ret == -1)
                    {
                        //-1 indicates an error
                    }
                    else
                    {
                        switch (uMsg.message)
                        {
                            case WIM_COOKIE:
                                // do cookies
                                break;
                            case WIM_CAKE:
                                // do cakes
                                break;
                        }
                    }
                }
    }
    
    


    "I = I + 1" .. Isn't it boolshit?

    • Marked as answer by RobbKirk Tuesday, October 29, 2019 4:35 AM
    Tuesday, October 29, 2019 4:24 AM
  • This is beyond what I can help with, I am unsubscribing from this thread.


    Sam Hobbs
    SimpleSamples.Info

    Tuesday, October 29, 2019 4:29 AM