Drag-and-drop, PreFilterMessage in endless loop

D

david

I am trying to implement simple(!) drag and drop on a Windows
UserControl. I want to use Windows messages directly (using
PreFilterMessage) to do this, rather than simple MouseDown/Move/Up
event handling, due to other constraints in the system.

The problem I have is that once I handle a MouseMove (0x200) message,
the same message is dropped into my PreFilterMessage in an endless
loop.

Worse, the message keeps getting handled so the system believes the
Cursor.Position is still moving even though it is not.

Example:
-I click the component at 200,200.
-I move the mouse 1 pixel up.
-My PreFilterMessage function catches the mouse move, relocates the
control to Cursor.Position, which is 200,199.
-PreFilterMessage returns false. (I've also tried true.)
-The PreFilterMessage function then runs again with the same message.
This time through, the Cursor.Position is set to 200,198.
-The same process continues running as long as I hold the mouse button
down--but without moving the mouse! The Cursor.Position keeps pointing
to a new location even though the mouse isn't moving. Eventually, the
Cursor.Position will be 200,-1000.

Can anyone tell me what I'm doing wrong in the following code and what
I need to do in order to stop processing the same message over and
over?

tia,
david

public class ControlBase : System.Windows.Forms.UserControl,
IMessageFilter
{

#region Internal Declarations
protected bool m_IsMouseDown;
private Point m_StartingLocation, m_StartingLocationScreen;
const int WM_MOUSEMOVE = 0x200;
const int WM_LBUTTONUP = 0x202;
#endregion

public bool PreFilterMessage(ref Message m)
{
if (m_IsMouseDown && m.Msg == WM_MOUSEMOVE)
{
Point _MousePosition = this.PointToScreen(Cursor.Position);
int x = _MousePosition.X - m_StartingLocationScreen.X;
int y = _MousePosition.Y - m_StartingLocationScreen.Y;

Debug.WriteLine("mouse: " + _MousePosition.X.ToString() + ", " +
_MousePosition.Y.ToString());
Debug.WriteLine("delta: " + x.ToString() + ", " + y.ToString());

Point _NewLocation = new Point(m_StartingLocation.X + x,
m_StartingLocation.Y + y);
this.Location = _NewLocation;
this.Invalidate();
}
return false;
}

#region Draggable Events

protected virtual void ControlBase_MouseUp(Object o, MouseEventArgs
e)
{
m_IsMouseDown = false;
}
private void ControlBase_MouseDown(object sender,
System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
m_IsMouseDown = true;
}
}
#endregion

public ControlBase()
{
//Add event handlers
this.MouseDown +=new MouseEventHandler(ControlBase_MouseDown);
this.MouseUp += new MouseEventHandler(ControlBase_MouseUp);
Application.AddMessageFilter(this);
}
}
}
 
L

Lloyd Dupont

it looks like it might be a windows bug?
you move => your relative position to the cursor change => it trigger a
mouse move

anyway, the 'recursive call' aside, I'm not surprised of your weird
values...
what is this PointToScreem doing there?

I strongly advise you to change all your location updating code to this
simpler version (using, appropriately, PointToClient)
this.Location = Parent.PointToClient(Cursor.Position)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top