Why is there no WM_MOUSEENTER message?

There is a WM_MOUSELEAVE message. Why isn't there a WM_MOUSEENTER message?

Because you can easily figure that out for yourself.

When you receive a WM_MOUSELEAVE message, set a flag that says, "The mouse is outside the window." When you receive a WM_MOUSEMOVE message and the flag is set, then the mouse has entered the window. (And clear the flag while you're there.)

Let's illustrate this with our sample program, just to make sure you get the idea:

BOOL g_fMouseInClient;
void OnMouseMove(HWND hwnd, int x, int y, UINT keyFlags)
    if (!g_fMouseInClient) {
        g_fMouseInClient = TRUE;
        TRACKMOUSEEVENT tme = { sizeof(tme) };
        tme.dwFlags = TME_LEAVE;
        tme.hwndTrack = hwnd;
    case WM_MOUSELEAVE: g_fMouseInClient = FALSE; return 0;
    HANDLE_MSG(hwnd, WM_MOUSEMOVE, OnMouseMove);

This program beeps whenever the mouse enters the client area.

Exercise: If the program starts with the mouse already in the client area without moving, why do you get a beep?

Comments (6)
  1. Damit says:

    Is it because g_fMouseInClient is initialized to 0 (FALSE) ?

  2. Raymond Chen says:

    That’s half of it. But the mouse never moved, so why does it beep?

  3. YOu explained it two weeks ago in your post "Why do I get spurious WM_MOUSEMOVE messages?": "Often, Windows wants to do that follow-on work even though the mouse hasn’t actually moved. The most obvious example is when a window is shown, hidden or moved."

  4. Ian Hanschen says:

    just taking a stab at it..

    When an app calls GetMessage(), the WM not only dispatches messages from other threads and clears out the message queue, but it also checks the system input queue. <guessing part because I’ve not verified> This code checks the win32thread structure for the timestamp of the last mouse message sent. If it is 0, or does not match, a WM_MOUSEMOVE input message with the current timestamp is pushed onto the message queue.

  5. Dmitriy Zaslavskiy says:

    Sorry for off topic question, could you blog about using user API from multiple theads, and GUI api (i.e. painting from multiple threads onto the same window). Normally user handles are scopped by desktop and so it seems that multiple threads are already using user/gui subsystems from multiple threads, yet there are some API such as DestroyWindow that require explicitly to be called from the creator thread. There are also some info about "trying" not creating parent/child windows from diff. threads.
    Could you comment on the source of all that. Is GDI/USER code multithread safe or not?
    Thanks in advance.

  6. Karl says:

    I would assume Windows sends a WM_MOUSEMOVE to apps on startup if the cursor is inside the client area because some apps need to know the position of the mouse cursor whenever it is inside the client area to maintain a consistant user experience. For example, if you launch a web browser with a page that has a link directly under the mouse cursor, you’d expect the cursor to change immediately to indicate it’s a link.

Comments are closed.