c# - disable events during MouseDoubleClick - c#

Is it possible to disable other MouseEvent during a MouseDoubleClick event?
I've registered multiple events on a label but i want MouseDoubleClick is prioritary and block all other MouseEvent (es. MouseDown or MuoseMove). Then, after the DoubleClickHandler is finished i want to reactivate them.

You can create a flag to store your different states in order for your methods to know what they have to know.
A simple approach will be something like:
bool dblClickDone = false;
void DoubleClickHandler(...)
{
//...
dblClickDone = true;
}
void MouseDownHandler(...)
{
if (dblClickDone) {
//...
}
}
You get the idea.

Just unregister the events using "-=", example:
private void OnMouseDoubleClick(object sender, MouseEventArgs e)
{
this.MouseDown -= MethodOnMouseDown;
this.MouseMove -= MethodOnMouseMove;
// Do something.....
this.MouseDown += MethodOnMouseDown;
this.MouseMove += MethodOnMouseMove;
}

MSDN suggests two methods. The one you use will be based on the design of you program. I've copied the code from MSDN below in case the page goes down.
First method is to rollback any changes made that were made in the 'single click' event if the double click event is fired.
using System;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace MouseRollBackSingleClick
{
public class Form1 : Form
{
private DoubleClickButton button1;
private FormBorderStyle initialStyle;
public Form1()
{
initialStyle = this.FormBorderStyle;
this.ClientSize = new System.Drawing.Size(292, 266);
button1 = new DoubleClickButton();
button1.Location = new Point (40,40);
button1.Click += new EventHandler(button1_Click);
button1.AutoSize = true;
this.AllowDrop = true;
button1.Text = "Click or Double Click";
button1.DoubleClick += new EventHandler(button1_DoubleClick);
this.Controls.Add(button1);
}
// Handle the double click event.
void button1_DoubleClick(object sender, EventArgs e)
{
// Change the border style back to the initial style.
this.FormBorderStyle = initialStyle;
MessageBox.Show("Rolled back single click change.");
}
// Handle the click event.
void button1_Click(object sender, EventArgs e)
{
this.FormBorderStyle = FormBorderStyle.FixedToolWindow;
}
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}
}
public class DoubleClickButton : Button
{
public DoubleClickButton() : base()
{
// Set the style so a double click event occurs.
SetStyle(ControlStyles.StandardClick |
ControlStyles.StandardDoubleClick, true);
}
}
}
The second method is to create a timer which triggers when the single click is performed. If a double click is not followed within the timer limit, it's assumed the user wants to perform a single click and that action is taken, otherwise the double click action is taken.
using System;
using System.Drawing;
using System.Windows.Forms;
namespace SingleVersusDoubleClick
{
class Form1 : Form
{
private Rectangle hitTestRectangle = new Rectangle();
private Rectangle doubleClickRectangle = new Rectangle();
private TextBox textBox1 = new TextBox();
private Timer doubleClickTimer = new Timer();
private ProgressBar doubleClickBar = new ProgressBar();
private Label label1 = new Label();
private Label label2 = new Label();
private bool isFirstClick = true;
private bool isDoubleClick = false;
private int milliseconds = 0;
[STAThread]
public static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}
public Form1()
{
label1.Location = new Point(30, 5);
label1.Size = new Size(100, 15);
label1.Text = "Hit test rectangle:";
label2.Location = new Point(30, 70);
label2.Size = new Size(100, 15);
label2.Text = "Double click timer:";
hitTestRectangle.Location = new Point(30, 20);
hitTestRectangle.Size = new Size(100, 40);
doubleClickTimer.Interval = 100;
doubleClickTimer.Tick +=
new EventHandler(doubleClickTimer_Tick);
doubleClickBar.Location = new Point(30, 85);
doubleClickBar.Minimum = 0;
doubleClickBar.Maximum = SystemInformation.DoubleClickTime;
textBox1.Location = new Point(30, 120);
textBox1.Size = new Size(200, 100);
textBox1.AutoSize = false;
textBox1.Multiline = true;
this.Paint += new PaintEventHandler(Form1_Paint);
this.MouseDown += new MouseEventHandler(Form1_MouseDown);
this.Controls.AddRange(new Control[] { doubleClickBar, textBox1,
label1, label2 });
}
// Detect a valid single click or double click.
void Form1_MouseDown(object sender, MouseEventArgs e)
{
// Verify that the mouse click is in the main hit
// test rectangle.
if (!hitTestRectangle.Contains(e.Location))
{
return;
}
// This is the first mouse click.
if (isFirstClick)
{
isFirstClick = false;
// Determine the location and size of the double click
// rectangle area to draw around the cursor point.
doubleClickRectangle = new Rectangle(
e.X - (SystemInformation.DoubleClickSize.Width / 2),
e.Y - (SystemInformation.DoubleClickSize.Height / 2),
SystemInformation.DoubleClickSize.Width,
SystemInformation.DoubleClickSize.Height);
Invalidate();
// Start the double click timer.
doubleClickTimer.Start();
}
// This is the second mouse click.
else
{
// Verify that the mouse click is within the double click
// rectangle and is within the system-defined double
// click period.
if (doubleClickRectangle.Contains(e.Location) &&
milliseconds < SystemInformation.DoubleClickTime)
{
isDoubleClick = true;
}
}
}
void doubleClickTimer_Tick(object sender, EventArgs e)
{
milliseconds += 100;
doubleClickBar.Increment(100);
// The timer has reached the double click time limit.
if (milliseconds >= SystemInformation.DoubleClickTime)
{
doubleClickTimer.Stop();
if (isDoubleClick)
{
textBox1.AppendText("Perform double click action");
textBox1.AppendText(Environment.NewLine);
}
else
{
textBox1.AppendText("Perform single click action");
textBox1.AppendText(Environment.NewLine);
}
// Allow the MouseDown event handler to process clicks again.
isFirstClick = true;
isDoubleClick = false;
milliseconds = 0;
doubleClickBar.Value = 0;
}
}
// Paint the hit test and double click rectangles.
void Form1_Paint(object sender, PaintEventArgs e)
{
// Draw the border of the main hit test rectangle.
e.Graphics.DrawRectangle(Pens.Black, hitTestRectangle);
// Fill in the double click rectangle.
e.Graphics.FillRectangle(Brushes.Blue, doubleClickRectangle);
}
}
}

