dotnet windows forms:
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); } } }
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)
Don't see what you're looking for? Try a search.
|