c# timer preventing button click - c#

I am currently trying to create a hover effect on a custom control, where a panel (panel1) shows up after the mouse enters the control.
I have a timer that starts when the mouseleave event is raised, the interval is 250ms, and there is an onTick event that changes the visibility of the panel1 to false.
This all works. However, the buttons on panel1 do not always respond when clicked.
Here is the pertinent code - I will supply anything else that is required if I'm missing some information.
private void MagicCardViewer_MouseLeave(object sender, EventArgs e)
{
timer1.Start();
timer1.Interval = 250;
timer1.Tick += new EventHandler(timer1_TickOff);
timer1.Tick -= timer1_TickOn;
}
private void MagicCardViewer_MouseEnter(object sender, EventArgs e)
{
showPanel1();
}
public void showPanel1()
{
//show necessary controls
buttonDiscard.Show();
//show panel1
panel1.Visible = true;
ActiveControl = panel1;
}
public void hidePanel1()
{
panel1.Visible = false;
//hide controls
}
# region button events
private void buttonChoose_Click(object sender, EventArgs e)
{
Chosen = !Chosen;
if (Chosen)
{
callCardChosen();
}
}
private void buttonTap_Click(object sender, EventArgs e)
{
cards[0].ChangeTap();
DrawCardTap();
onCardChanged();
}
private void buttonActivate_Click(object sender, EventArgs e)
{
cards[0].TryActivate(0);
}
private void buttonDiscard_Click(object sender, EventArgs e)
{
cards[0].onDiscard();
}
# endregion
I think that is everything, but there is a lot of code to select from.
breakpoints don't trigger, the button flashes but nothing happens. If the timer interval is set very long, it works fine, but the point is for the button to vanish quickly once the mouse leaves the control. If the mouse is on the buttons, then the form reports it as having left the control.
To sum up - the buttons are not always processing when I click on them.

If you have the timer ticking every 250ms that could prevent the event on the mouse click.
I would check that you stop the timer after the tick if you no longer need it, and restart as I think you are doing when the user leaves the control or enter it again.
This could be why it works when you set a longer time interval.

Related

Apply parent mouse events to child elements

I am making little Windows Forms Application.
I have PictureBox (parent) and Label (child) in it.
The Parent's Mouse Events are working perfectly, but Mouse events generated by child elements are not reflected on the Parent. The Cursor also changes back to its default (arrow).
Is it possible to pass events generated by child Controls, e.g., the MouseEnter event, to the Parent Control?
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Card.MouseEnter += new EventHandler(Card_MouseEnter);
Card.MouseLeave += new EventHandler(Card_MouseLeave);
Card.MouseDown += new MouseEventHandler(this.Card_MouseDown);
Card.MouseUp += new MouseEventHandler(this.Card_MouseUp);
}
void Card_MouseLeave(object sender, EventArgs e)
{
this.Card.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.card_bg));
this.Rename("Running!");
}
void Card_MouseEnter(object sender, EventArgs e)
{
this.Card.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.card_hover_bg));
}
private void Card_MouseDown(object sender, EventArgs e)
{
this.Card.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.card_click_bg));
}
private void Card_MouseUp(object sender, EventArgs e)
{
this.Card.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.card_hover_bg));
this.Rename("Please Wait...");
}
private void CardName_MouseDown(object sender, MouseEventArgs e)
{
}
void Rename(string args)
{
this.CardName.Text = args;
}
private void CardName_Click(object sender, EventArgs e)
{
}
}
         
