Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. Other Discussions
  3. Clever Code
  4. Infinite Loop and Mouse Hooks [modified]

Infinite Loop and Mouse Hooks [modified]

Scheduled Pinned Locked Moved Clever Code
helptutorial
2 Posts 1 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    John Crenshaw
    wrote on last edited by
    #1

    The infinite loop is the classic bug, the bane of all programmers existence. I had a good one the other day that came down to this. It takes a bit of code to set up so I'll just nail the principles. 1) Set up a system wide mouse hook (I used a system wide hook but it ought to work with any mouse hook.) 2) Do something in the hook callback that requires a loop for a period of time. I don't care what, for me, I wanted some delay control requiring the mouse to hover over a certain point for a defined period. Here is a pseudo code example of what I did. POINT oldpoint = GetMousePoint(); DWORD starttime = TimeInMS(); while (GetMousePoint() == oldpoint && (starttime + DELAY > TimeInMS())) { ...do something... } 3) Since you are running a loop, and you don't want to be a processor hog, you have to yield some control to the processor. MS says to do this: MSG msg; PeekMessage(&msg, hwnd, NULL, NULL, PM_NOREMOVE); so the loop becomes: POINT oldpoint = GetMousePoint(); DWORD starttime = TimeInMS(); while (point == oldpoint && (starttime + DELAY < TimeInMS())) { ...do something... MSG msg; PeekMessage(&msg, hwnd, NULL, NULL, PM_NOREMOVE); } 4) Voila! It works, no 100% processor, hooked mouse, delay, perfect...except, under certain situations after CLICKING the mouse the program stops doing anything until the user MOVES the mouse. I'll let all the bright folks out there chew on this, solution in the next post. -- modified at 12:22 Monday 2nd April, 2007

    J 1 Reply Last reply
    0
    • J John Crenshaw

      The infinite loop is the classic bug, the bane of all programmers existence. I had a good one the other day that came down to this. It takes a bit of code to set up so I'll just nail the principles. 1) Set up a system wide mouse hook (I used a system wide hook but it ought to work with any mouse hook.) 2) Do something in the hook callback that requires a loop for a period of time. I don't care what, for me, I wanted some delay control requiring the mouse to hover over a certain point for a defined period. Here is a pseudo code example of what I did. POINT oldpoint = GetMousePoint(); DWORD starttime = TimeInMS(); while (GetMousePoint() == oldpoint && (starttime + DELAY > TimeInMS())) { ...do something... } 3) Since you are running a loop, and you don't want to be a processor hog, you have to yield some control to the processor. MS says to do this: MSG msg; PeekMessage(&msg, hwnd, NULL, NULL, PM_NOREMOVE); so the loop becomes: POINT oldpoint = GetMousePoint(); DWORD starttime = TimeInMS(); while (point == oldpoint && (starttime + DELAY < TimeInMS())) { ...do something... MSG msg; PeekMessage(&msg, hwnd, NULL, NULL, PM_NOREMOVE); } 4) Voila! It works, no 100% processor, hooked mouse, delay, perfect...except, under certain situations after CLICKING the mouse the program stops doing anything until the user MOVES the mouse. I'll let all the bright folks out there chew on this, solution in the next post. -- modified at 12:22 Monday 2nd April, 2007

      J Offline
      J Offline
      John Crenshaw
      wrote on last edited by
      #2

      OK, here's the solution. It has to do with an undocumented behavior of the mouse hooks. Although MS doesn't tell us so, a mouse hook is triggered when PeekMessage or GetMessage finds a mouse message on the queue. MS would have us believe that this hook has nothing to do with picking up the message, but it's not true. Normally these mouse messages only hit the queue for a window one at a time, however, if the mouse is CLICKED then TWO end up on the queue for the window. In the code above, the first message, WM_LBUTTONDOWN, gets processed by the hook, which then calls PeekMessage in it's loop. PeekMessage finds WM_LBUTTONUP in the queue, not that we care because we are really just telling windows not to write us off. However, Windows DOES care, since this next message was a mouse message, and queues up another call for the mouse hook to complete as soon as the current one is done. After exiting the current hook function call, Windows calls it again, this time for WM_LBUTTONUP, however, WM_LBUTTONUP was never removed from the message queue, so it is STILL the message that PeekMessage will find, queueing up another call for the current function. This happens infinitely, causing an infinite loop that prevents any other code in the application from running, but without taking up much processor time, or locking the user out, since moving the mouse upsets the delicate balance required to make this work. It creates a great bug though when the user clicks...and waits...and waits...and waits, and when they finally get impatient and move the mouse, the screen comes up. The fix is very simple. We don't care what PeekMessage finds, if anything, so change the two NULL parameters to WM_QUIT. This will make PeekMessage ONLY serve up any WM_QUIT messages that it finds (which it will do anyway no matter what.) Since no mouse messages are served up, the bug goes away.

      1 Reply Last reply
      0
      Reply
      • Reply as topic
      Log in to reply
      • Oldest to Newest
      • Newest to Oldest
      • Most Votes


      • Login

      • Don't have an account? Register

      • Login or register to search.
      • First post
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • World
      • Users
      • Groups