How to make a button on/off switch? - c#

Using VS2013, C#, .Net and Winforms how can I make a regular Button look "pressed"? Imagine this button is an on/off switch. ToolStripButton has the Checked property, but the regular Button does not.

Are you really forced to use a button or does it just have to look like one? For the latter you can just use a checkbox with the Appearance set to Button and Checked=true. This will make the checkbox appear like a button which is clicked.

If it is a custom requirement i.e. the button you need does not exist in the regular controls, I suggest you create a custom control button for your needs. Here is a link of a tutorial to create a custom control : How to: Create a Custom Image Button Control
You can also use a third party control like : Telerik Button - Radios and Checkboxes

Once the files are available to your site, activating the script is very easy:
...
$(document).ready(function() {
$(':checkbox').iphoneStyle();
});

You can change button's background image or background color in button click event handler.
Decalre somewhere in your code :
bool isClicked = false;
In event handler you can do :
private void button1_click(object sender, EventArgs e)
{
Button btn = sender as Button;
isClicked = !isClicked;
btn.BackgroundImage = isClicked? image1 : image2; // or use BackColor
}

There is a better and elegant solution. You can take a look how .NET draws it itself and try to do the same.
You should basically use
System.Windows.Forms.ButtonRenderer
class for drawing buttons in different states (Pressed, Hover etc.)
Please try to avoid using images for displaying states because to do it correctly, you would need to support different DPIs, sizing, proportions and so on. Rely on standard Render* classes fist.

Related

How does groupbox.Controls[i] or panel.Controls[i] work?

I am new to C# and was wondering how groupbox.Controls[i] and/oror panel.Controls[i] works?
I have a panel with a bunch of buttons in it to represent a keyboard. I change the color of the keyboard button when the key is pressed.
However, when I do keyboardPanel.Controls[2].BackColor = Color.Red;, my spacebar becomes red.
My spacebar is button55 and at TabIndex 54. Why is it my spacebar that turns red?
The reason that yoor space-bar gets red is simple: keyboardPanel.Controls[2] is the space-bar. please pay attention that the buttons are not necessarily added to the keyboardPanel.Controls list in the order they are named. Meaning: keyboardPanel.Controls[1] is not necessarily button1 and also button55 is not necessarily keyboardPanel.Controls[55].
Now, If you want to extract buttons by name you should use this:
keyboardPanel.Controls.Find("Button55" , true);
where "button55" is the name of that control and true goes for the option to search all the children.
But I think there is a simpler way to change the color. Using the Sender:
private void button_Click(object sender, EventArgs e)
{
Control btn = sender as Control;
btn.BackColor = Color.Red;
}
and make this method as the event handler of all the buttons' click event.
EDIT:
If you really want to re-arrange the controls in the GroupBox you should visit the the designer. The simple way to get to the designer is to right-click on InitializeComponent() in the constructor method of your form and choose Go To Definition.
There you will find the order that controls are added. something like below:
this.groupBox1.Controls.Add(this.button2);
this.groupBox1.Controls.Add(this.button3);
this.groupBox1.Controls.Add(this.button1);
I my case Controls[0] is button2, Controls[1] is button3 and so on. You can re-arrange them like below:
this.groupBox1.Controls.Add(this.button1);
this.groupBox1.Controls.Add(this.button2);
this.groupBox1.Controls.Add(this.button3);

How to check if button from user control was clicked?

It seems like a straight forward thing, but I can't figure it out.
How can I check if a certain button was clicked from user control?
my user control is uc_test and button name is btnTest .
I assume its some sort of event handler added to uc_test.btnTest ?
I'm working in WinForms.
It sounds like you've created a button but want to make it do something on click. I don't often use Winforms but from memory double-clicking on the control in the form should automatically create a btnTest_Click method. If not, just go to code and put in a method like:
protected void btnTest_Click(object sender, Eventargs e)
{
//do something
}
Then set in the properties of the button the OnClick event to btnTest_Click.