This is what I have This is what I want to achieve
The first animation represents what I have now, the second is what I need to achieve :)
When I'm making pictureBox1.Controls.Add(label1) label1 is
disappearing and I tried bring to front and change color but couldn't
do it. Please if you will have any idea show me in provided code by me
to be understandable for me. Thank you all again and again :)
You'd use code like this, maybe in the Load() event of the Form:
private void Form1_Load(object sender, EventArgs e)
{
Point pt = CardName.Parent.PointToScreen(CardName.Location);
Card.Controls.Add(CardName);
CardName.Location = Card.PointToClient(pt);
}
This keeps the label in the same position as it was, but makes the picturebox the parent.
Not sure where you're going wrong. Here's an example showing it in action. Both the PictureBox (Card) and Label (CardName) are inside a Panel (panel1). Clicking on button2 toggles the visibility of the Card. Clicking on button1 makes Card the Parent of CardName. You can see that at first, only the Card toggles visibility, but after clicking on button1 and setting the Parent, both toggle visibility together since CardName is a Child of Card (it also changes its BackColor to match that of its new Parent):
Code:
public partial class Form1 : Form
{
private void button1_Click(object sender, EventArgs e)
{
Point pt = CardName.Parent.PointToScreen(CardName.Location);
Card.Controls.Add(CardName);
CardName.Location = Card.PointToClient(pt);
}
private void button2_Click(object sender, EventArgs e)
{
Card.Visible = !Card.Visible;
}
}
When I move mouse over label, panel thinks mouse left it and rises
MouseLeave event
Here is how you can tell if the cursor has actually left the BOUNDS of the Panel, as opposed to simply enter a child control within the Panel:
private void panel1_MouseEnter(object sender, EventArgs e)
{
panel1.BackColor = Color.Red;
}
private void panel1_MouseLeave(object sender, EventArgs e)
{
Point pt = panel1.PointToClient(Cursor.Position);
if (!panel1.ClientRectangle.Contains(pt))
{
// we only get in here when the cursor leaves the BOUNDS of panel1
panel1.BackColor = Control.DefaultBackColor;
}
}
First of all, you should build a UserControl as a container for all your objects: it'd make everything simpler (the one I'm using here is actually a UserControl, modified to comply with your current setup).
When a Control other than the PictureBox is interacted with, you can decide whether you want to trigger a similar action on the main Control or perform a different action based on what event has been generated.
▶ When the Mouse Pointer enters you assembled Control, you want to change the default Cursor: then, when one of the Labels raises the Enter event, call the method of the main Control that handles this. An event handler is a method, you can call it.
▶ When a Label is clicked, you don't want to trigger the related action of the main Control: in this case, there's nothing to do, just handle this event and perform the required action.
▶ The Label should be child of the main Control. You're using a PictureBox, which is not a ContainerControl. You can add child controls to it anyway. You need to do this in code, since - as mentioned - the PictureBox is not designed to host Controls, thus you cannot drop one inside it: the Control you drop will be parented with the Container that hosts the PictureBox (your Form, here).
When you set the parent in code, you need to remember that the Location of the child control is relative to the old Parent, so you have to re-define it's position.
E.g: PictureBox.Bounds = (100, 100, 100, 200) / Label.Bounds = (100, 250, 100, 50)
When the PictureBox becomes Parent of your Label, the Label.Location is still (100, 250): so, now, it will be hidden, since it's outside the visible bounds of its new Parent. You have to reposition it in relation to the new host: its new Location should be (0, 150), to keep the previous relative position.
PictureBox.Control.Add(Label);
//[...]
Label.Location = new Point(Label.Left - PictureBox.Left, Label.Top - PictureBox.Top);
=> Label.Location = (100 - 100, 250 - 100) => (0, 150)
Or, centered horizontally:
Label.Location = new Point((PictureBox.Width - Label.Width) / 2, Label.Top - PictureBox.Top);
=> Label.Location = ((100 - 100) / 2, 250 - 100) => (0, 150) // <- Since both have the same Width
Or, using positions relative to the Screen:
var p = Label.PointToScreen(Point.Empty); // Relative to the ClientRectangle (Top/Left = (0, 0))
PictureBox.Controls.Add(Label);
Label.Location = PictureBox.PointToClient(p);
In any case, call BringToFront() after, to ensure that the new child Control is brought on top and anchor the Control, so it will keep its position and its Width will be bound to the Parent Width:
Label.BringToFront();
Label.Anchor = AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Right;
Now, assuming you want to change the Cursor to Cursors.Hand when the Mouse enters your combined Control and reset to default when it leaves it:
▶ You want the Cursor to change shape in any case.
▶ You want to generate different actions when the PictureBox is clicked and when one of the Labels is clicked.
▶ Both Labels can have distinct actions when clicked.
→ In the visual sample, the Label above the PictureBox is named lblTitle, the Label inside the PictureBox, at the bottom, is named lblFooter.
→ The PictureBox is named ImageView.
Setup the handlers:
NOTE: With a UserControl, the events handling, e.g., in relation to MouseEnter, changes in:
// The Parent's MouseEnter calls OnMouseEnter
protected override void OnMouseEnter(EventArgs e)
{
base.OnMouseEnter(e);
this.Cursor = Cursors.Hand;
}
// Child Controls just call the same method
private void Labels_MouseEnter(object sender, EventArgs e) => OnMouseEnter(e);
public Form1()
{
InitializeComponent();
Point p = lblFooter.PointToScreen(Point.Empty);
ImageView.Controls.Add(lblFooter);
lblFooter.Location = ImageView.PointToClient(p);
ImageView_MouseEnter += ImageView_MouseEnter;
ImageView_MouseLeave += ImageView_MouseLeave;
// Not added in the code here, do whatever is needed with this handler
ImageView_Click += ImageView_Click;
lblFooter.MouseEnter += Labels_MouseEnter;
lblFooter.MouseLeave += Labels_MouseLeave;
lblFooter.MouseClick += lblFooter_MouseClick;
lblTitle.MouseEnter += Labels_MouseEnter;
lblTitle.MouseLeave += Labels_MouseLeave;
lblTitle.MouseDown += lblTitle_MouseDown;
lblTitle.MouseUp += lblTitle_MouseUp;
}
private void ImageView_MouseEnter(object sender, EventArgs e) => this.Cursor = Cursors.Hand;
private void ImageView_MouseLeave(object sender, EventArgs e) => this.Cursor = Cursors.Default;
private void Labels_MouseEnter(object sender, EventArgs e)
{
ImageView_MouseEnter(ImageView, e);
// [...]
// Do stuff related to the Labels Enter event
}
private void Labels_MouseLeave(object sender, EventArgs e) {
ImageView_MouseLeave(ImageView, e);
}
private void lblTitle_MouseDown(object sender, MouseEventArgs e) {
// Perform actions when the Mouse button is held down lblTitle
}
private void lblTitle_MouseUp(object sender, MouseEventArgs e) {
// Perform actions when the Mouse button is released
}
private void lblFooter_MouseClick(object sender, MouseEventArgs e) {
// Perform actions on a Mouse Click event on lblFooter
}

