By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,266 Members | 1,816 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,266 IT Pros & Developers. It's quick & easy.

Cascading MouseMove Events

P: n/a
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.tomato Box_MouseUp);
this.tomatoBox.MouseMove += new
System.Windows.Forms.MouseEventHandler(this.tomato Box_MouseMove);
this.tomatoBox.MouseDown += new
System.Windows.Forms.MouseEventHandler(this.tomato Box_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;
}
}
}
}

Nov 17 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a
"Crucifix" <da***@davidfuchs.ca> wrote in message
news:11*********************@g44g2000cwa.googlegro ups.com...
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.tomato Box_MouseUp);
this.tomatoBox.MouseMove += new
System.Windows.Forms.MouseEventHandler(this.tomato Box_MouseMove);
this.tomatoBox.MouseDown += new
System.Windows.Forms.MouseEventHandler(this.tomato Box_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;
}
}
}
}

Nov 17 '05 #2

P: n/a
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);

}


Nov 17 '05 #3

P: n/a
"Crucifix" <da***@davidfuchs.ca> wrote in message
news:11*********************@g14g2000cwa.googlegro ups.com...
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
Nov 17 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.