MouseWheel Event Fire - c#

I have a problem on calling my private method on MouseWheel event. In fact my mouse wheel event gets fired properly when i only increment a variable or display something in Title bar etc. But when i want to call a private method, that method gets called only one time which is not the requirement i want to call that method depending on the speed of scroll i.e. when scroll is done one time slowly call the private method one time but when the scroll is done in high speed call the private method more than one time depending on the scroll speed.
For further explanation i am placing the sample code which displays the value of i in Title bar and add it in the Listbox control properly depending on the scroll speed but when i want to call the private method more than one time depending upon the scroll speed, that method gets called only one time.
public partial class Form1 : Form
{
ListBox listBox1 = new ListBox();
int i = 0;
public Form1()
{
InitializeComponent();
// Settnig ListBox control properties
this.listBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.listBox1.FormattingEnabled = true;
this.listBox1.Location = new System.Drawing.Point(13, 13);
this.listBox1.Name = "listBox1";
this.listBox1.Size = new System.Drawing.Size(259, 264);
this.listBox1.TabIndex = 0;
// Attaching Mouse Wheel Event
this.listBox1.MouseWheel += new MouseEventHandler(Form1_MouseWheel);
// Adding Control
this.Controls.Add(this.listBox1);
}
void Form1_MouseWheel(object sender, MouseEventArgs e)
{
i++;
this.Text = i.ToString();
this.listBox1.Items.Add(i.ToString());
// Uncomment the following line to call the private method
// this method gets called only one time irrelevant of the
// mouse wheel scroll speed.
// this.LaunchThisEvent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.listBox1.Select();
}
private void LaunchThisEvent()
{
// Display message each time
// this method gets called.
MessageBox.Show(i.ToString());
}
}
How to call the private method more than one time depending upon the speed of the mouse wheel scroll?

