Imagine that i have 10 buttons and i want to use mouse enter event to increase buttons width and height by 30. if i want to do this i have to use mouse event for each of them one by one,
how can i write my code only once for all buttons.i'm trying to use foreach loop but not sure if i should use form load and don't know how to handle event. (windows form)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace main
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
foreach (Control item in Controls)
{
if (item is Button)
{
// code
}
}
}
}
}
First of all shorten your code by getting only the buttons on the form. Then add an eventhandler for the MouseEnter event:
foreach (Button btn in Controls.OfType<Button>())
{
btn.MouseEnter += new System.EventHandler(btn_MouseEnter);
}
Then in the event change the width:
private void btn_MouseEnter(object sender, System.EventArgs e)
{
var senderButton = (Button)sender;
senderButton.Width += 30;
}
You'all also have to add an event handler + event for MouseLeave to decrease the width again. Otherwise the buttons will keep on growing:
foreach (Button btn in Controls.OfType<Button>())
{
btn.MouseEnter += new System.EventHandler(btn_MouseEnter);
btn.MouseLeave += new System.EventHandler(btn_MouseLeave );
}
private void btn_MouseEnter(object sender, System.EventArgs e)
{
var senderButton = (Button)sender;
senderButton.Width += 30;
}
private void btn_MouseLeave (object sender, System.EventArgs e)
{
var senderButton = (Button)sender;
senderButton.Width -= 30;
}
The foreach-loop code can be added after InitializeComponent() or in the Form_Load event.
private void Form1_Load(object sender, System.EventArgs e)
{
foreach (Button btn in Controls.OfType<Button>())
{
btn.MouseEnter += new System.EventHandler(btn_MouseEnter);
btn.MouseLeave += new System.EventHandler(btn_MouseLeave );
}
}
You can easily loop through your all buttons using OfType extension method like this:
foreach(var button in this.Controls.OfType<Button>())
{
button.MouseEnter += button_MouseEnter;
}
Use functions to wrap your logic.
Write your code that change the weight and width in method, an subscribe to MouseMove or whatever event that suits you.
Then use GetChildAtPoint to locate the button, so you can change its size.
// This goes in the
foreach(var button in this.Controls.OfType<Button>())
{
button.Mouse += button_IncreaseSize;
}
protected override void button_IncreaseSize(MouseEventArgs e)
{
// use GetChildAtPoint to get the control
var button = GetChildAsPoint(new Point(e.X, e.Y));
// Change the size of button, eg. with Scal, and with the Size property, or by chaning Height and Width propertis manually
button.Scale(new SizeF(30, 30));
}
Alternatively you can also do this:
private void Form1_Load(object sender, EventArgs e)
{
foreach (Control item in this.Controls)
{
if (item is Button)
{
//item.MouseEnter += (s, ea) => { YourMethodName(); };
item.MouseEnter += new System.EventHandler(btn_MouseEnter);
}
}
}
private void btn_MouseEnter(object sender, System.EventArgs e)
{
//your code to increase width and height
var btnSenderButton = sender as Button;
btnSenderButton.Width += 30;
}
Related
I am facing an issue over here. I want to remove the dynamic created button by press the X button.
The function will be user press X button, then press the button he/she want to delete, the button will be remove.
For now my program is able to create a new button but I do not know how to delete it, here is my coding, please help me , thanks very much!!
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp2
{
public partial class graphtest : Form
{
public graphtest()
{
InitializeComponent();
}
private Point Origin_Cursor;
private Point Origin_Control;
private bool BtnDragging = false;
private void button1_Click(object sender, EventArgs e)
{
var b = new Button();
b.Width = 54;
b.Height = 58;
b.Image = Image.FromFile(#"C:\Users\prod01\Desktop\Mote.png");
b.Text = "";
b.Name = "button";
//b.Click += new EventHandler(b_Click);
b.MouseUp += (s, e2) => { this.BtnDragging = false; };
b.MouseDown += new MouseEventHandler(this.b_MouseDown);
b.MouseMove += new MouseEventHandler(this.b_MouseMove);
this.Controls.Add(b);
}
private void b_MouseDown(object sender, MouseEventArgs e)
{
Button ct = sender as Button;
ct.Capture = true;
this.Origin_Cursor = System.Windows.Forms.Cursor.Position;
this.Origin_Control = ct.Location;
this.BtnDragging = true;
}
private void b_MouseMove(object sender, MouseEventArgs e)
{
if (this.BtnDragging)
{
Button ct = sender as Button;
ct.Left = this.Origin_Control.X - (this.Origin_Cursor.X - Cursor.Position.X);
ct.Top = this.Origin_Control.Y - (this.Origin_Cursor.Y - Cursor.Position.Y);
}
}
private void graphtest_Load(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
for (int ix = this.Controls.Count - 1; ix >= 0; ix--)
{
if (this.Controls[ix] is Button) this.Controls[ix].Dispose();
}
}
}
}
Here is how you can do that
//a list where you save all the buttons created
List<Button> buttonsAdded = new List<Button>();
private void button2_Click(object sender, EventArgs e)
{
Button myText = new Button();
myText.Tag = counter;
myText.Location = new Point(x2,y2);
myText.Text = Convert.ToString(textBox3.Text);
this.Controls.Add(myText);
//add reference of the button to the list
buttonsAdded.Insert(0, myText);
}
//atach this to a button removing the other buttons
private void removingButton_Click(object sender, EventArgs e)
{
if (buttonsAdded.Count > 0)
{
Button buttonToRemove = buttonsAdded[0];
buttonsAdded.Remove(buttonToRemove);
this.Controls.Remove(buttonToRemove);
}
}
Ref :- how to delete a button run time?
I have a simple TextBox:
<TextBox Name="PART_txtBx" IsReadOnly="True" ScrollViewer.VerticalScrollBarVisibility="Auto" />
and from codebehind i add some text every while:
public MainWindow()
{
InitializeComponent();
DispatcherTimer dt = new DispatcherTimer();
dt.Interval = TimeSpan.FromMilliseconds(100);
dt.Tick += dt_Tick;
dt.Start();
}
void dt_Tick(object sender, EventArgs e)
{
PART_txtBx.Text += "hi\n";
}
when i click on the textbox it automatically put the scrollbar on top when i add some text to it.
if I handle the PreviewMouseLeftButtonDown event like this:
private void PART_txtBx_PreviewMouseLeftButtonDown_1(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
}
the textbox works normally but i can't (of course) select any text.
any ideas to prevent this behavior?
EDIT 1:
I noticed when the textbox is created there isn't any caret in it even if it has got focus. the caret is shown only when the click is executed but i can't find what's changed inside the textbox after the click.
My TextBox is read only so i don't need the caret.
May: PART_txtBx.CaretIndex =PART_txtBx.Length;
or:
PART_txtBx.SelectionStart = PART_txtBx.Text.Length;
PART_txtBx.ScrollToCaret();
ScrollToEnd().
with textbox_changed event
You need to extend your TextBox control to add PreviewTextChanged event, like it is described here. On PreviewTextChanged you will have to remember SelectionStart and SelectionLength
Handle event ScrollViewer.ScrollChanged for your TextBox:
ScrollViewer.ScrollChanged="OnScrollChanged" <!--in xaml-->
private void OnScrollChanged(object sender, ScrollChangedEventArgs e)
{
// here you could prevent scrolling
isOnBottom = (sender as TextBox).VerticalOffset + (sender as TextBox).ViewportHeight == (sender as TextBox).ExtentHeight;
}
Handle TextChanged event:
TextChanged="OnTextChanged"
private void OnTextChanged(object sender, TextChangedEventArgs e)
{
if (isOnBottom) (sender as TextBox).ScrollToEnd();
// and here you can select text that was selected earlier
// by using remembered SelectionStart and SelectionLength
}
In the case of manual text entering you will have to prevent text selection
Hope, it helps
So i created my own CustomTextblock for resolving this issue:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace CE.EthernetMessagesManager.Views
{
public class CustomTextBox : TextBox
{
private int realCaretIndex = 0;
private bool triggeredByUser = false;
private bool isScrollingWithMouse = false;
public CustomTextBox()
: base()
{
this.PreviewMouseLeftButtonDown += CustomTextBox_PreviewMouseLeftButtonDown;
this.PreviewMouseLeftButtonUp += CustomTextBox_PreviewMouseLeftButtonUp;
this.PreviewMouseMove += CustomTextBox_PreviewMouseMove;
this.PreviewMouseWheel += CustomTextBox_PreviewMouseWheel;
this.TextChanged += CustomTextBox_TextChanged;
this.LostFocus += CustomTextBox_LostFocus;
this.AddHandler(ScrollViewer.ScrollChangedEvent, new RoutedEventHandler((X, S) =>
{
if ((S as ScrollChangedEventArgs).VerticalChange != 0 && triggeredByUser)
{
TextBox textBox = (X as TextBox);
int newLinePosition = 0;
newLinePosition = (int)(((S as ScrollChangedEventArgs).VerticalChange + textBox.ExtentHeight) / (textBox.FontSize + 2));
realCaretIndex += newLinePosition * ((S as ScrollChangedEventArgs).VerticalChange < 0 ? -1 : 1);
if (realCaretIndex < 0)
realCaretIndex = 0;
textBox.CaretIndex = realCaretIndex;
triggeredByUser = false;
}
}));
}
void CustomTextBox_LostFocus(object sender, System.Windows.RoutedEventArgs e)
{
e.Handled = true;
}
void CustomTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
TextBox textBox = sender as TextBox;
textBox.CaretIndex = realCaretIndex;
var max = (textBox.ExtentHeight - textBox.ViewportHeight);
var offset = textBox.VerticalOffset;
if (max != 0 && max == offset)
this.Dispatcher.Invoke(new Action(() =>
{
textBox.ScrollToEnd();
}),
System.Windows.Threading.DispatcherPriority.Loaded);
}
void CustomTextBox_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
{
triggeredByUser = true;
}
void CustomTextBox_PreviewMouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
if (isScrollingWithMouse)
{
TextBox textBox = sender as TextBox;
realCaretIndex = textBox.GetCharacterIndexFromPoint(Mouse.GetPosition(textBox), true);
}
}
void CustomTextBox_PreviewMouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
isScrollingWithMouse = false;
}
void CustomTextBox_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
TextBox textBox = sender as TextBox;
realCaretIndex = textBox.GetCharacterIndexFromPoint(Mouse.GetPosition(textBox), true);
triggeredByUser = true;
isScrollingWithMouse = true;
}
}
}
this CustomTextBox also pin the scrollbar to the bottom when i manually put it to bottom.
the xaml:
<v:CustomTextBox
IsReadOnly="True"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto"
/>
Sadly with this implementation selection is broken. I'll look into it
I am fairly new to C# and I am trying to change the color of a menustrip item when the mouse 'leaves' the button after its selected. But I can't use the MouseLeave as a boolean as it is an event. It tells 'MouseLeave can only appear on the left hand side of +='. Any tips?
Here is what I tried to do:
if (e.Item.MouseLeave)
{
using (Brush b = new SolidBrush(Color.FromArgb(80, 80, 80)))
{
e.Graphics.FillRectangle(b, e.Graphics.ClipBounds);
}
}
You can have a global boolean:
private void frm_Load(object sender, EventArgs e)
{
ctrl.MouseEnter += ctrl_MouseEnter;
ctrl.MouseLeave += ctrl_MouseLeave;
}
private bool bMouseInside = false;
private void ctrl_MouseEnter(object sender, EventArgs e)
{
bMouseInside = true;
}
private void ctrl_MouseLeave(object sender, EventArgs e)
{
bMouseInside = false;
}
To use in your code:
if (!bMouseInside)
{
// using (Brush b etc..
}
As MouseLeave is an event on a control, try something like this:
On creating the control, add a method to the event handler:
control.MouseLeave += control_MouseLeft;
Then define the action that you want to occur in your control_MouseLeft method.
void control_MouseLeft(objet sender, EventArgs e)
{
using (Brush b = new SolidBrush(Color.FromArgb(80, 80, 80)))
{
e.Graphics.FillRectangle(b, e.Graphics.ClipBounds);
}
}
I have multiple pictureboxes all added to an event handler, this is the method for the event handler:
private void Picturemethod(object sender, MouseEventArgs e)
And this is how i added the pictureboxes to the event handler
for (int j = 0; j < top.Length; j++)
{
top[j].MouseClick += new MouseEventHandler(Picturemethod);
}
All the pictureboxes are in the top Array.
How would i go by making the picturebox invisible when clicked in my method?
If the only thing you want to do on MouseClick is hide the current PictureBox, you could write it inline, using a lambda expression, and get rid of private void Picturemethod.
foreach (var t in top)
{
var t2 = t;
t.MouseClick += (s, a) => t2.Hide();
}
Alternative syntax, using a delegate (anonymous method):
foreach (var t in top)
{
var t2 = t;
t.MouseClick += delegate { t2.Hide(); };
}
You can use sender parameter to get the current picture box that trigger the event.
private void Picturemethod(object sender, MouseEventArgs e)
{
var pBox = sender as PictureBox;
if(pBox != null)
{
pBox.Visible = false;
}
}
You can cast object sender to PictureBox and set Visibile property as follows:
private void Picturemethod(object sender, MouseEventArgs e)
{
if (sender is PictureBox) { ((PictureBox)sender).Visible = false; }
else { /* Do nothing or throw ArgumentException */ }
}
On a C# Winform application. Imagine that I have a Panel with some labels inside.
How can I listen all click events from this labels in Panel click event?
You can do this programmatically by calling the following code in your Form_Load event handler or any other suitable event handler.
foreach (Label label in panel1.Controls.OfType<Label>())
{
label.Click += LabelOnClick;
}
And then perform your operations in the event handler:
private void LabelOnClick(object sender, EventArgs eventArgs)
{
MessageBox.Show("Label In Panel Clicked");
}
Why not add a extra event handler to all the Control of Type Button within a Panel?
Sample Code :
private void SetupButtonClickListenerForPanel1()
{
panel1.Click += ListenForAllButtonClickOnPanel1;
foreach (Control control in panel1.Controls)
{
var tb = control as Button;
if (tb != null)
{
tb.Click += ListenForAllButtonClickOnPanel1;
}
}
}
private void ListenForAllButtonClickOnPanel1(object sender, EventArgs eventArgs)
{
//
Button tb = (Button) sender; // casting will fail if click is on Panel1 itself!
MessageBox.Show(tb.Name);
}
Linq way to add Handler :
private void SetupButtonClickListenerForPanel1()
{
panel1.Click += ListenForAllButtonClickOnPanel1;
foreach (var tb in panel1.Controls.OfType<Button>())
{
tb.Click += ListenForAllButtonClickOnPanel1;
}
}
If your Labels are children of the panel, a listener for the Click Event on the panel will listen all non redefined listeners of his children.
Example Code:
{
//Form init
panel1.Click += new System.EventHandler(this.panel1_Click);
....
}
private void panel1_Click(object sender, EventArgs e)
{
//The clicked label will be sender.
Label l = (Label) sender; //Should be a safe cast. Will crash if sender is not a label
}