PC Review


Reply
Thread Tools Rate Thread

Cascading MouseMove Events

 
 
Crucifix
Guest
Posts: n/a
 
      26th Sep 2005
Hello,

I'm writing a small C# app, and part of what I'm trying to do
involves the dragging of PictureBox controls on a form. Unfortunately,
MouseMove seems to be behaving very oddly, causing spurious MouseMove
events when the cursor doesn't actually move. I've looked for a
solution in the groups, and although I've come close, I haven't found a
proper explanation or fix. Here is a rundown, followed by a very
simple test app that reproduces the issue:

The concept is simple. There's a PictureBox control, which is
subscribed to the MouseDown, MouseMove, and MouseUp events. The user
clicks (and holds) a PictureBox, which triggers the MouseDown event.
The event handler updates two private member variables which contain
(1) a reference to the PictureBox object, and (2) a Point struct
defining the location (origin) of the PictureBox object when it was
clicked.

The user then drags the control, and the MouseMove event is
triggered, which checks if the PictureBox reference is null - if it is,
it does nothing, if it is not, it offsets the location of the
PictureBox according to its origin, and the X/Y coordinates of the
mouse.

The MouseUp event simply sets the reference to the PictureBox to
null, so that no more MouseMove events are triggered, and the
PictureBox is left where it is.

