1

我无法让 PeekMessage 工作。实际上,我希望它会向我发送消息,但它的返回值为 0。

我使用 WinForm,启动一个正在查看消息的后台线程并使用鼠标使用该窗口。该窗口像往常一样可用,但无法查看任何消息。我究竟做错了什么 ?最后一个错误始终为 0。

[StructLayout(LayoutKind.Sequential)]
public struct NativeMessage
{
    public IntPtr handle;
    public uint msg;
    public IntPtr wParam;
    public IntPtr lParam;
    public uint time;
    public Point p;
    public override string ToString()
    {
        return handle + ", " + msg + ", " + wParam + ", " + lParam + ", " + time + ", " + p;
    }
}

[DllImport("user32.dll")]
public static extern int PeekMessage(out NativeMessage lpMsg, IntPtr window, uint wMsgFilterMin, uint wMsgFilterMax, uint wRemoveMsg);

public Form1()
{
    ThreadPool.QueueUserWorkItem(o => run());
}

private void run()
{
    for (int i = 0; i < 1000000; )
    {
        NativeMessage a = new NativeMessage();
        int c = PeekMessage(out a, IntPtr.Zero, (uint) 0, (uint) 0, (uint) 0);
        if (c != 0)
            trace(" -> " + c); // prints strings
    }
}

解决了:

  • 我在主线程中调用Show()以显示我的表单
  • 并重定向主线程以记录消息
  • (不是 XY 问题,我需要 PeekMessage 才能工作或至少了解如何使用它)

(感谢您向我展示我犯的错误)

4

2 回答 2

6

当您为参数传递NULL(即 0)时,该函数检索线程消息,以及属于当前线程的任何窗口的消息。这在文档中明确指出:hWndPeekMessage

hWnd [输入,可选]

要检索其消息的窗口的句柄。窗口必须属于当前线程。

如果 hWnd 是NULL,则PeekMessage检索属于当前线程的任何窗口的消息,以及当前线程的消息队列中hwnd值为的任何消息NULL(参见MSG结构)。因此,如果hWndNULL,则窗口消息和线程消息都会被处理。

由于您在 ThreadPool 中的新线程上调用此函数,因此没有消息可供它检索。该线程不与任何窗口相关联并且没有消息。

FALSE当没有可用消息时,该函数返回(即 0)。

如果您正在调用PeekMessage主 UI 线程(与您的表单相关联的线程),您将看到所有发往您的表单窗口的消息。

于 2013-08-19T15:17:52.433 回答
2

窗口消息队列是每个线程的,除非以某种方式关联(AttachThreadInput,窗口父关系...)

于 2013-08-19T15:17:15.543 回答