I've had similar problem with having events on double click and mouse up. I've experienced that the mouse up during the double click gets triggered twice during a double click as is reasonable.
What worked best for me was to hide the mouse up behind two levels on when it can be triggered. A bool and a timer with an interval short enough not to be noticeable by the user but longer than the interval between clicks in a double click.
The bool let's call it canMouseUp is true by default. and should be set to false during a double click to ignore the mouse up as the double click is finished.
the mouse up checks for canMouseUp and if it is false then it is set to true, nothing else. If canMouseUp is true then I start the mouseUpTimer.
double click stops the mouseUpTimer, sets canMouseUp to false and does it's own thing.
private void MyObject_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
try
{
if (!canMouseUp)
{
canMouseUp= true;
e.Handled = true;
}
else
{
mouseUpTimer.Start();
e.Handled = true;
}
}
catch (Exception)
{
throw;
}
}
private void MyObject_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
try
{
mouseUpTimer.Stop();
// Do what DoubleClick is supposed to do
canMouseUp = false;
e.Handled = true;
}
catch (Exception)
{
throw;
}
}
private void mouseUpTimer_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
// Do what Mouse up is supposed to do.
}
catch (Exception)
{
}
}

Related

How to make the event wait until a boolean is changed

I have an event registered.
layout.SizeChanged += parentToggleBox.Resize;
Problem is, I would like this Resize event to wait until my mouse has moved away from the box.
How to make this event wait until a boolean is changed from false to true?
or wait until OnMouseLeave(object sender, MouseEventArgs e) is triggered?
Here's an example that I put together:
public class Form1 : Form
{
private Panel Panel1;
private Label Label1;
public Form1()
{
this.Panel1 = new Panel()
{
BackColor = System.Drawing.Color.Red,
};
this.Label1 = new Label()
{
Top = 200,
Text = "Click",
};
bool clicked = false;
bool entered = false;
this.Panel1.Click += (s, e) =>
{
this.Panel1.BackColor = System.Drawing.Color.Blue;
clicked = true;
};
this.Panel1.MouseEnter += (s, e) =>
{
this.Panel1.BackColor = System.Drawing.Color.Yellow;
clicked = false;
entered = true;
};
this.Panel1.MouseLeave += (s, e) =>
{
if (entered && clicked)
{
this.Panel1.BackColor = System.Drawing.Color.Green;
this.Label1.Text = "Success";
}
};
this.Controls.Add(this.Panel1);
this.Controls.Add(this.Label1);
}
}
I've used a Click event rather than a Resize to demonstrate the technique.
Effectively this is just setting two booleans and when the right combination of entered and clicked occurs then the code in the block that contains this.Label1.Text = "Success"; will run.
The colours are set for debugging purposes.
To run, do this:
var form1 = new Form1();
form1.ShowDialog();