When this app runs, and the user clicks and drags the PictureBox,
many MouseMove events are called - it seems that moving the PictureBox
triggers another MouseMove, but why? I've reduced the effect somewhat
by adding a check in MouseMove to see if the cursor position has
changed - this stops the cascading events, but it doesn't stop the
PictureBox control from drawing itself at two different locations
(flickering) as I move it around. (I'm sure double-buffering would fix
that, but I'd like to address the real problem).

Your help is much appreciated!



using System;
using System.Drawing;
using System.Windows.Forms;

namespace MouseMoveTest
{
public class MouseMoveTest : System.Windows.Forms.Form
{
private System.Windows.Forms.PictureBox tomatoBox;
private System.Windows.Forms.PictureBox tomatoBox_Dragging;
private Point tomatoBox_Origin;

private Point mouseLocation = new Point(0,0);

private System.ComponentModel.Container components = null;

public MouseMoveTest()
{
this.SuspendLayout();

this.Name = "MouseMove Test Form";
this.Text = this.Name;
this.ClientSize = new System.Drawing.Size(512, 512);

this.tomatoBox = new System.Windows.Forms.PictureBox();
this.tomatoBox.BackColor = System.Drawing.Color.Tomato;
this.tomatoBox.Location = new System.Drawing.Point(160, 144);
this.tomatoBox.Name = "tomatoBox";
this.tomatoBox.Size = new System.Drawing.Size(64, 64);
this.tomatoBox.TabIndex = 0;
this.tomatoBox.TabStop = false;
this.tomatoBox.MouseUp += new
System.Windows.Forms.MouseEventHandler(this.tomatoBox_MouseUp);
this.tomatoBox.MouseMove += new
System.Windows.Forms.MouseEventHandler(this.tomatoBox_MouseMove);
this.tomatoBox.MouseDown += new
System.Windows.Forms.MouseEventHandler(this.tomatoBox_MouseDown);

this.Controls.Add(this.tomatoBox);

this.ResumeLayout(false);
}

protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

[STAThread]
static void Main()
{
Application.Run( new MouseMoveTest() );
}


private void tomatoBox_MouseUp(object sender,
System.Windows.Forms.MouseEventArgs e)
{
Console.WriteLine( "MouseUp: " + e.X + "," + e.Y );

tomatoBox_Dragging = null;
}

private void tomatoBox_MouseDown(object sender,
System.Windows.Forms.MouseEventArgs e)
{
Console.WriteLine( "MouseDown: " + e.X + "," + e.Y );

tomatoBox_Dragging = (sender as PictureBox );
tomatoBox_Origin = new Point( tomatoBox.Location.X,
tomatoBox.Location.Y );

Console.WriteLine( "Origin is: " + tomatoBox_Origin );
}

private void tomatoBox_MouseMove(object sender,
System.Windows.Forms.MouseEventArgs e)
{
Console.WriteLine( "MouseMove: " + e.X + "," + e.Y );

// Only proceed if mouse position has changed.
/*
if ( mouseLocation.Equals(Cursor.Position) )
return;
else
mouseLocation = Cursor.Position;
*/

if ( tomatoBox_Dragging != null )
{
tomatoBox_Dragging.Left = tomatoBox_Origin.X + e.X;
tomatoBox_Dragging.Top = tomatoBox_Origin.X + e.Y;
}
}
}
}

 
Reply With Quote
 
 
 
 
Michael C
Guest
Posts: n/a
 
      26th Sep 2005
"Crucifix" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Hello,
>
> I'm writing a small C# app, and part of what I'm trying to do
> involves the dragging of PictureBox controls on a form. Unfortunately,
> MouseMove seems to be behaving very oddly, causing spurious MouseMove
> events when the cursor doesn't actually move. I've looked for a
> solution in the groups, and although I've come close, I haven't found a
> proper explanation or fix. Here is a rundown, followed by a very
> simple test app that reproduces the issue:


Put this code back in and it works perfectly. You need to store the point
that the mouse clicked on the picturebox, not the original location of the
picturebox. And you should use Location instead of Left and Top so that it
is only moved once.
tomatoBox_Origin = new Point( e.X, e.Y );

if ( tomatoBox_Dragging != null )

{

tomatoBox_Dragging.Location = new Point(tomatoBox_Dragging.Left + e.X -
tomatoBox_Origin.X, tomatoBox_Dragging.Top +e.Y - tomatoBox_Origin.Y);

}



Michael


>
> The concept is simple. There's a PictureBox control, which is
> subscribed to the MouseDown, MouseMove, and MouseUp events. The user
> clicks (and holds) a PictureBox, which triggers the MouseDown event.
> The event handler updates two private member variables which contain
> (1) a reference to the PictureBox object, and (2) a Point struct
> defining the location (origin) of the PictureBox object when it was
> clicked.
>
> The user then drags the control, and the MouseMove event is
> triggered, which checks if the PictureBox reference is null - if it is,
> it does nothing, if it is not, it offsets the location of the
> PictureBox according to its origin, and the X/Y coordinates of the
> mouse.
>
> The MouseUp event simply sets the reference to the PictureBox to
> null, so that no more MouseMove events are triggered, and the
> PictureBox is left where it is.
>
> When this app runs, and the user clicks and drags the PictureBox,
> many MouseMove events are called - it seems that moving the PictureBox
> triggers another MouseMove, but why? I've reduced the effect somewhat
> by adding a check in MouseMove to see if the cursor position has
> changed - this stops the cascading events, but it doesn't stop the
> PictureBox control from drawing itself at two different locations
> (flickering) as I move it around. (I'm sure double-buffering would fix
> that, but I'd like to address the real problem).
>
> Your help is much appreciated!
>
>
>
> using System;
> using System.Drawing;
> using System.Windows.Forms;
>
> namespace MouseMoveTest
> {
> public class MouseMoveTest : System.Windows.Forms.Form
> {
> private System.Windows.Forms.PictureBox tomatoBox;
> private System.Windows.Forms.PictureBox tomatoBox_Dragging;
> private Point tomatoBox_Origin;
>
> private Point mouseLocation = new Point(0,0);
>
> private System.ComponentModel.Container components = null;
>
> public MouseMoveTest()
> {
> this.SuspendLayout();
>
> this.Name = "MouseMove Test Form";
> this.Text = this.Name;
> this.ClientSize = new System.Drawing.Size(512, 512);
>
> this.tomatoBox = new System.Windows.Forms.PictureBox();
> this.tomatoBox.BackColor = System.Drawing.Color.Tomato;
> this.tomatoBox.Location = new System.Drawing.Point(160, 144);
> this.tomatoBox.Name = "tomatoBox";
> this.tomatoBox.Size = new System.Drawing.Size(64, 64);
> this.tomatoBox.TabIndex = 0;
> this.tomatoBox.TabStop = false;
> this.tomatoBox.MouseUp += new
> System.Windows.Forms.MouseEventHandler(this.tomatoBox_MouseUp);
> this.tomatoBox.MouseMove += new
> System.Windows.Forms.MouseEventHandler(this.tomatoBox_MouseMove);
> this.tomatoBox.MouseDown += new
> System.Windows.Forms.MouseEventHandler(this.tomatoBox_MouseDown);
>
> this.Controls.Add(this.tomatoBox);
>
> this.ResumeLayout(false);
> }
>
> protected override void Dispose( bool disposing )
> {
> if( disposing )
> {
> if (components != null)
> {
> components.Dispose();
> }
> }
> base.Dispose( disposing );
> }
>
> [STAThread]
> static void Main()
> {
> Application.Run( new MouseMoveTest() );
> }
>
>
> private void tomatoBox_MouseUp(object sender,
> System.Windows.Forms.MouseEventArgs e)
> {
> Console.WriteLine( "MouseUp: " + e.X + "," + e.Y );
>
> tomatoBox_Dragging = null;
> }
>
> private void tomatoBox_MouseDown(object sender,
> System.Windows.Forms.MouseEventArgs e)
> {
> Console.WriteLine( "MouseDown: " + e.X + "," + e.Y );
>
> tomatoBox_Dragging = (sender as PictureBox );
> tomatoBox_Origin = new Point( tomatoBox.Location.X,
> tomatoBox.Location.Y );
>
> Console.WriteLine( "Origin is: " + tomatoBox_Origin );
> }
>
> private void tomatoBox_MouseMove(object sender,
> System.Windows.Forms.MouseEventArgs e)
> {
> Console.WriteLine( "MouseMove: " + e.X + "," + e.Y );
>
> // Only proceed if mouse position has changed.
> /*
> if ( mouseLocation.Equals(Cursor.Position) )
> return;
> else
> mouseLocation = Cursor.Position;
> */
>
> if ( tomatoBox_Dragging != null )
> {
> tomatoBox_Dragging.Left = tomatoBox_Origin.X + e.X;
> tomatoBox_Dragging.Top = tomatoBox_Origin.X + e.Y;
> }
> }
> }
> }
>



 
Reply With Quote
 
Crucifix
Guest
Posts: n/a
 
      26th Sep 2005
Michael,

The code you responded with works perfectly! The effective
difference between your code and mine is that the new location of the
object is calculated differently (if I calculate the origin
incorrectly, it still works, just the image starts out in the wrong
place).

I'm really interested to know why setting the new location
(incorrectly) caused this problem. Do you (or does anyone else
reading) know why this is? I would have assumed that it would just put
my object in the wrong place... not result in cascading events.

Thank-you very much for your time Michael.

-David

Michael C wrote:

> Put this code back in and it works perfectly. You need to store the point
> that the mouse clicked on the picturebox, not the original location of the
> picturebox. And you should use Location instead of Left and Top so that it
> is only moved once.
> tomatoBox_Origin = new Point( e.X, e.Y );
>
> if ( tomatoBox_Dragging != null )
>
> {
>
> tomatoBox_Dragging.Location = new Point(tomatoBox_Dragging.Left + e.X -
> tomatoBox_Origin.X, tomatoBox_Dragging.Top +e.Y - tomatoBox_Origin.Y);
>
> }


 
Reply With Quote
 
Michael C
Guest
Posts: n/a
 
      26th Sep 2005
"Crucifix" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> I'm really interested to know why setting the new location
> (incorrectly) caused this problem. Do you (or does anyone else
> reading) know why this is? I would have assumed that it would just put
> my object in the wrong place... not result in cascading events.


Moving the control under the mouse will cause a mouse move event I believe,
so it's very easy to get the events firing repeatedly if your code isn't
moving the control to the correct location. I think you'll still get the
event firing repeatedly with the changes I made but the second time it fires
it will move the control to the same location so won't fire a third time.

> Thank-you very much for your time Michael.


No worries, it took about 5 minutes as I worked on this exact problem about
a week ago :-)

Michael


 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Strategies for controlling cascading events for interdependent controls on a form? Joergen Bech Microsoft VB .NET 4 19th Jun 2007 07:24 PM
Q: cascading events not working? Matt C. Microsoft ASP .NET 0 26th Jun 2006 06:11 PM
MouseDown, MouseMove & MouseUp Events doesn't work with HScrollBar =?Utf-8?B?VGlzbW9K?= Microsoft Dot NET Compact Framework 3 28th Mar 2005 06:04 PM
Cascading events down to child controls Scott McChesney Microsoft Dot NET 0 5th May 2004 08:48 PM
ItemsSelected.Count on MouseUp and MouseMove Events Ronald Dodge Microsoft Access Form Coding 2 30th Sep 2003 01:15 PM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 06:27 AM.