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);
}
}
}
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);
}
}
}