Dynamic button click event within a timer tick event

I have a grid with 9 buttons. In the timer tick event a random button is higlighted. If one clicks the higlighted button, a dynamic click event is created and within the click event the button is marked with a different color. The counterHits variable in the dynamic button click event is supposed to keep track of the highlighted buttons that were hit. Sometimes though it increases the variable more than by one. I cannot figure out why this is happening. Any help anyone?
public partial class Form1 : Form
{
const int buttons = 9;
int counterHits;
int counterTicks;
int currentIndex;
int lastIndex;
bool hit = false;
Random r;
Timer timerGameLoop;
Timer timerUpdateUI;
public Form1()
{
InitializeComponent();
timerGameLoop = new Timer();
timerGameLoop.Interval = 1000;
timerGameLoop.Tick += t_Tick;
timerUpdateUI = new Timer();
timerUpdateUI.Interval = 10;
timerUpdateUI.Tick += timerUpdateUI_Tick;
r = new Random();
}
// set up the grid and start
private void btnStart_Click(object sender, EventArgs e)
{
for (int i = 0; i < buttons; i++)
{
var b = new Button();
b.Size = new Size(100, 100);
b.Margin = new Padding(0);
b.BackColor = Color.White;
flowLayoutPanel.Controls.Add(b);
}
timerGameLoop.Start();
timerUpdateUI.Start();
}
// tick event ui update loop
void timerUpdateUI_Tick(object sender, EventArgs e)
{
lblHitCounter.Text = "hits : " + counterHits.ToString();
lblTickCounter.Text = "ticks : " + counterTicks.ToString();
}
// tick event game loop
void t_Tick(object sender, EventArgs e)
{
// reset to white background if not clicked
if (!hit)
flowLayoutPanel.Controls[lastIndex].BackColor = Color.White;
// highlight button to be clicked
currentIndex = r.Next(buttons);
lastIndex = currentIndex;
flowLayoutPanel.Controls[currentIndex].BackColor = Color.Violet;
// highligted button clicked
flowLayoutPanel.Controls[currentIndex].Click += b_Click;
hit = false;
counterTicks++;
}
// highlighted button clicked event
void b_Click(object sender, EventArgs e)
{
var b = (Button)sender;
b.BackColor = Color.Olive;
hit = true;
counterHits++;
b.Click -= b_Click;
}
}
The following lines attaches b_Click to your button. That eventhandler is only removed if you press the button
flowLayoutPanel.Controls[currentIndex].Click += b_Click;
See the implementation of b_Click
// highlighted button clicked event
void b_Click(object sender, EventArgs e)
{
//Stugg
b.Click -= b_Click;←Removed Here only if it is pressed
}
This line indicates that some buttons have more than one EventHandler attached. Therefore when you click the button eventhandler runs more than once.

Address a generated button for clickevent

I have a class that creates panels with controls based on my database. It creates a panel with a button on each panel, per row in DB. How do I address one specific button to make a click event?
I'm a rookie, and maybe abit over my head, but you don't learn to swim in shallow water ;)
Any help appreciated!
while (myDataReader.Read())
{
i++;
Oppdrag p1 = new Oppdrag();
p1.Location = new Point (0, (i++) * 65);
oppdragPanel.Controls.Add(p1);
p1.makePanel();
}
class Oppdrag : Panel
{
Button infoBtn = new Button();
public void makePanel()
{
this.BackColor = Color.White;
this.Height = 60;
this.Dock = DockStyle.Top;
this.Location = new Point(0, (iTeller) * 45);
infoBtn.Location = new Point(860, 27);
infoBtn.Name = "infoBtn";
infoBtn.Size = new Size(139, 23);
infoBtn.TabIndex = 18;
infoBtn.Text = "Edit";
infoBtn.UseVisualStyleBackColor = true;
}
}
You'll need a method that matches the event thrown by clicking on the button.
i.e.)
void Button_Click(object sender, EventArgs e)
{
// Do whatever on the event
}
Then you'll need to assign the click event to the method.
p1.infoBtn.Click += new System.EventHandler(Button_Click);
Hope this helps.
You can add the event handler for the button when you create the button. You can even add a unique CommandArgument per button so you can distinguish one button from another.
public void makePanel()
{
/* ... */
infoBtn.UseVisualStyleBackColor = true;
infoBtn.Click += new EventHandler(ButtonClick);
infoBtn.CommandArgument = "xxxxxxx"; // optional
}
public void ButtonClick(object sender, EventArgs e)
{
Button button = (Button)sender;
string argument = button.CommandArgument; // optional
}