Dynamic Naming of C# Form Elements

My app needs to be able to dynamically create new form elements and work with them. Right now I have a panel with buttons and labels in it. I need to be able to make a duplicate of this and show it in my app and then work with it.
For example, I have panel1. Inside are label1, button1, and button2.
Label 1 just counts up by seconds.
When you click button1, label1 starts counting up. When you click button2, the timer stops.
My problem is that I need to be able to duplicate panel1 many times and still have the new buttons correspond to the correct labels.
On button_click
private void button1_Click(object sender, EventArgs e)
{
Button theSender = (Button)sender;
Panel parentPanel = (Panel)theSender.Parent;
}
From here, I can't target any of the child control . I'm used to targeting and handles in jQuery, so I don't even know the correct C# terminology for how to explain myself.
If understand your problem correctly, I recommend you to make a Usercontrol with a Panel and fill it with your Label, Button and whatever. Write the events for your buttons in the usercontrol. Then introduce this usercontrol in your form and it should work. You can introduce any number of usercontrols in your form and each button will behave/work for the label in that usercontrol only.
As you mentioned you are new in winforms and you are not sure what I am saying, let me know and I will help if I get enough time.
Hope it helps.
Children of a control can be accessed using Control.Contrtols collection, e.g. to access button on a form:
Button btn = this.Controls["button1"];
But that is only true if button1 is placed directly on your form and button1.Name property is set to "button1" (designer does that automattically, if you are creating your controls dynamically, you have to take care of naming your controls yourself.)
You can also enumerate child controls of any control, e.g. child controls of panel1:
foreach(Control c in panel1.Controls)
{
// do something, e.g.
if(c is Label){//do sth...}
if(c.Name.Equals("label1") && c is Label)
{
Label l = c as Label;
}
}
and as #rapsalands said, UserControl may be an answer for you.
I would create a user control (UserControl) for this.
Check this article for more explanation about the difference between Control and UserControl.
Controls and UserControls are easy to duplicate and the full functionality is there.
You can create new UI Controls in code as you would any other object: Button b = new Button();
Then you can add them to the form using form.Controls.Add(b). You'll need to position and size the controls as well (there are properties available for doing this) and hook up your event handlers using b.Clicked += form.button_click;.
To see an example of this, you can try having a look at the designer.cs file that is generated in Visual Studio (don't make changes to it, just have a look). It will look quite complex at first but might go some way to helping demystify Windows Forms, and you will be able to find all of the properties you need to set in there.
Whenever you update something in the designer, Visual Studio generates new code and puts it in the designer.cs file. The entire form is set up in the InitializeComponent() method, which is called from the constructor of your form. You should be able to copy some of that code and with a couple of modifications use it for creating your own dynamic UI elements.
As rapsalands says, it sounds like a user control would be useful in this situation, as it will help encapsulate the functionality you're after. However that may take a bit of time to get your head round and you may find it simpler for now to do everything in your form without creating a new control.
So you are a beginner and need some time to understand Usercontrol as I mentioned in my previous answer. Use a for loop in the Constructor or Load event of your form to dynamically generate controls.
Panel panel;
Label label;
Button button1;
Button button2;
for(int i = 0; i > count; i++)
{
panel = new Panel();
button1 = new Button();
button2 = new Button();
label = new Label();
panel.Controls.Add(button1);
panel.Controls.Add(button2);
panel.Controls.Add(label);
Controls.Add(panel);
button1.Click += Event1;
button2.Click += Event2;
}
private void Event1()
{
label.Text = "Button 1 Clicked."
}
private void Event2()
{
label.Text = "Button 2 Clicked."
}
This way certainly you can create as many controls you want and will also serve your purpose. Use some variables to locate the panel controls appropriately. Set any properties you wish to add in the for loop for the controls.
This is just an alternative for my previous answer. I still recommend the previous answer given by me. This code is dummy and not tested.
Hope it helps.

C#, fire event of container

I have a MyButton class that inherits from Button. On this class I have placed several other controls (Labels, Progessbar). The problem with this is that the controls on the Button make it impossible to fire the Button.Click or Button.MouseHover event. How can I achieve it that the controls on the Button are only displayed but are "event transparent": A click/hover on the label and progessbar is the same as if I clicked/hover directly on the Button (including sender and everything). Something like "inheriting the events from the parent".
class MyButton : Button
{
Label foo = new Label();
ProgressBar bar = new ProgessBar();
}
You should derive from UserControl then have the button as a child control, and bubble up the button child's on click event.
This link is probably more than what you need, but it's a good starting point.
UPDATE
As pointed out, you may not be using ASP.NET. So here is another post that talks about different custom user controls, specifically what you're after is a Composite Control. This is for Windows Forms.
Write Click event handlers for the label and PB, have them call PerformClick().
Making controls transparent to the mouse is possible but is ugly to do. You'd have to override WndProc() to catch WM_NCHITTEST and return HTTRANSPARENT. The all-around better solution is to not use controls. A Label is just TextRenderer.DrawText() in the button's Paint event. ProgressBar isn't hard either, e.Graphics.FillRectangle().
Having the child controls be real controls in front of the button (either in a class inheriting from Button or from UserControl) may make it hard to get button-specific events working properly, as you have found. (Edit: Although it's hard, it's not impossible -- see Hans Passant's answer)
As a workaround, instead of using child controls, you could custom-paint them onto the button surface, since you don't need most of the functionality of the controls (events, focusing, etc.), just their display.
You can do the additional painting in the OnPaint method of your class. Something like:
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.DrawString("My fake label", Font,
SystemBrushes.ControlText, new Point(10, 10))
// draw progressbar
}
To update the display, you would need to trigger a repaint of the Button using Invalidate().
Take a look at Custom Bitmap Button Using C# on CodeProject for a more complete example.
This answer was here a moment ago, but got deleted:
Can you inherit from UserControl instead? This will allow you to place other controls on the control surface, including your button and subscribe to their events.
If you're using WPF, I guess what you're looking for would be something called Bubbled Events. It's a feature in WPF by which events are bubbled from a control to its parent (in your case, it would be from your ProgressBar and Label to your button). I found this article on the matter which I think would be of help to you.
Hope this helps :)

How do I programmatically wire up ToolStripButton events in C#?

I'm programmatically adding ToolStripButton items to a context menu.
That part is easy.
this.tsmiDelete.DropDownItems.Add("The text on the item.");
However, I also need to wire up the events so that when the user clicks the item something actually happens!
How do I do this? The method that handles the click also needs to receive some sort of id or object that relates to the particular ToolStripButton that the user clicked.
Couldn't you just subscribe to the Click event? Something like this:
ToolStripButton btn = new ToolStripButton("The text on the item.");
this.tsmiDelete.DropDownItems.Add(btn);
btn.Click += new EventHandler(OnBtnClicked);
And OnBtnClicked would be declared like this:
private void OnBtnClicked(object sender, EventArgs e)
{
ToolStripButton btn = sender as ToolStripButton;
// handle the button click
}
The sender should be the ToolStripButton, so you can cast it and do whatever you need to do with it.
Thanks for your help with that Andy. My only problem now is that the AutoSize is not working on the ToolStripButtons that I'm adding! They're all too narrow.
It's rather odd because it was working earlier.
Update: There's definitely something wrong with AutoSize for programmatically created ToolStripButtons. However, I found a solution:
Create the ToolStripButton.
Create a label control and set the font properties to match your button.
Set the text of the label to match your button.
Set the label to AutoSize.
Read the width of the label and use that to set the width of the ToolStripButton.
It's hacky, but it works.

Categories

Resources