So I have built an application in C# using Winforms and my application uses a few different buttons. I'd like to have a highlight on the button that has been clicked to show what 'tab' you're in.
I've tried doing the following;
// BUTTONS //
private void dashboard_btn_Click(object sender, EventArgs e)
{
// Load Form
OpenChildForm(new FormDashboard());
dashboard_btn.FlatAppearance.BorderColor = Color.Red;
dashboard_btn.FlatAppearance.BorderSize = 1;
}
However, this of course doesn't work nicely since it adds a border around the button but when I click another button the border also stays around the previous button.
How would you implement a feature to add a border around the button that get's clicked but have the border disappear after you click another button?
Thank you for any feedback!
EDIT:
I've implemented Jimi's advice and used the Leave event to change the border around the button back to 0. However I'm not sure how to implement this in a global way so all my buttons are subscribed to this event.
My code now looks like this;
// BUTTONS //
private void dashboard_btn_Click(object sender, EventArgs e)
{
// Load Form
OpenChildForm(new FormDashboard());
// Button Highlight
dashboard_btn.FlatAppearance.BorderColor = Color.Red;
dashboard_btn.FlatAppearance.BorderSize = 1;
}
// BUTTON REMOVE HIGHLIGHT //
private void dashboard_btn_Leave(object sender, EventArgs e)
{
dashboard_btn.FlatAppearance.BorderSize = 0;
}
EDIT 2:
I ended up using Jimi's example and this worked for me :)
This might lend itself to a RadioButton style functionality because clicking a different radio button in the same container will uncheck the others. So, to implement the "generalized approach" that you mention in your comment, you could make a simple custom RadioButtonEx class where the Appearance property is set to Button then change your border style when the Checked property changes. In this example, the Click event has been changed to static so that clicking on any button directs the event to the common onAnyClick method.
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
RadioButtonEx.Click += onAnyClick;
}
private void onAnyClick(object sender, EventArgs e)
{
label1.Text = ((RadioButtonEx)sender).Text;
}
}
public class RadioButtonEx : RadioButton
{
public static new event EventHandler Click;
public RadioButtonEx()
{
FlatAppearance.BorderColor = Color.Red;
FlatAppearance.BorderSize = 1;
Appearance = Appearance.Button;
}
protected override void OnCheckedChanged(EventArgs e)
{
base.OnCheckedChanged(e);
if(Checked)
{
FlatStyle = FlatStyle.Flat;
Click?.Invoke(this, EventArgs.Empty);
}
else
{
FlatStyle = FlatStyle.Standard;
}
}
}
I have an application with two windows. One window contains textboxes while the other window is the keyboard. My problem now is that when I click on my Keyboard window I encounter error. I cannot type on the textbox I clicked on the other window. Here is my code.
When I click one textbox from window I, I trigger this Mouse event.
private void TextBoxPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
textBox = sender as TextBox;
textBox.Focus();
}
I used sender as TextBox because my textboxes are programmatically added to my window. I used it to get the name of the textbox.
And here is my code when I click a button from my Keyboard window.
Let used button 1:
private void button_numeric_1_Click(object sender, RoutedEventArgs e)
{
Screen1 screen1 = new Screen1();
screen1.textBox.Text += "1";
}
Screen1 is the window containing my textboxes.
How I possibly able to type text in my textbox using my created keyboard. I'm using C#. Anyone please help me out.
instead of using new Screen1(); you may need to use the actual instance of the screen, you may pass the same to the keyboard via constructor.
example
class Screen
{
Keyboard keyboard;
public Screen()
{
//pass the screen instance to the keyboard
keyboard = new Keyboard(this);
}
//...
private void TextBoxPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
textBox = sender as TextBox;
textBox.Focus();
//open keyboard etc
keyboard.Show();
}
}
class Keyboard
{
private Screen screenInstance;
public Keyboard(Screen instance)
{
//store the instance in a member variable
screenInstance = instance;
}
//...
private void button_numeric_1_Click(object sender, RoutedEventArgs e)
{
//use the stored screen instance
screenInstance.textBox.Text += "1";
}
public void Show()
{
//display logic etc
}
}
above is just an example based on some assumptions, you may adjust/merge with your code as needed.
you may adjust the same to pass TextBox instance if you have multiple TextBoxes to be used
example
class Screen
{
Keyboard keyboard = new Keyboard();
private void TextBoxPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
textBox = sender as TextBox;
textBox.Focus();
//open keyboard etc
keyboard.Show(textBox);
}
}
class Keyboard
{
private TextBox textBoxInstance;
private void button_numeric_1_Click(object sender, RoutedEventArgs e)
{
//use the stored TextBox instance
textBoxInstance.Text += "1";
}
public void Show(TextBox instance)
{
textBoxInstance = instance;
//display logic etc
}
}
Alright, this is a little strange, but essentially I needed a message box class with buttons that did not come as options within the message box class in c#. Therefore, I read up on how to create my own class (here is the link if your interested: http://social.msdn.microsoft.com/Forums/vstudio/en-US/1086b27f-683c-457a-b00e-b80b48d69ef5/custom-buttons-in-messagebox?forum=csharpgeneral), and used an example provided inside of that. Here is the relevant code:
public partial class Form1 : Form
{
public static bool MessageSucceded { get; set; }
public static string MessageContent{ private get; set; }
private void buttonMyMessageBox_Click(object sender, EventArgs e)
{
using (MyMessageForm myForm = new MyMessageForm())
{
myForm.ShowDialog();
if (MessageSucceded = myForm.ShowDialog(this) == DialogResult.OK)
{
if (MessageContent== "Yes do it")
{
//HERE DO WHAT YOU WANT IF THE USER CLICKS ON BUTTON YES DO IT
}
else if (MessageContent== "No, don`t do it")
{
//HERE DO WHAT YOU WANT IF THE USER CLICKS ON BUTTON NO, DON`T DO IT
}
}
}
}
}
public partial class MyMessageForm : Form
{
private void MyMessageForm_Load(object sender, EventArgs e)
{
this.StartPosition = FormStartPosition.CenterScreen;
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.MinimizeBox = false;
this.MaximizeBox = false;
this.buttonYes.Text = "Yes do it";
this.buttonNo.Text = "No, don`t do it";
this.labelMyForm.Text = "Are you sure you want to… ?";
}
private void buttonYes_Click(object sender, EventArgs e)
{
Form1.MessageSucceded = true;
Form1.MessageContent= buttonYes.Text;
this.DialogResult = DialogResult.OK;
this.Close();
}
private void buttonNo_Click(object sender, EventArgs e)
{
Form1.MessageSucceded = true;
Form1.MessageContent= buttonNo.Text;
this.DialogResult = DialogResult.OK;
this.Close();
}
}
This works exactly as I intended it to, except for one small detail. Just before the message box pops up, for a split second, a terminal version of the message box form opens up, before it closes on its own and the windows form version opens and functions as expected. I can't understand why this is happening, and it isn't causing any performance issues that I can notice, but aesthetically it looks very bad. Does anyone know why this is happening or how to stop it? I'm using Visual Studio 2010 Express for what its worth. Thanks for any help you have and taking the time to read this.
Edit: heres my code for main:
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
You're invoking ShowDialog() twice:
myForm.ShowDialog();
if (MessageSucceded = myForm.ShowDialog(this) == DialogResult.OK) {
Form has been closed so it'll close immediatly, right way to do it is to save its first result and check that in your if condition:
var result = myForm.ShowDialog();
if (MessageSucceded = (result == DialogResult.OK)) {
Or directly:
MessageSucceded = myForm.ShowDialog() == DialogResult.OK;
if (MessageSucceded) {
Moreover if you returns different results according to clicked button then you do not need to compare MessageContent (it's also a bad idea to have a reference to caller just to return a result):
private void buttonYes_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.Yes;
this.Close();
}
private void buttonNo_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.No;
this.Close();
}
Note that now you can simply remove such code and add proper DialogResult property to each button (because assign Form.DialogResult and call Form.Close() is default behavior if Button.DialogResult property is assigned). Done that you can simply use it like this:
switch (myForm.ShowDialog())
{
case DialogResult.Yes:
break;
case DialogResult.No:
case DialogResult.Cancel: // Unless ControlBox is also Hidden
break;
}
As last note: if you're targeting Vista+ you may also check Task Dialog instead of writing a custom form (you may keep it as fallback for XP's users).
I have developed a windows form application in C#.Net. There are multiple forms in the application. Main form say frmA has a push button say btnA. On clicking btnA, new form say frmB is opened and frmA goes behind frmB. frmB also has a push button say btnB and position (location) of btnB on frmB is exactly same as that of btnA on frmA. On clicking btnB, some different actions take place.
Now my problem is some of application users double click on btnA. I get two single clicks back to back. On first single click on btnA, frmB is opened with btnB. Second single click is immediately executed on btnB and in effect users don't even get to see frmB.
My constraint is I cannot change locations of buttons on either forms. Is there anyway I can handle this problem?
Set btnB.Enabled to false and use the following code. This will delay the possibility to click the button for half a second.
public partial class frmB : Form
{
private Timer buttonTimer = new Timer();
public frmB()
{
InitializeComponent();
buttonTimer.Tick += new EventHandler(buttonTimer_Tick);
buttonTimer.Interval = 500;
}
private void frmB_Shown(object sender, EventArgs e)
{
buttonTimer.Start();
}
void buttonTimer_Tick(object sender, EventArgs e)
{
btnB.Enabled = true;
buttonTimer.Stop();
}
}
Just try to fire new form into different position.
As i've understood user is firing frmB on first click
and pressing btnB on "second click"
It's not double click.
It's two different clicks
try something like that:
Form2 form=new Form2();
form.StartPosition = FormStartPosition.Manual;
form.Location=new Point(0, 10);
form.Show();
I would do some trick, What about changing the cursor position. Once user click on btnA cursor point will be shifted a little so the second click will not hit the btnB.
this.Cursor = new Cursor(Cursor.Current.Handle);
Cursor.Position = new Point(Cursor.Position.X - 50, Cursor.Position.Y - 50);
Cursor.Clip = new Rectangle(this.Location, this.Size);
disable it on the first click enable it when the user open again the forma or it come from forma to form b
this.button.enable=false;
immediately after pressing the button.
and write again in the constructor of forma
this.button.enable=true;
I agree that this UI is not friendly but if you absolutely cannot change the position of the buttons or the open position of the second form then you need to stop the second click causing the closure of frmB. Easiest way would be to build in a delay upon opening formB e.g.
public partial class FormB : Form
{
public FormB()
{
InitializeComponent();
Thread.Sleep(2000);
}
}
You can use IMessageFilter to detect WM_LBUTTONDOWN messages and suppress them if they occur within a certain time threshold:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Application.AddMessageFilter(new DoubleClickSuppressser());
}
private void button1_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2();
f2.StartPosition = FormStartPosition.Manual;
f2.Location = this.Location;
f2.Show();
}
private void listBox1_MouseDoubleClick(object sender, MouseEventArgs e)
{
Console.WriteLine("listBox1 DoubleClick");
}
}
public class DoubleClickSuppressser : IMessageFilter
{
private int difference;
private DateTime Last_LBUTTONDOWN = DateTime.MinValue;
private const int WM_LBUTTONDOWN = 0x201;
public bool PreFilterMessage(ref Message m)
{
switch (m.Msg)
{
case WM_LBUTTONDOWN:
if (Control.FromHandle(m.HWnd) is Button)
{
if (!Last_LBUTTONDOWN.Equals(DateTime.MinValue))
{
difference = (int)DateTime.Now.Subtract(Last_LBUTTONDOWN).TotalMilliseconds;
Last_LBUTTONDOWN = DateTime.Now;
if (difference < System.Windows.Forms.SystemInformation.DoubleClickTime)
{
return true;
}
}
Last_LBUTTONDOWN = DateTime.Now;
}
break;
}
return false;
}
}
Note that I've specifically disabled Double Clicking only for Buttons with the Control.FromHandle() check. This will allow double clicks to work on other controls such as ListBoxes, etc...
In your own class, inherit the base control and use the .SetStyle() method to disable the double-click. The below code isn't for a Button, but it should work the same:
public class MOBIcon : PictureBox
{
public MOBIcon() : base()
{
this.SetStyle(ControlStyles.StandardDoubleClick, false);
}
}
The problem with enabling and disabling the button is that if the code you have in the click event runs so fast that the button gets enabled before the second click of the double click action (some users don't understand that it only takes 1 click) so here is my solution.
private const int waittime = 2;
private DateTime clickTime = DateTime.Now;
private void cmd_TimeStamp_Click(object sender, EventArgs e)
{
if ((DateTime.Now - clickTime).Seconds < waittime)
return;
else
clickTime = DateTime.Now;
try
{
cmd_TimeStamp.Enabled = false;
//Do some stuff in here
}
catch (Exception ex)
{
//Show error if any
MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
cmd_TimeStamp.Enabled = true;
}
}
I have an application with one form in it, and on the Load method I need to hide the form.
The form will display itself when it has a need to (think along the lines of a outlook 2003 style popup), but I can' figure out how to hide the form on load without something messy.
Any suggestions?
I'm coming at this from C#, but should be very similar in vb.net.
In your main program file, in the Main method, you will have something like:
Application.Run(new MainForm());
This creates a new main form and limits the lifetime of the application to the lifetime of the main form.
However, if you remove the parameter to Application.Run(), then the application will be started with no form shown and you will be free to show and hide forms as much as you like.
Rather than hiding the form in the Load method, initialize the form before calling Application.Run(). I'm assuming the form will have a NotifyIcon on it to display an icon in the task bar - this can be displayed even if the form itself is not yet visible. Calling Form.Show() or Form.Hide() from handlers of NotifyIcon events will show and hide the form respectively.
Usually you would only be doing this when you are using a tray icon or some other method to display the form later, but it will work nicely even if you never display your main form.
Create a bool in your Form class that is defaulted to false:
private bool allowshowdisplay = false;
Then override the SetVisibleCore method
protected override void SetVisibleCore(bool value)
{
base.SetVisibleCore(allowshowdisplay ? value : allowshowdisplay);
}
Because Application.Run() sets the forms .Visible = true after it loads the form this will intercept that and set it to false. In the above case, it will always set it to false until you enable it by setting allowshowdisplay to true.
Now that will keep the form from displaying on startup, now you need to re-enable the SetVisibleCore to function properly by setting the allowshowdisplay = true. You will want to do this on whatever user interface function that displays the form. In my example it is the left click event in my notiyicon object:
private void notifyIcon1_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
this.allowshowdisplay = true;
this.Visible = !this.Visible;
}
}
I use this:
private void MainForm_Load(object sender, EventArgs e)
{
if (Settings.Instance.HideAtStartup)
{
BeginInvoke(new MethodInvoker(delegate
{
Hide();
}));
}
}
Obviously you have to change the if condition with yours.
protected override void OnLoad(EventArgs e)
{
Visible = false; // Hide form window.
ShowInTaskbar = false; // Remove from taskbar.
Opacity = 0;
base.OnLoad(e);
}
At form construction time (Designer, program Main, or Form constructor, depending on your goals),
this.WindowState = FormWindowState.Minimized;
this.ShowInTaskbar = false;
When you need to show the form, presumably on event from your NotifyIcon, reverse as necessary,
if (!this.ShowInTaskbar)
this.ShowInTaskbar = true;
if (this.WindowState == FormWindowState.Minimized)
this.WindowState = FormWindowState.Normal;
Successive show/hide events can more simply use the Form's Visible property or Show/Hide methods.
Try to hide the app from the task bar as well.
To do that please use this code.
protected override void OnLoad(EventArgs e)
{
Visible = false; // Hide form window.
ShowInTaskbar = false; // Remove from taskbar.
Opacity = 0;
base.OnLoad(e);
}
Thanks.
Ruhul
Extend your main form with this one:
using System.Windows.Forms;
namespace HideWindows
{
public class HideForm : Form
{
public HideForm()
{
Opacity = 0;
ShowInTaskbar = false;
}
public new void Show()
{
Opacity = 100;
ShowInTaskbar = true;
Show(this);
}
}
}
For example:
namespace HideWindows
{
public partial class Form1 : HideForm
{
public Form1()
{
InitializeComponent();
}
}
}
More info in this article (spanish):
http://codelogik.net/2008/12/30/primer-form-oculto/
I have struggled with this issue a lot and the solution is much simpler than i though.
I first tried all the suggestions here but then i was not satisfied with the result and investigated it a little more.
I found that if I add the:
this.visible=false;
/* to the InitializeComponent() code just before the */
this.Load += new System.EventHandler(this.DebugOnOff_Load);
It is working just fine.
but I wanted a more simple solution and it turn out that if you add the:
this.visible=false;
/* to the start of the load event, you get a
simple perfect working solution :) */
private void
DebugOnOff_Load(object sender, EventArgs e)
{
this.Visible = false;
}
You're going to want to set the window state to minimized, and show in taskbar to false. Then at the end of your forms Load set window state to maximized and show in taskbar to true
public frmMain()
{
Program.MainForm = this;
InitializeComponent();
this.WindowState = FormWindowState.Minimized;
this.ShowInTaskbar = false;
}
private void frmMain_Load(object sender, EventArgs e)
{
//Do heavy things here
//At the end do this
this.WindowState = FormWindowState.Maximized;
this.ShowInTaskbar = true;
}
Put this in your Program.cs:
FormName FormName = new FormName ();
FormName.ShowInTaskbar = false;
FormName.Opacity = 0;
FormName.Show();
FormName.Hide();
Use this when you want to display the form:
var principalForm = Application.OpenForms.OfType<FormName>().Single();
principalForm.ShowInTaskbar = true;
principalForm.Opacity = 100;
principalForm.Show();
This works perfectly for me:
[STAThread]
static void Main()
{
try
{
frmBase frm = new frmBase();
Application.Run();
}
When I launch the project, everything was hidden including in the taskbar unless I need to show it..
Override OnVisibleChanged in Form
protected override void OnVisibleChanged(EventArgs e)
{
this.Visible = false;
base.OnVisibleChanged(e);
}
You can add trigger if you may need to show it at some point
public partial class MainForm : Form
{
public bool hideForm = true;
...
public MainForm (bool hideForm)
{
this.hideForm = hideForm;
InitializeComponent();
}
...
protected override void OnVisibleChanged(EventArgs e)
{
if (this.hideForm)
this.Visible = false;
base.OnVisibleChanged(e);
}
...
}
Launching an app without a form means you're going to have to manage the application startup/shutdown yourself.
Starting the form off invisible is a better option.
This example supports total invisibility as well as only NotifyIcon in the System tray and no clicks and much more.
More here: http://code.msdn.microsoft.com/TheNotifyIconExample
As a complement to Groky's response (which is actually the best response by far in my perspective) we could also mention the ApplicationContext class, which allows also (as it's shown in the article's sample) the ability to open two (or even more) Forms on application startup, and control the application lifetime with all of them.
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
MainUIForm mainUiForm = new MainUIForm();
mainUiForm.Visible = false;
Application.Run();
}
I had an issue similar to the poster's where the code to hide the form in the form_Load event was firing before the form was completely done loading, making the Hide() method fail (not crashing, just wasn't working as expected).
The other answers are great and work but I've found that in general, the form_Load event often has such issues and what you want to put in there can easily go in the constructor or the form_Shown event.
Anyways, when I moved that same code that checks some things then hides the form when its not needed (a login form when single sign on fails), its worked as expected.
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form1 form1 = new Form1();
form1.Visible = false;
Application.Run();
}
private void ExitToolStripMenuItem_Click(object sender, EventArgs e)
{
this.Close();
Application.Exit();
}
Here is a simple approach:
It's in C# (I don't have VB compiler at the moment)
public Form1()
{
InitializeComponent();
Hide(); // Also Visible = false can be used
}
private void Form1_Load(object sender, EventArgs e)
{
Thread.Sleep(10000);
Show(); // Or visible = true;
}
In the designer, set the form's Visible property to false. Then avoid calling Show() until you need it.
A better paradigm is to not create an instance of the form until you need it.
Based on various suggestions, all I had to do was this:
To hide the form:
Me.Opacity = 0
Me.ShowInTaskbar = false
To show the form:
Me.Opacity = 100
Me.ShowInTaskbar = true
Why do it like that at all?
Why not just start like a console app and show the form when necessary? There's nothing but a few references separating a console app from a forms app.
No need in being greedy and taking the memory needed for the form when you may not even need it.
I do it like this - from my point of view the easiest way:
set the form's 'StartPosition' to 'Manual', and add this to the form's designer:
Private Sub InitializeComponent()
.
.
.
Me.Location=New Point(-2000,-2000)
.
.
.
End Sub
Make sure that the location is set to something beyond or below the screen's dimensions. Later, when you want to show the form, set the Location to something within the screen's dimensions.