I have a login form. The form has 2 textboxes, and 3 buttons. one button says "Students."
What I want to do is to show a tooltip on this button when the form opens. I dont want to have to go to the button and hover on it in order for it to display. I want the form to load, show the tooltip, and then the tooltip should disappear after 5 seconds. this is what I have tried so far:
private void Form1_Load(object sender, EventArgs e)
{
toolTip.IsBalloon = true;
toolTip.ToolTipIcon = ToolTipIcon.Info;
toolTip.ShowAlways = true;
toolTip.UseFading = true;
toolTip.UseAnimation = true;
toolTip.ToolTipTitle = "Student Mode";
toolTip.Show("You don't have to log in if you are a student. Just click here to go to the questions.", btnStudent);
}
The form's Load event is mis-used far too often. It is here, the event fires before the window becomes visible. Your tooltip is therefore not visible either.
Move your code to a Shown event handler instead. Do favor overriding OnShown() btw, it doesn't make sense for a class to listen to its own events.
protected override void OnShown(EventArgs e) {
base.OnShown(e);
// Your code here
//...
}
Related
I am working on a WinForms Desktop application in C# .NET. The target framework is .NET Framework 4.8. When the application is started, the main form is displayed with several buttons. Each button hides the main form when clicked and opens another form that displays data with which the user interacts. The main form is the owner of the new form.One button opens a form that presents a list of files from a network share folder in a data grid view. The user selects a row in the data grid and clicks a button to import the information in the file to various tables in a SQL Server database. When the import is complete, the selected row is removed from the data grid. When the user closes this form, there is code in the Form Closed event to show the owner. This all works well.My problem is that when the main form is unhidden, I need to disable the button that opens the form to list files to import if there are not any files in the network share folder to be imported. There is also a line of code to change the button's text property informing the user there are not any files to import.I realize I can place the code to disable the button and change button text in the VisibleChanged event. But, I only want the code to run after the owned form's closed event shows the owner form. How do I enclose the code in the main form's VisibleChanged event to disable the file import button only after the owned form is closed. Or, is it possible to edit the properties of the button on the owner form in the Form Closed event prior to the Owner.Show();I found a similar question WinForm Form Closed Event. But when I follow the suggestion
private void LoadChildForm_Click(object sender, EventArgs e)
{
ChildForm form = new ChildForm();
form.FormClosed += new FormClosedEventHandler(ChildFormClosed);
form.Show();
}
substituting my names
private void btnImportHFR_Click(object sender, EventArgs e)
{
Form form = new frmHFRFiles();
form.FormClosed += new FormClosedEventHandler(frmHFRFiles_FormClosed);
form.Show(this);
Hide();
}
Visual Studio flags frmHFRFiles_FormClosed as an error for the name does not exist in the current context.
ChildForm form = new ChildForm(this);
Then in ChildForm constructor:
MainForm m_MainForm;
Public ChildForm (MainForm mainForm)
{
m_MainForm = mainForm;
}
Then in closing event:
m_MainForm.button1.Enabled = false;
Ensure button1 is public
Here is what I did. I created a boolean variable in the main form and set the initial value to false.
private bool updateButtons = false;
The main form's constructor executes the search for files in the network folder.
public frmMainMenu()
{
InitializeComponent();
Shared.FilesForImport = GetHFRFiles();
}
The form's load event calls the EnableButtons() method
public void EnableButtons()
{
btnImportHFR.Enabled = Convert.ToBoolean(Shared.FilesForImport.Count);
btnImportHFR.Text = btnImportHFR.Enabled ? "Find Available HFR" : "No HFR For Import";
btnGetFacilityStatus.Enabled = Shared.sqlWrap.GetDataForFacStat(Shared.DsFacStat);
updateButtons = false;
}
The main form's visible changed event fires after the form load event. The network folder is not searched again because the updateButtons value is set to false.
private void frmMainMenu_VisibleChanged(object sender, EventArgs e)
{
if(updateButtons)
{
EnableButtons();
}
}
In the button click event, the updateButtons value is set to true after the main form is hidden.
private void btnImportHFR_Click(object sender, EventArgs e)
{
frmHFRFiles form = new frmHFRFiles();
form.Show(this);
Hide();
updateButtons = true;
}
The child form's closed event calls the Owner.Show() method
private void frmHFRFiles_FormClosed(object sender, FormClosedEventArgs e)
{
Owner.Show();
}
This causes the main form's visible changed event to fire. Only this time the EnableButtons() method will run because the updateButtons value is true.
private void frmMainMenu_VisibleChanged(object sender, EventArgs e)
{
if(updateButtons)
{
EnableButtons();
}
}
public void EnableButtons()
{
btnImportHFR.Enabled = Convert.ToBoolean(Shared.FilesForImport.Count);
btnImportHFR.Text = btnImportHFR.Enabled ? "Find Available HFR" : "No HFR For Import";
btnGetFacilityStatus.Enabled = Shared.sqlWrap.GetDataForFacStat(Shared.DsFacStat);
updateButtons = false;
}
Finally, the EnableButtons() method sets the updateButtons value to false.
It seems rudimentary to me, but it works. Thank you everyone for your feedback.
My problem is that when the main form is unhidden, I need to disable the button that opens the form to list files to import if there are not any files in the network share folder to be imported. There is also a line of code to change the button's text property informing the user there are not any files to import.
So your main form has a button X. If this button is clicked a method is called. This method will first hide the form, then show the subform until the subform is closed. The method should disable button X, change the button's text and unhide the form.
To make this flexible, we won't do everything in one procedure, we make several procedures with the intention of the procedure: "Inform operator there are no files to import" "Disable opening the subform", and of course their counterparts "Enable opening the subform", "Inform operator there are files to import"
TODO: invent proper method names
private void ShowNoFilesToImport()
{
this.buttonX.Text = ...;
}
private void DisableOpeningSubForm()
{
this.buttonX.Text.Enabled = false;
}
The advantage of this, is that if you later want to change the way that you want to inform the operator, for instance if you want to use an information field at the bottom of you screen, you will only have to change this in one place.
Furthermore, you can reuse the procedures, for instance you can add a menu item that will do the same as button X, this menu item can call the same methods
private void PerformActionsButtonX() // TODO: invent proper name
{
// Hide this form, and show the Subform until it is closed
this.Visible = false;
using (var dlg = new SubForm())
{
// if needed, set properties of the subForm:
dlg.Text = ...
dlg.Position = ...
// show the form until it is closed
var dlgResult = dlg.ShowDialog();
this.ProcessDlgResult(dlgResult, dlg);
}
// Show that there are no files to Import and disable OpeningSubform
this.ShowNoFilesToImport();
this.DisableOpeningSubform();
// Finally: show this form:
this.Visible = true;
}
And of course call this method when ButtonX or menu item Y are clicked:
private void OnButtonX_Clicked(object sender, ...)
{
this.PerformActionsButtonX();
}
private void OnMenyItemYClicked(object sender, ...)
{
this.PerformActionsButtonX();
}
I checked and found this article that is referred to MANY times in this type of question, and it is NOT the answer I want...
I have a form, Form_Main frmMainPage, it creates Form_Status frmStatus.
When it does so, I disable the controls on frmMainPage so the user can't mess with things while things are processing.
When things are done processing they can close the frmStatus window to go back to frmMainPage to continue working. I cannot re-enable the controls from frmStatus. I tried to use the frmMainPage_Enter, but it goes crazy when it first loads, so that isn't really an option.
I have the following in Form_Main.cs
public void EnableForm() {
this.gridData.Enabled = true;
this.txtLocation.Enabled = true;
this.txtSupplier.Enabled = true;
this.txtItem.Enabled = true;
this.FillTable("", "", "");
}
When I use this (per article above):
private void btnClose_Click(object sender, EventArgs e) {
Form_Main f2 = new Form_Main();
f2.Show();
f2.EnableForm();
this.Close();
}
It creates a second Form_Main, which is not what I want. I want to know how to change the controls in the existing form.
Edit: No, it is not this that was also suggested. Most of the answers deal with changing controls on Form 2 from Form 1 when Form 2 is created by Form 1. In my case I need to do the opposite and change controls on Form 1 FROM Form 2, which was created by Form 1. Kind of a circular thing.
I can think of a couple of ways to do this. First (and most common) is to show the second form modally (which means that the first form's code pauses while the second form's code is running):
private void button1_Click(object sender, EventArgs e)
{
var statusForm = new frmStatus();
// ShowDialog will prevent frmMainPage from being accessible.
// This form's code will pause at the next line until the second form is closed
statusForm.ShowDialog();
}
There are occasions where you want to have both forms accessible at the same time. If this is the case, another method would be to add an event handler for the second form's FormClosed event, where you can re-enable the controls on the first form. This will allow both forms to be accessed at the same time:
private void button1_Click(object sender, EventArgs e)
{
var statusForm = new frmStatus();
// Add an event handler for the second form's FormClosed event, and
// put code in that event handler to re-enable controls on this form
statusForm.FormClosed += statusForm_FormClosed;
// Disable our controls on this form and show the second form
DisableForm();
statusForm.Show();
}
private void statusForm_FormClosed(object sender, FormClosedEventArgs e)
{
// When the second form closes, re-enable controls on this form
EnableForm();
}
private void DisableForm()
{
this.gridData.Enabled = false;
this.txtLocation.Enabled = false;
this.txtSupplier.Enabled = false;
this.txtItem.Enabled = false;
}
public void EnableForm()
{
this.gridData.Enabled = true;
this.txtLocation.Enabled = true;
this.txtSupplier.Enabled = true;
this.txtItem.Enabled = true;
this.FillTable("", "", "");
}
you dont need to do this disable enable.
you just need to show your new from with ShowDialog(); like this:
frmStatus.ShowDialog();
instead of just:
frmStatus.Show();
To show the relevant information(in monopoly game, the property belongs which player, current market price etc.), I put a Label on the top of a panel, and used a ToolTip object to display the information. This is the image of my current setup.
Here are the steps I have done:
1.Added MouseHover event handler (The Label name is MEDITERANEAN)
this.MEDITERANEAN.MouseHover += new System.EventHandler(this.MEDITERANEAN_MouseHover);
2.Initialized Tooltip
private void InitializeToolTip()
{
toolTipLabel.ToolTipIcon = ToolTipIcon.Info;
toolTipLabel.IsBalloon = true;
toolTipLabel.ShowAlways = true;
}
3.Call setToolTip() in MouseHover call back function
private void MEDITERANEAN_MouseHover(object sender, EventArgs e)
{
toolTipLabel.SetToolTip(MEDITERANEAN, "You put mouse over me");
rolledDice.AppendText("Mouse Over");
}
But when I start application and move my cursor over the label, there is no text from toolTipLabel. What part did I make mistakes?
Interestingly, i made other function and it works.
private void panelBoard_MouseOver(object sender, EventArgs e)
{
toolTipLabel.SetToolTip(panelBoard, "You put mouse over me");
rolledDice.AppendText("Mouse Over");
}
I think you just need to bring your lable control in front of image. Try something like this .
MEDITERANEAN.BringToFront();
I found the solution, first I should set Panel's property "Enable" to true, then set label's property "visible" to true as well.
I am having trouble getting my 'start' button to show when I select either of the radio boxes.
Ideally, when one of the boxes is selected, the 'start' button will enable and allow to be clicked.
Here is my code for the form, as I am relatively new to C# I'm not sure if I'm posting all of the code you need, I'll post more if required.
public partial class mainForm : Form
{
public mainForm() {
InitializeComponent();
}
private void label1_Click(object sender, EventArgs e) {
}
private void mainForm_Load(object sender, EventArgs e) {
title.Font = new Font("Arial", 10, FontStyle.Bold);
}
private void startButton_Click(object sender, EventArgs e) {
if (radioDice.Checked) {
startButton.Enabled = true; //Activates 'start' button
whichDiceGameForm GameForm = new whichDiceGameForm();
GameForm.Show();
}
if (radioCard.Checked) {
startButton.Enabled = true; //Activates 'start' button
whichCardGame GameForm = new whichCardGame();
GameForm.Show();
}
}
}
[Posting for a friend.]
You have placed your enable code in the Button's Click event Handler while you should do it on your checkboxes changed.
Take this code :
if (radioDice.Checked)
{
startButton.Enabled = true;
}
to radioDice checkbox's changed event handler and this one :
if (radioCard.Checked)
{
startButton.Enabled = true; //Activates 'start' button
}
to radioCard checkbox's changed event handler .
Man, seriously?
ANSWER:
You're trying to enable DISABLED button when clicking on that button. You cannot click DISABLED button. What's more - you're duplicating your code.
Button should be always enabled. You only have two choices. Every choice enabled button. So it should be always enabled. No matter the choice. If there is something hidden and button may be disabled, then enable the button in Radio Click event.
Additional information about your code:
Now. About code duplication. Look what you're doing in startButton_Click. You have duplicated code.
You can do something like:
BaseGameForm f = null;
if(radioDice.Checked)
f = new DiceGameForm();
else
if(radioCard.Checked)
f = new CardGameForm();
f.Show();
(BaseGameForm is base form for every game)
But this is not good solution. Better solution is (somewhere in construtor):
radioDice.Tag = new DiceGameForm();
radioCard.Tag = new CardGameForm();
Then in Start button click you look for checked radio:
foreach(Control c in selectGameTypeGroupBox.Controls) //you could do this using LINQ
{
if((c is RadioButton) && ((RadioButton)c).Checked)
{
((Form)c.Tag).Show();
}
}
But this is still not good solution, because you're creating all game forms at startup and this is stupid.
So the better solution would be to keep game form class name in your radio Tag property and then create object of this class using reflection and Activator.
But this is still not the best solution. But I assume that this is one of your first applications so I won't be telling you now about separating gui from logic. If you want to know more - read on the Internet. Or just ask.
I have Windows Form TestForm, and in my Form I have several labels that are only used to display some text.
I need to display a MessageBox.Show anytime the Form is clicked. So I have an event handler for the click, which looks like this:
private void TestForm_Click(object sender, EventArgs e)
{
MessageBox.Show("The form has been clicked");
}
Unfortunately, the click event doesn't fire when I click over a label in the Form. Is there a way to fix this, besides consuming the click event for the labels?
Thanks.
To use the same click event for all labels:
In the properties for each label, go to the Events (lightning bolt tab).
You will see (probably near the top) a label for Click, click the dropdown for this event, and you will be shown a list of handlers that you could use for that label.
Here's the Properties > Events > Click handler (bottom right):
Because all of your labels are of the same type, and produce the same EventArgs, you are able to use the same handler for all of them.
Then, when you are adding more Labels, just choose the event handler from the Click event dropdown:
Hope this helps!
To flesh out LarsTech's comment, I have used something like this in the past when I was having problems with labels overlapping each other and lack of true transparency in WinForms. What I did was make the labels invisible on the Form, then iterate through them in the Form's paint event, pull the information out of them and then use Graphics.DrawString to draw the text. That way you you will still be able see them in design mode.
This is a quick example of what I mean.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
foreach (var temp in this.Controls)
{
if (temp is Label) //Verify that control is a label
{
Label lbl =(Label)temp;
e.Graphics.DrawString(lbl.Text, lbl.Font, new SolidBrush(lbl.ForeColor), new Rectangle(lbl.Location, lbl.Size));
}
}
}
private void Form1_Click(object sender, EventArgs e)
{
MessageBox.Show("The Form has been clicked");
}
}