1

I can't get PeekMessage to work. Actually I would expect it to flood me with messages but it's return value is 0.

I use a WinForm, start a background thread that is peeking messages and use the window with the mouse. The window is usable like always but no messages can be peeked. What am I doing wrong ? Last error is 0 all the time.

[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
    }
}

Solved:

  • I called Show() in the main thread to show my form
  • and redirected the main thread to log the messages
  • (not XY problem, I needed PeekMessage to work or at least to understand how to use it)

(thanks for showing me the error I made)

Bitterblue
  • 13,162
  • 17
  • 86
  • 124
  • Based upon your code, you do not create a window on that thread. Why would you expect any messages in the thread's queue? – noseratio Aug 19 '13 at 15:16
  • @Noseratio There is no requirement for a thread to own any windows to receive messages. There is [`PostThreadMessage`](http://msdn.microsoft.com/en-us/library/windows/desktop/ms644946.aspx) after all. – IInspectable Aug 19 '13 at 15:23
  • @IInspectable, I don't see that anywhere in the code above. That's why I asked why OP expects a flood of messages. – noseratio Aug 19 '13 at 15:29
  • @Noseratio If you print all messages that are posted to WndProc it is quite a flood. – Bitterblue Aug 19 '13 at 15:37
  • @mini-me, correct, but you do not create a window inside your `run()` thread, do you? At least, not in the code above. A thread can't pump messages posted to a window belonging to another thread. Also, it doesn't look to me like a good idea using a pool thread for your message loop. You should create a new child thread. – noseratio Aug 19 '13 at 15:43

2 Answers2

6

When you pass NULL (i.e. 0) for the hWnd parameter, the PeekMessage function retrieves thread messages, and messages for any window that belongs to the current thread. This is called out explicitly in the documentation:

hWnd [in, optional]

A handle to the window whose messages are to be retrieved. The window must belong to the current thread.

If hWnd is NULL, PeekMessage retrieves messages for any window that belongs to the current thread, and any messages on the current thread's message queue whose hwnd value is NULL (see the MSG structure). Therefore if hWnd is NULL, both window messages and thread messages are processed.

Since you are calling this function on a new thread in a ThreadPool, there are no messages for it to retrieve. That thread is not associated with any windows and has no messages.

The function returns FALSE (i.e. 0) when there are no messages available.

If you were calling PeekMessage on the main UI thread (the one associated with your form), you would be getting a peek at all messages destined for your form window.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • Well, I actually read that thread note but since every window has it's own thread I was confused how 1 thread can peek messages of other windows as the parameter note states. And I just want to log all messages via PeekMessage and let them be translated by the API itself. – Bitterblue Aug 19 '13 at 15:36
  • @mini Every window does *not* have its own thread. In fact, the general situation is almost exactly the opposite: every window runs on a *single* thread; it is called the UI thread. And to answer your other question, a thread can peek messages of other windows by passing in the handle of the window of interest. – Cody Gray - on strike Aug 19 '13 at 15:43
  • 1
    PeekMessage is not a good logging mechanism, certainly not how you're using it. There are better ways of doing it, but that's an entirely different question. I would have answered that one, had you asked it. Do beware of [the XY problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). – Cody Gray - on strike Aug 19 '13 at 15:44
2

Window message queues are per-thread unless associated in some way (AttachThreadInput, window parent relationship...)

Medinoc
  • 6,577
  • 20
  • 42