dlgrasse

I'm new to C# programming, learning it for pleasure on my own time. As an exercise, I'm creating a simple Windows program that 1) takes the mouse-down event as an 'anchor' point, 2) while dragging the mouse around continually draw a line from that anchor point to the current mouse position, 3) once the mouse-up occurs, shrink the resulting line down automatically until it disappears. Not too hard, and it works perfectly fine.

My problem is that I do not want the Form to accept any mouse-down's while the shrinking logic is occurring. Currently, while the line is shrinking, I can do some more click-and-drags, and once the shrinking completes, those subsequent lines are drawn/shrunk in like fashion. I want to effectively ignore any mouse-down's while the shrinking logic is happening.

The techniques I've tried so far are: 1) set/reset a boolean flag in the mouse-down and mouse-up handler methods, 2) don't override OnMouseDown in favor of registering my on event handler method and using -= and += on the MouseDown event around the shrinking method. Neither of these seem to work. It's as if the mouse events are queue-up by the OS during my shrinking loop and there's no way to completely ignore them.

I haven't been able to find an answer in my searches. Any ideas

dlgrasse



Re: Visual C# General ignore mouse down event

Paul Louth

Surely using your own boolean flag will work

private void Form1_MouseDown(object sender, MouseEventArgs e)
{
if (mouseDragEnabled)
{
// do your mouse handling here
}
}

You have total control of the boolean flag, so I don't see how it can't be working, unless your code inadvertantly sets it to false when you don't realise.





Re: Visual C# General ignore mouse down event

GavH

If you overide OnMouseDown and then choose not to pass the MouseEventArgs down to the Base, you will in effect prevent the MouseDownEvent from firing.

You need a mouseLock bollean that will set to true when your shrinking procedure is running and set to false once it has finished. Whilst the mouseLock is set mouse down events will not be passed onto the base.

private bool bMouseLock = false;

protected override void OnMouseDown(MouseEventArgs e)
{
if(!bMouseLock)
base.OnMouseDown(e);
}

Hope That Helps

Regards






Re: Visual C# General ignore mouse down event

GavH

The simple bollean method Paul suggests is even better, because it wont effect other mouse activity on the interface.

Perhaps we are not clear on what you are trying to achieve

Regards






Re: Visual C# General ignore mouse down event

dlgrasse

I think each of you understand what I'm trying to do, and thank each of you for your replies.

Unless I'm really missing something simple, the flag check simply doesn't work. Here's a paste of the three mouse-event-related methods within my Form subclass.

protected override void OnMouseDown (MouseEventArgs me)
{
if (!myMouseDown)
{
myMouseDown = true;

myFromX = me.X;
myFromY = me.Y;
}
}
// only re-draw while dragging
protected override void OnMouseMove (MouseEventArgs me)
{

if (myMouseDown)
{
myToX = me.X;
myToY = me.Y;

Refresh ();
}
}

protected override void OnMouseUp (MouseEventArgs me)
{
Diminish ();

myMouseDown = false;
}

dlgrasse





Re: Visual C# General ignore mouse down event

GavH

The problem could be your OmMouseUp override, the mouseup still fires even though MouseDown is being ignored. so Diminish is called multiple times on mouseup events even if the previous Diminsh has yet to finish.

I would try changing the MouseUp override to :

bool myDiminishLock = false;

protected override void OnMouseUp (MouseEventArgs me)
{
  
if (!myDiminishLock)
   {
         myDiminishLock = true;
    Diminish ();
        myDiminishLock = false;
   }
}

I think that is what you are looking for.

Regards





Re: Visual C# General ignore mouse down event

dlgrasse

I understand what you're saying and had tried that in one of my many permutations. It doesn't work. I was also worried that maybe it was the mouse-move events that were being picked up during the Diminish logic since myMouseDown wasn't set to false until after Diminish completed (thereby queueing up the mouse-move events), but some Console.WriteLines continue to show that the mouse-down's are being deferred until Diminish completes.

My code really isn't too long, so I've presumptuously pasted the entire thing here. It includes my current state of things, including the 'diminish lock' technique just recommended. It's got to be something simple. Maybe a well placed base-method call in my overriddent event handlers Maybe a flag not being set correctly Maybe some other technique to ignore mouse-down's specifically I'm stumped. Within this code you'll see the Console.WriteLines that show that the mouse-down's and mouse-move's are not being handled until after Diminish completes. (Try dragging the mouse a few times while the line diminishes.)

dlgrasse

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

