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

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.

Related

Win forms, how to assign a method to radio button when checked

I am new to c# and Win forms so please be patient with me.
I have e radio buttons that has been written programatically. I want to update the value of which button is checked. Here is the code for one of the buttons
RadioButton cab = new RadioButton();
cab.Text = m_appContext.L10nManager.TranslateString("Modern");
cab.Name = "Modern";
cab.Location = new Point(15, 45);
cab.AutoSize = true;
I want to assign a "method" when it is checked. So I go ahead add this to my radio button:
ca.Checked = m_appContext.EWSMode;
Here is the code for EWSMode:
public enum EWSMode { Auto = 0, EWS = 1, Classical = 2 };
EWSMode m_EWSMode = EWSMode.Auto;
public EWSMode EWSMode
{
get { return m_EWSMode; }
set { m_EWSMode = value; }
}
Depending on which radio button is selected I want to set m_EWSMode to that value. So by default
EWSMode m_EWSMode = EWSMode.Auto;
When, say radio button EWS is selected I want to set m_EWSMode to EWS
At what point do I set/pass the new value to my EWSMode enum and how do I do it?
You have to use an EventHandler, like this:
ca.Checked += new System.EventHandler(EWSMode);
Note that EWSMode has to have the correct signature, taking object and EventArgs as parameters:
private void EWSMode(object sender, EventArgs e)
If you want to set a variable's value according to what check is selected, you can subscribe them both to an event handler:
ca1.Checked += new System.EventHandler(EWSMode_Event);
ca2.Checked += new System.EventHandler(EWSMode_Event);
And then put the logic in EWSMode_Event:
private void EWSMode_Event(object sender, EventArgs e)
{
//When ca1 or ca2 gets checked, this event will be triggered. Here, you would
//set your m_EWSMode variable.
}
You can do the same thing using one event for each CheckBox:
ca1.Checked += new System.EventHandler(EWSMode_Event);
private void EWSMode_Event(object sender, EventArgs e)
{
//When ca1 gets checked, this event will be triggered.
EWSMode m_EWSMode = EWSMode.EWS;
}

Datagridview shall disappear when clicking on the Form in the background