How to know when user doesn't click anymore on a button WPF

I'm doing some password eye text box.
I want, that when the user would press on the eye button, the password would be visible and when he leaves the mouse button it would be unvisible again.
My question: How to know when the user stopped clicking the mouse button?
Image of how it looks like:
My code is roughly as follows:
private void eye_click(object sender , RoutedEventArgs e)
{
//here I making the password visible
}
I'm looking for something like:
private void user_doesnt_click_anymore_click(object sender , RoutedEventArgs e)
{
//return the password to be unvisible
}
You can react to different events, depending on your
Form-Example
this.button1.Click += new System.EventHandler(this.button1_Click);
this.button1.MouseClick += new System.Windows.Forms.MouseEventHandler(this.button1_MouseClick);
this.button1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.button1_MouseDown);
this.button1.MouseUp += new System.Windows.Forms.MouseEventHandler(this.button1_MouseUp);
private void button1_Click(object sender, EventArgs e)
{
Console.WriteLine("button1_Click");
}
private void button1_MouseClick(object sender, MouseEventArgs e)
{
Console.WriteLine("button1_MouseClick");
}
private void button1_MouseDown(object sender, MouseEventArgs e)
{
Console.WriteLine("button1_MouseDown");
}
private void button1_MouseUp(object sender, MouseEventArgs e)
{
Console.WriteLine("button1_MouseUp");
}
MouseDown
Fires if you mouse is over the button an a mousebutton is pushed down.
First chance to see something
Here you want to show the pw.
MouseUp
Fires if you release the mousebutton which you "downed" on the button.
Fired when stopped clicking. You're not neccessarily on the button anymore!
Here you want to hide the pw.
MouseClick
Fires if a MouseDown AND MouseUp is performed and you're still hovering the button.
This prevents hitting buttons with the keyboard. Perhaps helpful in some situations?!
Click
Fires if the button is clicked (Pushed down and released). This could also be done my selecting the button by tabbing to it and pushing space.
This is what you normally want to use, when a button is clicked, like "submit form"-actions.
Well I guess you could go for something in the area of MouseDown/MouseUp
<Button x:Name="Btn" MouseDown="MouseDown" MouseUp="MouseUp" />

C# mousedown event continously press key

okay so what I want to do, it when the mouse is HELD DOWN I want it to continously press a key. it should continously press this key until I let off.
Imagine if you will, a left and right button on a windows form,
then by clicking and holding the right button, the letter "R" displays on a textbox continously until you release the button. What I am doing has very little to do with that scenario, but you get what I'm trying to do here.
What exactly do I put in the mouse down to keep the sendkeys going forever without locking up the application?
I hope my question makes sense. lol.
Thanks
RT
private void pictureBoxKeyboard_MouseDown(object sender, MouseEventArgs e)
{
//something goes here
}
This is worth a read...
http://msdn.microsoft.com/en-us/library/ms171548.aspx
SendKeys.Send("r")
This might just fire once, you may want to attach a timer that starts on the MouseDown event and stops on the MouseUp event. Then you could put the SendKeys in the Timer.Tick event.
private void Form1_Load(object sender, EventArgs e)
{
this.timer1.Interval = 500;
}
private void button1_MouseUp(object sender, MouseEventArgs e)
{
timer1.Stop();
this.Text = "moose-Up";
}
private void button1_MouseDown(object sender, EventArgs e)
{
timer1.Start();
this.Text = "moose-Down";
this.richTextBox1.Select();
}
private void timer1_Tick(object sender, EventArgs e)
{
SendKeys.Send("r");
Debug.Print("tickling");
}
Select the control that you wish to receive the SendKeys value...