namespace dlg
{
public class DrawLine : Form
{
private float myFromX;
private float myFromY;
private int myToX;
private int myToY;
private bool myMouseDown;
private bool myIsDiminishing;

private DrawLine ()
{
Height = 400;
Width = 600;
BackColor = Color.White;
FormBorderStyle = FormBorderStyle.FixedSingle;
DoubleBuffered = true;
}

protected override void OnMouseDown (MouseEventArgs me)
{
if (!myMouseDown)
{
Console.WriteLine ("#OnMouseDown");
myMouseDown = true;

myFromX = me.X;
myFromY = me.Y;
myToX = me.X;
myToY = me.Y;
}
}

protected override void OnMouseMove (MouseEventArgs me)
{
if (myMouseDown)
{
Console.WriteLine ("#OnMouseMove");
myToX = me.X;
myToY = me.Y;

// don't let the line get past, or too close to, the edge
myToX = (myToX < ClientSize.Width-10) myToX : ClientSize.Width-10;
myToY = (myToY < ClientSize.Height-10) myToY : ClientSize.Height-10;
myToX = (myToX > 10) myToX : 10;
myToY = (myToY > 10) myToY : 10;

Refresh ();
}
}

protected override void OnMouseUp (MouseEventArgs me)
{
if (!myIsDiminishing)
{
Console.WriteLine ("#OnMouseUp");
myIsDiminishing = true;
Diminish ();
myIsDiminishing = false;

myMouseDown = false;
}
}

private void Diminish ()
{
// determine the angle of the current line
// so the diminish follows the same course
float diffX = (float)myToX - myFromX;
float diffY = (float)myToY - myFromY;

float denom = Math.Abs ((Math.Abs(diffX) > Math.Abs (diffY)) diffX : diffY);
float xRatio = (diffX/denom);
float yRatio = (diffY/denom);

Console.WriteLine ("xRatio {0} yRatio {1}", xRatio, yRatio);

while ((myToX != (int)myFromX) || (myToY != (int)myFromY))
{
if (myToX != (int)myFromX)
{
myFromX+=xRatio;
}
if (myToY != (int)myFromY)
{
myFromY+=yRatio;
}

Thread.Sleep (5);
Refresh ();
}
}

protected override void OnPaint (PaintEventArgs pea)
{
pea.Graphics.DrawLine (Pens.Black, new Point ((int)myFromX, (int)myFromY), new Point (myToX, myToY));
}

public static void Main ()
{
// Application.EnableVisualStyles ();

Application.Run (new DrawLine ());
}
}
}





Re: Visual C# General ignore mouse down event

GavH

Hi,

In your Diminish method you are running through an intensive while loop, which will basicly block events until it has completed. You could use the line:

Application.DoEvents();

Within that line and it will ensure that events continue to be processed, and ignored as required, else they will all fire when the loop completes.

See if that fixes the problem you are seeing, I am fairly conifident it will.

Regards





Re: Visual C# General ignore mouse down event

GavH

Sorry in the above I meant to say add the line Application.DoEvents() to your while loop.

Regards





Re: Visual C# General ignore mouse down event

dlgrasse

Application.DoEvent - I'll have to keep that method in mind. I added it to the while loop and indeed that worked. I tried it in a couple of other places (at the start of Diminish, etc) and observed varying degrees of incorrect behavior. I don't completely understand the behavior of that method - it seems to take effect only with the scope in which it's called As I said, I'll have to investigate that method some more.

But concentrating on your observation of my while loop blocking all events, I decided to go with a different tactic - starting Diminish as a separate thread. With my other flags correctly in place, this gave me the exact behavior I wanted: the mouse events are not blocked and queued, yet other events are allowed to occur that DoEvent was stopping. For instance, with DoEvent I couldn't move my window until Diminish completed. The threaded technique lets that occur.

So many thanks for the time, effort, and direction.

dlgrasse





Re: Visual C# General ignore mouse down event

GavH

Hi dlgrasse,

You are certainly getting into C# for a hobbiest, good to see :)

Yes a worker thread is the preferred way of performing intensive operations, anything you run in the form class runs on the UI thread, which is why the events pause during a loop operation.

Regards





Re: Visual C# General ignore mouse down event

dlgrasse

That makes perfect sense. I guess I was thinking the UI thread was separate.

And yes, I'm doing this as a hobby - much to my wife's chagrin. I'm a software developer by trade, so my hobby just keeps me in front of the screen that much more :-)

Again, thanks.

dlgrasse