C# 等待使用SendMessage API发送到MainWindow的消息

C# 等待使用SendMessage API发送到MainWindow的消息,c#,wpf,winapi,sendmessage,windows-messages,C#,Wpf,Winapi,Sendmessage,Windows Messages,应用程序有多个进程,进程通过IPC进行通信。主进程用C编写,具有Windows窗体和DefWndProc。另一个进程通过SendMessage API将消息发送到主进程窗口,但是在DefWndProc中不会立即接收到消息。在接收过程中,我是否可以等待消息 我在主窗口中尝试了睡眠和定时器,但是只有在延迟之后才收到消息 进程A-WinForm应用程序,defwndproc在此实现进程B-使用SendMessage API向进程窗口发送消息 我的主要意图是立即处理发送到主窗口的消息,我可以看到消息不立

应用程序有多个进程,进程通过IPC进行通信。主进程用C编写,具有Windows窗体和DefWndProc。另一个进程通过SendMessage API将消息发送到主进程窗口,但是在DefWndProc中不会立即接收到消息。在接收过程中,我是否可以等待消息

我在主窗口中尝试了睡眠和定时器,但是只有在延迟之后才收到消息

进程A-WinForm应用程序,defwndproc在此实现进程B-使用SendMessage API向进程窗口发送消息


我的主要意图是立即处理发送到主窗口的消息,我可以看到消息不立即传递到DEFWNDPROC

> P>这是C++中的示例代码,删除错误检查< /P> MainWindow.cpp:

#include <windows.h>
#include <iostream>
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}
DWORD WINAPI createyourwindow(LPVOID param)
{
    WNDCLASSEXW wcex = { 0 };

    wcex.cbSize = sizeof(WNDCLASSEX);
    HWND* hWnd = (HWND*)param;
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = GetModuleHandle(NULL);
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.lpszClassName = L"MyClass";
    RegisterClassExW(&wcex);
    *hWnd = CreateWindowW(L"MyClass", L"window", WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, GetModuleHandle(NULL), NULL);

    if (!*hWnd)
    {
        return FALSE;
    }

    ShowWindow(*hWnd, SW_NORMAL);
    UpdateWindow(*hWnd);
    MSG msg;

    // Main message loop:
    while (GetMessage(&msg, NULL, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, NULL, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    return 0;
}

int main()
{
    DWORD ThreadId;
    HWND hwnd = NULL;
    HANDLE hThread = CreateThread(NULL, 0, createyourwindow, (LPVOID)&hwnd, 0, &ThreadId);
    MSG msg;
    DWORD tid = GetCurrentThreadId(); // used in the PostThreadMessage().
    // Main message loop:
    while (GetMessage(&msg, NULL, 0, 0))
    {
        if (msg.message == WM_USER && hwnd != NULL)
        {
            SuspendThread(hThread);
            printf("suspend\n");

            getchar(); //To Do here. 

            ResumeThread(hThread);
        }
    }
    WaitForSingleObject(hThread, INFINITE);
    return 0;

}
PostThreadMessage.cpp:

#include <windows.h>
#include <iostream>
int main()
{
    DWORD tid = 0x....;
    PostThreadMessage(tid,WM_USER,0,0);
    return 0;
}
在MainWindow.cpp中,在线程中创建主窗口,然后在主线程中还有一个messageloop,用于接收用户消息。然后挂起mainwindow的线程,做你想做的事情,最后恢复它

更新:

WinForm Program.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Runtime.InteropServices;
namespace WindowsFormsApp2
{
    static class Program
    {
        static uint WM_USER = 0x0400;
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]

        static void Main()
        {
            Thread thread = new Thread(MainWindow);
            thread.Start();
            MSG msg = new MSG();
            uint tid = GetCurrentThreadId();
            while (GetMessage(ref msg, IntPtr.Zero, 0, 0) == 1)
            {
                if (msg.message == WM_USER)
                {
                    //Thread.Sleep(5000);  //You could still move the window for 5 second(just for test)
                    thread.Suspend();

                    Thread.Sleep(5000);  //To Do here. 

                    thread.Resume();
                }
            }
        }
        static void MainWindow()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
        [DllImport("user32.dll")]
        private static extern int GetMessage(ref MSG msg, IntPtr hwnd, uint wMsgFilterMin, uint wMsgFilterMax);
        [DllImport("Kernel32.dll")]
        private static extern uint GetCurrentThreadId();
        private struct MSG
        {
            public IntPtr hwnd;
            public uint message;
            public uint wParam;
            public long lParam;
            public ulong time;
            public long x;
            public long y;
        }
    }
}

然后将postmessage发送到tid。

只有在收件人处理完邮件并且收件人从其窗口过程返回或调用ReplyMessage后,对SendMessage的调用才会返回。你不必做任何特殊的事情来等待它被接收。@JonathanPotter问题是我想让MainWindow停止其他事情并优先接收此消息,但是,它会做其他事情,并且只有在完成其他事情后才接收消息。可能您需要一个单独的线程,该线程有自己的窗口,该窗口除了响应IPC消息之外什么都不做。@cc125当通过SendMessage跨线程/进程边界发送消息时。。。,在消息所属线程执行消息检索之前,消息不会传递到接收窗口。即使线程的消息循环不会看到消息,窗口过程也会看到。必须确保窗口以正确的顺序接收消息,以便线程控制消息的处理时间。如果线程正忙于执行其他操作,则在线程准备就绪之前,不会处理发送的消息。这在MSDN上有明确的记录。等待是非常麻烦的。只需将等待之后的代码移动到消息处理程序或事件中即可。感谢您的帮助。您在CWinform或WPF中也有它吗?嗨,它解决了您的问题吗?如果您有任何问题,请随时与我联系,如果它对您有帮助,请接受。WU-MSFT您有这个WinC窗体的实现吗?