Mouse events not fired

I'm making a C# WinForms application. The MouseMove and MouseClick events of the form aren't getting fired for some reason. (I'm probably going to feel like an idiot when I find out why.)
It is a transparent form (TransparencyKey is set to the background colour) with a semi-transparent animated gif in a Picture Box. I am making a screensaver.
Any suggestions?
EDIT:
MainScreensaver.cs
Random randGen = new Random();
public MainScreensaver(Rectangle bounds)
{
InitializeComponent();
this.Bounds = Bounds;
}
private void timer1_Tick(object sender, EventArgs e)
{
Rectangle screen = Screen.PrimaryScreen.Bounds;
Point position = new Point(randGen.Next(0,screen.Width-this.Width)+screen.Left,randGen.Next(0,screen.Height-this.Height)+screen.Top);
this.Location = position;
}
private void MainScreensaver_Load(object sender, EventArgs e)
{
Cursor.Hide();
TopMost = true;
}
private Point mouseLocation;
private void MainScreensaver_MouseMove(object sender, MouseEventArgs e)
{
if (!mouseLocation.IsEmpty)
{
// Terminate if mouse is moved a significant distance
if (Math.Abs(mouseLocation.X - e.X) > 5 ||
Math.Abs(mouseLocation.Y - e.Y) > 5)
Application.Exit();
}
// Update current mouse location
mouseLocation = e.Location;
}
private void MainScreensaver_KeyPress(object sender, KeyPressEventArgs e)
{
Application.Exit();
}
private void MainScreensaver_Deactive(object sender, EventArgs e)
{
Application.Exit();
}
private void MainScreensaver_MouseClick(object sender, MouseEventArgs e)
{
Application.Exit();
}
Excerpt from MainScreensaver.Designer.cs InitialiseComponent()
this.MouseClick += new System.Windows.Forms.MouseEventHandler(this.MainScreensaver_MouseClick);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.MainScreensaver_MouseMove);
This isn't an answer to you question, but I'm leaving this answer in case anyone else stumbles upon this question while trying to debug this same issue (which is how I got here)
In my case, I had a class that was derived from Form.
I was also using TransparencyKey.
Some things I noticed
The events will not fire on the transparent parts of the form.
The events will not fire if the mouse cursor is over another control on the form.
The events will not fire if you override WndProc and set the result of a WM_NCHITTEST message. Windows doesn't even send out the corresponding mouse messages that would cause the .NET events.
My Solution
In my constructor, I had forgotten to call InitializeComponent().
Which was where the event handlers were being bound to my controls.
Events were not firing because the handlers were not being bound.
Are you sure that your form has focus? If your form does not have focus, the mouse events will not be fired.

Creating A Continuous Action During A Windows Form Mouse Event

When I put a button on a form in C#, Visual Studio 2005, and have an action triggered by a button event, such as MouseHover or MouseDown, then the event triggers a single call to the function which defines the action despite the fact that I may continue to hover or keep the left button down. In this case I am trying to move a graphical object by rotating or translating it. I don't want to continue to click the mouse in order to get a repeated call to the transforming function, just keep the mouse hovering or hold the button down. What maintains the action until I cease my own action?
Set a flag on MouseEnter and keep doing the action while the flag remains true. Set the flag to false on MouseLeave.
In your case you need to use a combination of the events MouseDown, MouseMove and MouseUp.
Here a small simplified example to start:
private void OnMouseDown(object sender, EventArgs e)
{
//hit test to check if the mouse pointer is on a graphical object
_myHitObject = the_selected_object
}
private void OnMouseMove(object sender, EventArgs e)
{
if(_myHitObject != null)
//do your action relative to the mouse movements.
}
private void OnMouseUp(object sender, EventArgs e)
{
_myHitObject = null;
}
The solution is to use DoEvents() which allows for the MouseLeave event to be noted and the class variable "more" to be changed:
private void MouseEnter_ZoomIn(object sender, EventArgs e)
{
more = true;
while (more == true)
{
c1Chart3D1.ChartArea.View.ViewportScale *= ZoomMultiple;
Application.DoEvents();
}
} // MOUSEENTER_ZOOMIN()
//-------------------------------------
private void MouseLeave_Stop(object sender, EventArgs e)
{
more = false;
}

Categories