As described in the title, I have a Form with a Datagridview on the front. The datagridview is smaller than my form in the back and I want the Datagridview to disappear whenever I click anywhere else but the Datagridview.
My code looks like this:
this.dataGridView1.Leave += new System.EventHandler(this.focus);
and the Eventhandler is defined like this:
private void focus(object sender, EventArgs e)
{
if(dataGridView1.Focused == false)
{
dataGridView1.Visible = false;
}
}
My problem is that my Datagridview only disappears when a new event in my form is activated but not when I click for example in a textbox on my form.
Can anyone help me?
The Leave event will not raise if you click on Form, or a ToolStripButton, PictureBox or any other non-selectable control.
If you expect a behavior like a dropdown, you can host DataGridView in a ToolStripControlHost and show it using a ToolStripDropDown. This way when you click anywhere outside the `DataGridView, it will disappear. It will act like a dropdown menu. Also the grid can be larger than your form:
private void button1_Click(object sender, EventArgs e)
{
this.dataGridView1.Margin = new Padding(0);
var host = new ToolStripControlHost(this.dataGridView1);
this.dataGridView1.MinimumSize = new Size(200, 100);
host.Padding = new Padding(0);
var dropdown = new ToolStripDropDown();
dropdown.Padding = new Padding(0);
dropdown.Items.Add(host);
dropdown.Show(button1, 0,button1.Height);
}
Important Note: It's an example. It's better to pay attention to disposing of objects in a real world application. For example, use just a single ToolStripdropDown and dispose it when closing the form.
Change the event handler assigning to:
this.dataGridView1.Leave += new System.EventHandler(fokussiert);
Worked for me when focusing on a textbox
you want your dgv also to disapear when you click on your textbox? is that what you mean?
private void dataGridView1_Leave(object sender, EventArgs e)
{
dataGridView1.Visible = false;
}
private void Form1_Click(object sender, EventArgs e)
{
dataGridView1.Visible = false;
}

NullReferenceException dynamically created controls, object seems to exist

In Win Forms I have these three test methods. First to create a button, second to create a tab control with two tabs and third to move created button to first tab.
private void button1_Click(object sender, EventArgs e)
{
Button przycisk = new Button();
przycisk.Location = new Point(24, 250);
przycisk.Name = "nowy";
przycisk.Text = "utworzony";
przycisk.Width = 131;
przycisk.Height = 23;
Controls.Add(przycisk);
}
private void button2_Click(object sender, EventArgs e)
{
TabControl zakladki = new TabControl();
zakladki.Location = new Point(208, 160);
zakladki.Name = "zakl";
zakladki.Height = 150;
zakladki.Width = 208;
zakladki.TabPages.Add("zakladka1", "pierwsza");
zakladki.TabPages.Add("zakladka2", "druga");
Controls.Add(zakladki);
}
private void button3_Click(object sender, EventArgs e)
{
TabControl zakladki = (TabControl)Controls.Find("zakl", false).FirstOrDefault();
int numerZakladki = 1;
foreach (TabPage zakladka in zakladki.TabPages)
{
Control kt = Controls["nowy"];
kt.Location = new Point(10, 10); // System.NullReferenceException
zakladka.Controls.Add(kt);
numerZakladki++;
}
}
I'm having a hard time to understand the behavior upon trying to change the referenced button location. The code above throws System.NullReferenceException, but when I do
if (kt != null)
{
kt.Location = new Point(10, 10);
}
it works as expected. Can anyone explain it to me ?
The new TabControl contains two Tabs.
If you move the button to the first Tab, the control at the Main form is null.
Code without Loop:
private void button3_Click(object sender, EventArgs e)
{
TabControl zakladki = (TabControl)Controls.Find("zakl", false).FirstOrDefault();
Control kt = Controls["nowy"];
kt.Location = new Point(10, 10);
zakladki.TabPages[0].Controls.Add(kt);
}
Your nowy controls are added to the root control (Form I guess), but you are trying to find them in the tab pages under zakl. You have to either add the controls to the tab page, or find them in the root control, just like you did with zakl.
You move the "nowy" button from the Form.Controls to the first TabPage's Controls collection. This removes the control from the first collection, so the code throws the exception on the next iteration. A Control can have only a singleParent.
Either create the Button for each tab separately (instead of moving it), or add the Button to the first tab only (without the foreach loop).

Context Menu Strip -> Changing the color of Highlighted Items

So on my Context Menu Strip, I want to change the color of selected item.
For example, I Want Menu Item "About Me" to change color from White to Black when it has been highlighted.
This is What I been trying:
ContextMenuStrip CMS = new ContextMenuStrip();
CMS.ForeColor = Color.White;
CMS.ShowImageMargin = false;
var item = CMS.Items.Add("About Me", null);
item.MouseHover += new EventHandler(CMS_MouseHover);
void CMS_MouseHover(object sender, EventArgs e)
{
ContextMenuStrip CMS = sender as ContextMenuStrip;
CMS.ForeColor = Color.Black;
}
I also have tried playing around with the ToolStripMenuitem event handlers, but I don't think it will be applied here ?
Any suggestion on how I could accomplish this ?
I was also Wondering if there was a way to change the highlight color, I know it depends on your system but I was just wondering.
I'm not convinced this is the best way, but one possible way to do this is to wire up the MouseEnter and MouseLeave events on the individual ToolStripMenuItems on your ContextMenuStrip.
For example:
private void aboutToolStripMenuItem_MouseEnter(object sender, EventArgs e)
{
ToolStripMenuItem TSMI = sender as ToolStripMenuItem;
TSMI.ForeColor = Color.Black;
}
private void aboutToolStripMenuItem_MouseLeave(object sender, EventArgs e)
{
ToolStripMenuItem TSMI = sender as ToolStripMenuItem;
TSMI.ForeColor = Color.White;
}
Obviously, you also need to also wire up the event handlers on your programatically created ToolStripMenuItem.
You seem to be trying to change the ForeColor of the whole ContextMenuStrip with "CMS.ForeColor = Color.Black", which isn't what you said you wanted. Tried the above and it does work.

ToggleButton in C# WinForms

Is it possible to create a toggle button in C# WinForms? I know that you can use a CheckBox control and set it's Appearance property to "Button", but it doesn't look right. I want it to appear sunken, not flat, when pressed. Any thoughts?
You can just use a CheckBox and set its appearance to Button:
CheckBox checkBox = new System.Windows.Forms.CheckBox();
checkBox.Appearance = System.Windows.Forms.Appearance.Button;
Check FlatStyle property. Setting it to "System" makes the checkbox sunken in my environment.
You may also consider the ToolStripButton control if you don't mind hosting it in a ToolStripContainer. I think it can natively support pressed and unpressed states.
thers is a simple way to create toggle button. I test it in vs2010. It's perfect.
ToolStripButton has a "Checked" property and a "CheckOnClik" property. You can use it to act as a toggle button
tbtnCross.CheckOnClick = true;
OR
tbtnCross.CheckOnClick = false;
tbtnCross.Click += new EventHandler(tbtnCross_Click);
.....
void tbtnCross_Click(object sender, EventArgs e)
{
ToolStripButton target = sender as ToolStripButton;
target.Checked = !target.Checked;
}
also, You can create toggle button list like this:
private void Form1_Load(object sender, EventArgs e)
{
arrToolView[0] = tbtnCross;
arrToolView[1] = tbtnLongtitude;
arrToolView[2] = tbtnTerrain;
arrToolView[3] = tbtnResult;
for (int i = 0; i<arrToolView.Length; i++)
{
arrToolView[i].CheckOnClick = false;
arrToolView[i].Click += new EventHandler(tbtnView_Click);
}
InitTree();
}
void tbtnView_Click(object sender, EventArgs e)
{
ToolStripButton target = sender as ToolStripButton;
if (target.Checked) return;
foreach (ToolStripButton btn in arrToolView)
{
btn.Checked = false;
//btn.CheckState = CheckState.Unchecked;
}
target.Checked = true;
target.CheckState = CheckState.Checked;
}
How about this?
Assuming you have System.Windows.Forms referenced.
var cbtnToggler = new CheckBox();
cbtnToggler.Appearance = Appearance.Button;
cbtnToggler.TextAlign = ContentAlignment.MiddleCenter;
cbtnToggler.MinimumSize = new Size(75, 25); //To prevent shrinkage!
Hope this helps ;)
This is my simple codes I hope it can help you
private void button2_Click(object sender, EventArgs e)
{
if (button2.Text == "ON")
{
panel_light.BackColor = Color.Yellow; //symbolizes light turned on
button2.Text = "OFF";
}
else if (button2.Text == "OFF")
{
panel_light.BackColor = Color.Black; //symbolizes light turned off
button2.Text = "ON";
}
}
When my button's FlatStyle is set to system, it looks flat. And when it's set to popup, it only pops up when mouses over. Either is what I want. I want it to look sunken when checked and raised when unchecked and no change while mousing over (the button is really a checkbox but the checkbox's appearance property is set to button).
I end up setting the FlatStyle to flat and wrote a new Paint event handler.
private void checkbox_paint(object sender, PaintEventArgs e)
{
CheckBox myCheckbox = (CheckBox)sender;
Rectangle borderRectangle = myCheckbox.ClientRectangle;
if (myCheckbox.Checked)
{
ControlPaint.DrawBorder3D(e.Graphics, borderRectangle,
Border3DStyle.Sunken);
}
else
{
ControlPaint.DrawBorder3D(e.Graphics, borderRectangle,
Border3DStyle.Raised);
}
}
I give a similar answer to this question:
C# winforms button with solid border, like 3d
Sorry for double posting.
You can always code your own button with custom graphics and a PictureBox, though it won't necessarily match the Windows theme of your users.
I ended up overriding the OnPaint and OnBackgroundPaint events and manually drawing the button exactly like I need it. It worked pretty well.
use if command to check status and let operate as a toggle button
private void Protection_ON_OFF_Button_Click(object sender, EventArgs e)
{
if (FolderAddButton.Enabled == true)
{
FolderAddButton.Enabled = false;
}
else
{
FolderAddButton.Enabled = true;
}
}
You should look into Siticone I use it and I love it. It works exactly like a checkbox but is a toggle button. Its downside is a message box will come up every time you open Visual Studios so I just installed a tool that disables it. You can also look into Guana but I found that to have a few bugs :)
Changing a CheckBox appearance to Button will give you difficulty in adjustments. You cannot change its dimensions because its size depends on the size of your text or image.
You can try this: (initialize the count variable first to 1 | int count = 1)
private void settingsBtn_Click(object sender, EventArgs e)
{
count++;
if (count % 2 == 0)
{
settingsPanel.Show();
}
else
{
settingsPanel.Hide();
}
}
It's very simple but it works.
Warning: This will work well with buttons that are occasionally used (i.e. settings), the value of count in int/long may be overloaded when used more than it's capacity without closing the app's process. (Check data type ranges: http://msdn.microsoft.com/en-us/library/s3f49ktz.aspx)
The Good News: If you're running an app that is not intended for use 24/7 all-year round, I think this is helpful. Important thing is that when the app's process ended and you run it again, the count will reset to 1.

Categories