Why huge amount of WM_MOUSEMOVE when listbox is clicked?

Answers to frequently asked questions about Phoenix.
TechSupport
Site Admin
Posts: 809
Joined: Tue Sep 14, 2004 7:55 pm
Location: Mississauga ON, Canada

Why huge amount of WM_MOUSEMOVE when listbox is clicked?

Postby TechSupport » Wed May 23, 2007 11:25 am

Question
If I place a MSGBOX within the WM_MOUSEMOVE function of a List box and
press left mousebutton onto an item of that List box, then I get a huge
amount of MOUSEMOVE messages. I definitely do not move the mouse, just
press the left mouse button!
Is that a normal behavior and if yes, can I prevent it?

Answer
It is normal behaviour, because the mouse does not actually have to move
to cause a WM_MOUSEMOVE message to be generated. For example, the following
code used to reset the pointer does not move the mouse but still generates
a WM_MOUSEMOVE message:

Code: Select all

GetCursorPos tpt
SetCursorPos tpt.x, tpt.y

Also, actions taken by the user can cause WM_MOUSEMOVE messages to be generated
even though the pointer appears to remain in the same location on the screen.
This is because when the pointer is over a window, a WM_MOUSEMOVE message is
generated if the window is moved programmatically or by some other means. A
WM_MOUSEMOVE message is also generated when the Z-Order of the window changes.
This last reason has important consequences (read runaway recursion) for the
launching of secondary windows from a WM_MOUSEMOVE handler. As a result,
displaying a secondary window (e.g. MsgBox) from the handler can lead to a stack
fault.

You might also want to read the post by Raymond Chen at

http://blogs.msdn.com/oldnewthing/archi ... 55108.aspx

Notwithstanding the above, simply pressing and releasing the left mouse button
does not normally cause a WM_MOUSEMOVE message to be generated. The list box is
doing something to cause this message to be generated. In fact, most controls
that allow user interaction via the mouse will exhibit this behaviour.
When coding a control, it is normal to write code similar to that shown below in
response to the WM_LBUTTONDOWN and WM_LBUTTONUP messages.

Code: Select all

'-------------------------------------------------------------------------------

FUNCTION Form1_OnLButtonDown _
  ( _
  BYVAL hWnd  AS DWORD, _ ' window handle
  BYVAL fKeys AS LONG, _  ' key flags
  BYVAL x     AS LONG, _  ' horizontal position of cursor
  BYVAL y     AS LONG _   ' vertical position of cursor
  ) AS LONG

  IF GetCapture() <> hWnd THEN SetCapture hWnd
 
END FUNCTION

'-------------------------------------------------------------------------------

FUNCTION Form1_OnLButtonUp _
  ( _
  BYVAL hWnd  AS DWORD, _ ' window handle
  BYVAL fKeys AS LONG, _  ' key flags
  BYVAL x     AS LONG, _  ' horizontal position of cursor
  BYVAL y     AS LONG _   ' vertical position of cursor
  ) AS LONG

  IF GetCapture() = hWnd THEN ReleaseCapture
 
END FUNCTION


This code combination causes a WM_MOUSEMOVE message to be generated when
ReleaseCapture is called.

One way to detect this spurious WM_MOUSEMOVE message generated by the code shown
above is to determine when the mouse has actually moved. The solution is to check
in your WM_MOUSEMOVE handler that the mouse position is different from the position
reported by the previous WM_MOUSEMOVE message. This will prevent a possible stack
fault when the left mouse button is clicked and a secondary window is displayed
during the WM_MOUSEMOVE message. For example,

Code: Select all

GLOBAL  g_tpt         AS POINTAPI

'-------------------------------------------------------------------------------

FUNCTION Form1_OnCreate _
  ( _
  BYVAL hWnd        AS DWORD, _ ' window handle
  BYVAL lptcs       AS DWORD, _ ' address of CREATESTRUCT structure
        lMsgResult  AS LONG _   ' value returned to message
  ) AS LONG

  g_tpt.x = -32767
  g_tpt.y = -32767
 
END FUNCTION

'-------------------------------------------------------------------------------

FUNCTION Form1_List1_OnMouseMove _
  ( _
  BYVAL hWnd  AS DWORD, _ ' control handle
  BYVAL fKeys AS LONG, _  ' key flags
  BYVAL x     AS LONG, _  ' horizontal position of cursor
  BYVAL y     AS LONG _   ' vertical position of cursor
  ) AS LONG

  IF (x <> g_tpt.x) OR (y <> g_tpt.y) THEN 
    g_tpt.x = x
    g_tpt.y = y   
    MSGBOX "WM_MOUSEMOVE"
  END IF
 
END FUNCTION

'-------------------------------------------------------------------------------

FUNCTION Form1_List1_OnLButtonUp _
  ( _
  BYVAL hWnd  AS DWORD, _ ' control handle
  BYVAL fKeys AS LONG, _  ' key flags
  BYVAL x     AS LONG, _  ' horizontal position of cursor
  BYVAL y     AS LONG _   ' vertical position of cursor
  ) AS LONG

  g_tpt.x = -32767
  g_tpt.y = -32767
 
END FUNCTION

Return to “Frequently Asked Questions”

Who is online

Users browsing this forum: No registered users and 1 guest