Why do I get spurious WM_MOUSEMOVE messages?

Date:October 1, 2003 / year-entry #78
Tags:code
Orig Link:https://blogs.msdn.microsoft.com/oldnewthing/20031001-00/?p=42343
Comments:    8
Summary:In order to understand this properly, it helps to know where WM_MOUSEMOVE messages come from. When the hardware mouse reports an interrupt, indicating that the physical mouse has moved, Windows determines which thread should receive the mouse move message and sets a flag on that thread's input queue that says, "The mouse moved, in case...

In order to understand this properly, it helps to know where WM_MOUSEMOVE messages come from.

When the hardware mouse reports an interrupt, indicating that the physical mouse has moved, Windows determines which thread should receive the mouse move message and sets a flag on that thread's input queue that says, "The mouse moved, in case anybody cares." (Other stuff happens, too, which we will ignore here for now. In particular, if a mouse button event arrives, a lot of bookkeeping happens to preserve the virtual input state.)

When that thread calls a message retrieval function like GetMessage, and the "The mouse moved" flag is set, Windows inspects the mouse position and does the work that is commonly considered to be part of mouse movement: Determining the window that should receive the message, changing the cursor, and determining what type of message to generate (usually WM_MOUSEMOVE or perhaps WM_NCMOUSEMOVE).

If you understand this, then you already see the answer to the question, "Why does my program not receive all mouse messages if the mouse is moving too fast?"

If your program is slow to call GetMessage, then multiple mouse interrupts may arrive before your program calls GetMessage to pick them up. Since all that happens when the mouse interrupt occurs is that a flag is set, if two interrupts happen in succession without a message retrieval function being called, then the second interrupt will merely set a flag that is already set, which has no effect. The net effect is that the first interrupt acts as if it has been "lost" since nobody bothered to pick it up.

You should also see the answer to the question, "How fast does Windows deliver mouse movement messages?"

The answer is, "As fast as you want." If you call GetMessage frequently, then you get mouse messages frequently; if you call GetMessage rarely, then you get mouse messages rarely.

Okay, so back to the original question, "Why do I get spurious WM_MOUSEMOVE messages?"

Notice that the delivery of a mouse message includes lots of work that is typically thought of as being part of mouse movement. 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. When that happens, the mouse cursor may be over a window different from the window it was over previously (or in the case of a move, it may be over a different part of the same window). Windows needs to recalculate the mouse cursor (for example, the old window may have wanted an arrow but the new window wants a pointy finger), so it artificially sets the "The mouse moved, in case anybody cares" flag. This causes all the follow-on work to happen, a side-effect of which is the generation of a spurious WM_MOUSEMOVE message.

So if your program wants to detect whether the mouse has moved, you need to add a check in your WM_MOUSEMOVE that the mouse position is different from the position reported by the previous WM_MOUSEMOVE message.


Comments (8)
  1. PeterM says:

    Interesting. I’m still a bit confused though. You say that Windows sends extra WM_MOUSEMOVE messages for things like showing, hiding, etc. However, if you use Spy++ and monitor pretty much any window, you’ll see that even if the mouse is just sitting over the window (without moving), that window gets about two WM_MOUSEMOVE message every second. What sort of things does Windows need to do when the mouse is stationary?

    So, is this basically a case where new functions got grafted onto the OS and the programmers found that WM_MOUSEMOVE was a convenient place to hook into without causing compatibility problems?

  2. Raymond Chen says:

    I’m not getting any WM_MOUSEMOVE messages when the machine is idle and the mouse isn’t moving. Perhaps there is some "mouse enhancement" program that is causing this.

  3. I got bit badly by this on a custom project a while back. I needed to detect when the user was not doing anything with the computer, so I installed systemwide hooks to watch for keyboard and mouse messages. It worked fine except in some rare situations. Finally we figured out that my code was getting tripped up when an OpenGL screen saver was running: It was getting WM_MOUSEMOVE messages repeatedly at the same cursor position. So I put in the test to see if the mouse position had actually changed, and all was well after that.

  4. PeterM says:

    I went and tried the Spy++ experiment again today. For some reason, I had very little activity. I will check this out from time to time to see if I can find any reason why I had 2 WM_MOUSEMOVE messages a second yesterday (with the mouse stationary) and only one every few seconds today. As for "mouse enhancement", I’m not running anything I’m aware of. I’ll double check and see what I can find.

  5. Simon Alford says:

    I had this problem. I was getting at least 2 WM_MOUSEMOVE messages every second to any window in my application when the mouse was over it, even if the mouse was not moving.

    Could not track down the problem any where.

    After about an hour or two of trying (and reading this page) I noticed PeterM had the problem go away the next day.

    I went for a total restart of my machine, and Dev environment, and the problem went away. I suspect that it was either a problem with the Dev Environment (MSVC++), or something deeper in the OS.

    If you get this problem, i sugest you try a restart before spending 2 hours on trying to find the cause.

  6. Li Xiong says:

    Problem Description: A customer called in, complained angrily. “A call to ShellExecute API, passing in

  7. Warren Tang says:

    MessageQueue TheAlgorithmforExtractingMessagesfromaThread’sQueue

Comments are closed.


*DISCLAIMER: I DO NOT OWN THIS CONTENT. If you are the owner and would like it removed, please contact me. The content herein is an archived reproduction of entries from Raymond Chen's "Old New Thing" Blog (most recent link is here). It may have slight formatting modifications for consistency and to improve readability.

WHY DID I DUPLICATE THIS CONTENT HERE? Let me first say this site has never had anything to sell and has never shown ads of any kind. I have nothing monetarily to gain by duplicating content here. Because I had made my own local copy of this content throughout the years, for ease of using tools like grep, I decided to put it online after I discovered some of the original content previously and publicly available, had disappeared approximately early to mid 2019. At the same time, I present the content in an easily accessible theme-agnostic way.

The information provided by Raymond's blog is, for all practical purposes, more authoritative on Windows Development than Microsoft's own MSDN documentation and should be considered supplemental reading to that documentation. The wealth of missing details provided by this blog that Microsoft could not or did not document about Windows over the years is vital enough, many would agree an online "backup" of these details is a necessary endeavor. Specifics include:

<-- Back to Old New Thing Archive Index