You can try using the MouseEventArgs.Delta field to calculate the number of calls:
int timesToCall = Math.Abs(e.Delta/120);
for (int k = 0; k < timesToCall; ++k)
{
this.LaunchThisEvent();
}
`

Related

C# Event Handler is called multiple times when selecting a menu item

I want to implement some Pictureboxes and when one of them is clicked, a MessageBox should appear and tell which Box is clicked.
However, I want to implement a choice how many Pictureboxes should appear. When I choose another MenuItem, then the click event will be called multiple times. I tried unsubscribing, but it doesn't work.
Here is my code:
public partial class Form1 : Form
{
PictureBox Pbox1;
PictureBox Pbox2;
PictureBox Pbox3;
PictureBox Pbox4;
public Form1()
{
InitializeComponent();
this.Text = "Picturebox";
Pbox1 = new PictureBox();
Pbox2 = new PictureBox();
Pbox3 = new PictureBox();
Pbox4 = new PictureBox();
}
private void Pbox_Click(object sender, EventArgs e, int nr)
{
MessageBox.Show("Picture number " + nr.ToString() + " is clicked");
}
private void toolStripMenuItem2_Click(object sender, EventArgs e)
{
Pbox1.Image = new Bitmap(#"Picture.png");
Pbox1.Location = new Point(20, 40);
Pbox1.Size = new Size(160, 120);
Pbox1.SizeMode = PictureBoxSizeMode.StretchImage;
Pbox1.Click += (sender2, e2) => Pbox_Click(sender2, e2, 1);
this.Controls.Add(Pbox1); }
The rest is the same as toolStripMenuItem2.
Can you help me with this problem?
When will it be called multiple times? I guess when switching to another menu item everything should work fine. But when switching back to an item that was already clicked before, then another click handler will be registered in addition to the existing one and will call the Pbox_Click method twice.
You can try to put the event registration in the constructor method or release other click-events before re-registering them.

How can I delay an animation without using System.Threading.Thread.Sleep()

I want to move my text up, but if I use System.Threading.Thread.Sleep() my app gets stuck. I think that the using a Timer is a good way to solve it but pls show me how. I was trying to use Animate() also, but I didn't solve it by this way.
for (int i = 0; i < 30; i+=2)
{
Brush snizovaniViditelnosti = new SolidBrush(Color.FromArgb(0+i*8, 0+i*8,0+i*8));
g.DrawString("+1", fontPridaniMaterialu, snizovaniViditelnosti, MousePosition.X, MousePosition.Y - i);
System.Threading.Thread.Sleep(30);
//ImageAnimator.Animate()
Timer d = new Timer();
d.Interval = 55;
Refresh();
}
It's suppose to work that I click on some button and then appears text - "+1" and it will be moving up with reducing opacity. Finally it will disappear.
Grab Timer and Button from toolbox.
Then select timer and go to events section in properties window. Double click Tick event. Apply your logic for moving text.
For button you need to use click event.
Sample code:
private void timer1_Tick (object sender, EventArgs e)
{
button1.Location = new Point (button1.Location.X + 1, button1.Location.Y);
}
private void button1_Click (object sender, EventArgs e)
{
timer1.Start ();
}
You will have to create a Timer out of your for loop and replace the loop by a Tick event. At the moment you are re-creating the Timer in every loop iteration. Put it as a component to your control, like this:
// Timer Interval is set to 0,5 second
private Timer _timer = new Timer { Interval = 500 };
And adding also the following fields to your control for
private int _index = 0;
private int _maxIndex = 30;
After this adding a delegate to the Tick event, which will moving up your text a ttle bit on every tick.
this._timer.Tick += delegate
{
if (this._index < this._maxIndex)
{
var alphaValue = 255 - this._index * 8;
Brush snizovaniViditelnosti = new SolidBrush(Color.FromArgb(alphaValue, 255, 255, 255));
g.DrawString("+1", fontPridaniMaterialu, snizovaniViditelnosti, MousePosition.X, MousePosition.Y - this._index);
Refresh();
this._index++;
}
else
{
this._timer.Stop();
}
};
If you only want to reduce opacity, reduce the alpha value and leave the color - as shown in the example above.
And wire this to your Button click event
private void Button_Click(object sender, EventArgs e)
{
this._timer.Start();
}
Hint: This is a quick solution for only one item. If you want to do this for more than one item you may add a class to your code containing the text, the Timer and the current and maxIndex.
I guess you are using winforms.
To avoid flickering while re-drawing your UI. You should activate double buffering.
See more information about Handling and Raising Events
As #apocalypse suggested in his answer. It will be better to setup a fix start location for your text to move up.

Keeping colors when repainting canvas.?

Here's my code:
public void Repaint() {
canvas1.Children.Clear();
ObservableCollection<ClassBox> classes = viewModel.Classes;
foreach (ClassBox j in classes) {
// connect our ui element to the mouse handler if not done already
if (!j.MouseActive) {
j.Box.PreviewMouseLeftButtonUp += Handle_MouseUp;
j.Box.PreviewMouseLeftButtonDown += Handle_MouseDown;
j.Box.PreviewMouseMove += Handle_MouseMove;
j.MouseActive = true;
// Heres should the code be written (something like :)
// j.Box.SetColor(Change_Color(value));
}
canvas1.Children.Add(j.Box);
} }
So the above code presents how the boxes are being repainted when im calling the method.
Works fine but now for the next part of the code:
private void Change_ColourBox(object sender, System.Windows.RoutedEventArgs e)
{
var element = sender as FrameworkElement;
ObservableCollection<ClassBox> classes = viewModel.Classes;
foreach (ClassBox j in classes)
{
// connect our ui element to the mouse handler if not done already
if (sender == BoxStandard)
{
j.Box.Background = new SolidColorBrush(Colors.White);
j.Box.Foreground = new SolidColorBrush(Colors.Black);
Repaint();
} }
This code tell that we should change color when the button "Change_Color" is pressed.
I have implemented the buttons in XAML and I have given them names, in this case "BoxStandard".
The next code snipp is where i spawn the box via an event handler.
private void Spawn_Box(object sender, System.Windows.RoutedEventArgs e) {
viewModel.GetURController.AddAndExecute(new AddClassCommand(viewModel));
}
Im gonna line it up: I give predefined colors to my elements which they start out with. When I change the colors via the click event "Change_Color" they change to the desired color. BUT when I then spawn a new element to the canvas its in the predefined color. I want to spawn it with the changed color.
Ask if you don't understand question I can explain deeper!
The ClassBox is an object which consists of properties for the boxes. The repaint is not only for foreground/background color its also calculating the difference in positioning of the boxes

Events and Buttons

I want to get the text of the button whenever I click on it.
The algorithm that I made is where i have a function that is a loop that creates a number of buttons and assigns numbers:
void ListAllPage()
{
if (pageMax < 50)
{
//if page max less than 50
for (int i = 0; i < pageMax; i++)
{
Button newBtn = new Button();
newBtn.Text = i.ToString();
newBtn.Width = 50;
newBtn.Click += page_Clicked;
pageCell.Controls.Add(newBtn);
}
}
}
Now buttons will appear on the screen, their events will be triggered and the function page_Click; will be executed:
public void page_Clicked(object sender, EventArgs e)
{
//inside this function I want to obtain the button number that was clicked by the user. How do I do that?
}
Take note, I must all the functions that I described here,...
My thinking is to feed all the buttons that i created inside the loop to a dictionary..
Dictionary.. it will take variables like this btndic.Add(Button b=new Button,b.text);
But the issue is how to retrieve the buttons,,,
if there is a better way, i would like to hear about it...
instead of using the Click Event -> Use the Command Event: http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.button.oncommand.aspx then you can distinguish which button has been clicked
You just need to cast the sender object to a Button, or more generally, a Control:
public void page_Clicked(object sender, EventArgs e)
{
Control c = sender as Control;
MessageBox.Show("Clicked on " + c.Text);
}
Also, it might be more appropriate to use the Tag property to store your custom information (number). In that case, Text property can be anything you like.
Try this way
public void page_Clicked(object sender, EventArgs e)
{
Button btn=(Button)sender;
}
in your ListAllPage method assign Tag to each button:
newBtn.Tag = i;
In your handler you can obtain button instance from sender:
var clickedButton = (Button)sender;
int pageIndex = (int)clickedButton.Tag;

Custom button in C#: How to remove hover background?

I'm trying to do a custom button to my form (which has FormBorderStyle = none) using Visual Studio 2005. I have my 3 states button images in an ImageList linked to the button.
this.btnClose.AutoSize = false;
this.btnClose.BackColor = System.Drawing.Color.Transparent;
this.btnClose.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
this.btnClose.FlatAppearance.BorderSize = 0;
this.btnClose.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnClose.ForeColor = System.Drawing.Color.Transparent;
this.btnClose.ImageKey = "Disabled";
this.btnClose.ImageList = this.imageList1;
this.btnClose.Location = new System.Drawing.Point(368, -5);
this.btnClose.Margin = new System.Windows.Forms.Padding(0);
this.btnClose.Name = "btnClose";
this.btnClose.Size = new System.Drawing.Size(31, 31);
this.btnClose.TabIndex = 0;
this.btnClose.UseVisualStyleBackColor = false;
this.btnClose.MouseLeave += new System.EventHandler(this.btnClose_MouseLeave);
this.btnClose.Click += new System.EventHandler(this.btnClose_Click);
this.btnClose.MouseDown += new System.Windows.Forms.MouseEventHandler(this.btnClose_MouseDown);
this.btnClose.MouseHover += new System.EventHandler(this.btnClose_MouseHover);
private void btnClose_MouseHover(object sender, EventArgs e)
{
btnClose.ImageKey = "enabled";
}
private void btnClose_MouseDown(object sender, MouseEventArgs e)
{
btnClose.ImageKey = "down";
}
private void btnClose_MouseLeave(object sender, EventArgs e)
{
btnClose.ImageKey = "disabled";
}
All is working, but there's one catch. Whenever I move the mouse hover the button I get a really annoying grey background.
How can I remove that?
btnClose.FlatAppearance.MouseOverBackColor = System.Drawing.Color.Transparent;
The grey background is due to the setting of "System.Windows.Forms.FlatStyle.Flat", it's the default behaviour, since it need to highlight the button when you hover. To eliminate that, you might have to write a custom button class, inherit from the original button and do some custom painting to achieve that.
Btw, instead of setting "enabled" in MouseHover, you should do it in MouseEnter. MouseEnter and MouseLeave is a pair which indicate whether is the mouse is within the button or not, and it's fired once per entry/exit. Where as MouseHover is fire whenever the mouse moved within the button, which create unnessecery repeated setting of "enabled".
I've solved this using a label instead of a button.
//
// imageListButtons
//
this.imageListButtons.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageListButtons.ImageStream")));
this.imageListButtons.TransparentColor = System.Drawing.Color.Transparent;
this.imageListButtons.Images.SetKeyName(0, "close_normal");
this.imageListButtons.Images.SetKeyName(1, "close_hover");
//
// lblClose
//
this.lblClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.lblClose.BackColor = System.Drawing.Color.Transparent;
this.lblClose.ImageKey = "close_normal";
this.lblClose.ImageList = this.imageListButtons;
this.lblClose.Location = new System.Drawing.Point(381, 7);
this.lblClose.Margin = new System.Windows.Forms.Padding(0);
this.lblClose.Name = "lblClose";
this.lblClose.Size = new System.Drawing.Size(12, 12);
this.lblClose.TabIndex = 0;
this.lblClose.MouseLeave += new System.EventHandler(this.lblClose_MouseLeave);
this.lblClose.MouseClick += new System.Windows.Forms.MouseEventHandler(this.lblClose_MouseClick);
this.lblClose.MouseEnter += new System.EventHandler(this.lblClose_MouseEnter);
private void lblClose_MouseEnter(object sender, EventArgs e)
{
lblClose.ImageKey = "close_hover";
}
private void lblClose_MouseLeave(object sender, EventArgs e)
{
lblClose.ImageKey = "close_normal";
}
private void lblClose_MouseClick(object sender, MouseEventArgs e)
{
this.Close();
}
PS: notice that I'm using now a two state button, instead of three. It is intended (I know that I still can use three).
create Mouse Enter event which is given below.
private void forAllButtons_MouseEnter(object sender, EventArgs e)
{
Button b = (Button)sender;
b.FlatAppearance.MouseOverBackColor = System.Drawing.Color.Transparent;
}
then assign this event to all the buttons.
Happy programming :)
I have got one suggestion.Create your own button class deriving from Button.Then override the MouseEnter event in that.Just remove the code for calling the base implementaion.
base.OnMouseEnter(e)
PS: You won't be able to use the MouseEnter event outside the derived class (e.g. a project using this control)
Hi you simply can apply these changes to your button easily using these two lines of codes.
Set the button's FlatStyle to Flat
this.btnClose.FlatStyle = FlatStyle.Flat;
Set the button's MouseOverBackColor to Transparent
this.btnClose.FlatAppearance.MouseOverBackColor = Color.Transparent;
Hope this will help. Thanks
You can also stop changing color of button by deselecting IsHitTestVisible option in Button Properties>common> IsHitTestVisible
Maybe this can also help ...
To solve the problem, Set the MouseOverBackColor to transparent inorder to remove the grey backgroud.

Categories