Fading in and fading out for a form

i have a requirement in which my form is transparent,if my mouse enters into it the form
should became visible,if my mouse leaves out of the form it becomes transparent, i have three different controls placed in my form , each controls mouse leave and mouse enter is the same that of the form . if my mouse enters into the form and enters into a control
form_mouseleaveevent and control_mouseenterd gets fired so iam not able to achieve it,how to overcome this.
below is the piece of code for this:
private void TransToOpac()
{
if (!isTransparent)
return;
if (TtoOON == false )
{
TtoOON = true;
for (i = this.Opacity; i <= 1; i = i + 0.02)
{
this.Opacity = i;
Thread.Sleep(50);
}
isTransparent = false;
TtoOON = false;
}
}
private void OpacToTrans()
{
if (isTransparent)
return;
if (OtoTON == false )
{
OtoTON = true;
for (i = this.Opacity; i >= 0.5; i = i - 0.02)
{
this.Opacity = i;
Thread.Sleep(50);
}
isTransparent = true;
OtoTON = false;
}
}
private void OnMouseEntered(object sender, EventArgs e)
{
TransToOpac();
}
private void OnMouseLeft(object sender, EventArgs e)
{
OpacToTrans();
}
You can't get this done with MouseEnter/Leave events. The smaller problem is that the form's Leave event may never fire if a control is close to the edge. The bigger problem is that it will fire when the cursor moves into the non-client area (border, caption), you don't want to fade the form when the user tries to close or resize the window.
The crude but effective solution is to use a timer to check where the mouse is located:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
this.Opacity = 0.99; // Avoid flicker
mFadeTimer.Interval = 15;
mFadeTimer.Tick += new EventHandler(mFadeTimer_Tick);
mMouseTimer.Interval = 200;
mMouseTimer.Tick += new EventHandler(mMouseTimer_Tick);
mMouseTimer.Enabled = true;
}
void mMouseTimer_Tick(object sender, EventArgs e) {
if (this.Bounds.Contains(Control.MousePosition)) {
if (mFade <= 0) { mFade = 1; mFadeTimer.Enabled = true; }
}
else {
if (mFade >= 0) { mFade = -1; mFadeTimer.Enabled = true; }
}
}
void mFadeTimer_Tick(object sender, EventArgs e) {
double opaq = this.Opacity + mFade * 0.05;
if (opaq >= 0.99) { opaq = 0.99; mFadeTimer.Enabled = false; }
if (opaq <= 0.15) { opaq = 0.15; mFadeTimer.Enabled = false; }
this.Opacity = opaq;
}
private Timer mFadeTimer = new Timer();
private Timer mMouseTimer = new Timer();
private int mFade = 0;
}
You could also check in Form_MouseLeave whether the mouse pointer is still within the form's bounds and in that case not fade out.
EDIT
There are several ways to find out whether the mouse is still within form's bounds. Easiest would be to use the Mouse.GetPosition method to find the current mouse position. The result is the location of the mouse pointer in screen coordinates. You can then check, whether the form's bounding rectangle contains the location.

C# - Make form semi-transparent while moving

Is there any way to make the form semi-transparent while it is being moved and then become opaque when it's not being moved anymore? I have tried the Form_Move event with no luck.
I'm stuck, any help?
The reason the form loads as semi-transparent is because the form has to be moved into the starting position, which triggers the Move event. You can overcome that by basing whether the opacity is set, on whether the form has fully loaded.
The ResizeEnd event fires after a form has finished moving, so something like this should work:
bool canMove = false;
private void Form1_Load(object sender, EventArgs e)
{
canMove = true;
}
private void Form1_Move(object sender, EventArgs e)
{
if (canMove)
{
this.Opacity = 0.5;
}
}
private void Form1_ResizeEnd(object sender, EventArgs e)
{
this.Opacity = 1;
}
To do it properly I expect you'd need to override the message processing to respond to the title bar being held, etc. But you could cheat, and just use a timer so that you make it opaque for a little while when moved, so continuous movement works:
[STAThread]
static void Main()
{
using (Form form = new Form())
using (Timer tmr = new Timer())
{
tmr.Interval = 500;
bool first = true;
tmr.Tick += delegate
{
tmr.Stop();
form.Opacity = 1;
};
form.Move += delegate
{
if (first) { first = false; return; }
tmr.Stop();
tmr.Start();
form.Opacity = 0.3;
};
Application.Run(form);
}
}
Obviously you could tweak this to fade in/out, etc - this is just to show the overall concept.

Categories