I have created a simple C# application to automatically login into a hotspot. I have a notify icon with a contextmenustrip with some functions like Connect, Disconnect, etc. I want to be able to run the form in the background showing only the notify icon to automatically login into the hotspot if the form is hidden.
I followed the instructions from VBNight in this post:
Hide form at launch
The application is running in the background, the notify icon showing but the Form_Load function is not working until I press on the notify icon.
I guess that's because Form_Load Occurs before a form is DISPLAYED for the first time.
Try moving your code from Form_Load to the constructor after InitializeComponent(); or so.
EDIT:
To answer your question, I suggest you extract code #1 from...
private void YOUR_BUTTON_Click(object sender, EventArgs e) {
// move this code #1 to...
}
and move the code to a brandnew method.
private void NewButtonClicked() {
// move code #1 here (in case)
}
Then, go back and call the method you just created.
private void YOUR_BUTTON_Click(object sender, EventArgs e) {
// You can leave code #1 but to remove duplicate,
NewButtonClicked();
}
Finally, replace YOUR_BUTTON.PerformClick(); with NewButtonClicked(); wherever you need. I assume you don't need any interaction with form Controls since the form is hidden.
I fixed it changing the form opacity to 0 and the ShowInTaskbar property to false. The form is hidden and the code is working.
Related
I tried opening a second form using a button on my main form, but when I close the second window, I can't open it again.
I added the following code to my main form:
settings_window secondForm = new settings_window();
private void settings_button_Click(object sender, EventArgs e)
{
secondForm.Show();
}
But when I try to open the second form named settings_window the second time, I get the following error: System.ObjectDisposedException.
I found the following code to fix this but I don't know where to place it:
private void settings_window_FormClosing(object sender, FormClosingEventArgs e)
{
this.Hide();
e.Cancel = true; // Do not close the form.
}
You can avoid storing references of Forms and use a simple generic method that shows a Form when an instance of it already exists or creates a new one (and shows it) when none has been created before:
private void ShowForm<T>() where T : Form, new()
{
T? f = Application.OpenForms.OfType<T>().SingleOrDefault();
if (f is null) {
f = new T();
f.FormClosing += F_FormClosing;
}
f.Show();
BeginInvoke(new Action(()=> f.WindowState = FormWindowState.Normal));
void F_FormClosing(object? sender, FormClosingEventArgs e)
{
e.Cancel = true;
(sender as Form)?.Hide();
}
}
When you need it, call as ShowForm<SomeFormClass>(), e.g.,
ShowForm<settings_window>()
Note:
This code uses a local method to subscribe to the FormClosing event.
You can use a standard method, in case this syntax is not available.
BeginInvoke() is used to defer the FormWindowState.Normal assignment. This is used only in the case you minimize a Form, then right-click on its icon in the TaskBar and select Close Windows from the Menu. Without deferring this assignment, the minimized Form wouldn't show up again.
When the starting Form closes, all other Forms close as well
This code supposes nullable is enabled (e.g., see object? sender). If nullable is disabled or you're targeting .NET Framework, remove it (e.g., change in object sender)
Is secondForm a private field of the main form class?
It should work then.
Alternative solution is to show it as as modal - ShowDialog()
Also if you want to save some data in your second form, just use some data initialization from constructor, then saving to first/parent form.
I think you need to create a new instance of the form each time you want to open it. It will create a new instance of the settings_window form each time the button is clicked.
private void settings_button_Click(object sender, EventArgs e)
{
// Create a new instance of the form
settings_window secondForm = new settings_window();
secondForm.Show();
}
Your code shows a class that you have named settings_window, which gives us a hint about what its intended use might be. In general, for a form that behaves "like" a settings window, that you can call multiple times using the same instance, you can declare a member variable using this pattern:
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
// Provide some means, like a menu or button, to show 'secondForm'
settingsMenu.Click += onClickSettingsMenu;
// Dispose the settings_form when the MainForm does.
Disposed += (sender, e) => secondForm.Dispose();
}
// By instantiating it here, its public default or persisted
// properties are immediately available, for example even
// while the main form constructs and loads the initial view.
settings_window secondForm = new settings_window();
private void onClickSettingsMenu(object? sender, EventArgs e)
{
if(DialogResult.OK.Equals(secondForm.ShowDialog()))
{
// Apply actions using the properties of secondForm
}
}
}
This is suitable for any form when you want to:
Repeatedly show and hide the form (e.g. a "Settings" form where the user can change the options multiple times).
Retrieve the default or the persisted properties of the form from the outset even if it's never been shown.
Use any of the form's public properties (e.g. GameLevel, SortType etc.) at any given moment while the app is running, even if the form isn't currently visible.
Display the form modally meaning that "no input (keyboard or mouse click) can occur except to objects on the modal form".
The reason it works is that calling ShowDialog (unlike calling Show) intentionally does not dispose the window handle, and this is to support of this very kind of scenario. The app is then responsible for disposing the resource when the app closes.
The Microsoft documentation for ShowDialog explains how this works.
Unlike non-modal forms, the Close method is not called by the .NET Framework when the user clicks the close form button of a dialog box or sets the value of the DialogResult property. Instead the form is hidden and can be shown again without creating a new instance of the dialog box. Because a form displayed as a dialog box is hidden instead of closed, you must call the Dispose method of the form when the form is no longer needed by your application.
I'm having a Windows Mobile CE application written in C# with .Net CF.
Consider i have 2 forms in my application:
List of objects (has a listview)
Details page (should appear when something is selected in previous listview)
Currently i'm attaching callback to listview's SelectedIndexChanged event, and open a new form there.
New form opens okay (in the midde of the event callback), but when i close the form(this.Close()), then the list page isn't clickable first time, after the first click UI is interactable again.
Also the the ListViewItem clicked at first step doesn't get selected(blue background).
Here's a short (12s) video showing this problem: http://take.ms/urkme
As you see from the video, after coming back from details screen, refresh button doesn't click on the first click..
I'm showing the details form like so:
private void listView_SelectedIndexChanged(object sender, EventArgs e)
{
(new FormDetails()).ShowDialog();
}
Is there any way to show the details form after event finishes, or am i doing it completely wrong?
PS! Tried the same with a Button and it's click event, then all worked nicely..
As I know ListView's SelectedIndexChanged event fired twice on almost case not like Button's Click event which fired once, this maybe what cause that weird interaction. Maybe try changing to ItemSelectionChanged event as suggested in here.
Your problem is caused by using the SelectedIndexChanged event. When you select an item in your list you'll set the SelectedIndex, if you select the same item again the index won't be changed so you'll never call the event.
You could use the Click event to trigger the wanted response.
Here is an example:
private void listView1_Click(object sender, EventArgs e)
{
var firstSelectedItem = listView1.SelectedItems[0]; //This is your selected item.
//do stuff
}
When you use ShowDialog() you open a form in modal mode. All further processing of following code will not take place until the modal form is closed or returns a DialogResult.
Better use a modeless form using .Show().
private void listView_SelectedIndexChanged(object sender, EventArgs e)
{
(new FormDetails()).Show(); //will not stop processing of events in mainForm
}
If the new FormDetails is finished, it can use a simple Hide or Close to bring up the main form to foreground.
Remember that the main form is still there and will not wait for the FormDetails being closed (as it is a modeless dialog).
I created a UserControl with the buttons Save, Close and Cancel. I want to close the form without saving on the Cancel button, prompt a message to save on the Close button and Save without closing on the Save button. Normally, I would have used this.Close() on the Cancel button, but the UserControl doesn't have such an option. So I guess I have to set a property for that.
Scrolling down the "Questions that may already have your answer" section, I came across this question: How to close a ChildWindow from an UserControl button loaded inside it? I used the following C# code:
private void btnCancel_Click(object sender, EventArgs e)
{
ProjectInfo infoScreen = (ProjectInfo)this.Parent;
infoScreen.Close();
}
This does the job for one screen, but I wonder if I have to apply this code for all the screen I have? I think there should be a more efficient way. So my question is: Do I need to apply this code for every form I have, or is there another (more efficient) way?
you can use
((Form)this.TopLevelControl).Close();
you can use the FindForm method available for any control:
private void btnCancel_Click(object sender, EventArgs e)
{
Form tmp = this.FindForm();
tmp.Close();
tmp.Dispose();
}
Do not forget to Dispose the form to release resources.
Hope this helps.
You also can close one form in any part of the code using a remote thread:
MyNamespace.MyForm FormThread = (MyNamespace.MyForm)Application.OpenForms["MyForm"];
FormThread.Close();
I found the simple answer :) I all ready thought of something like that.
To close a WinForm in a ButtonClicked Event inside a UserControl use the following code:
private void btnCancel_Click(object sender, EventArgs e)
{
Form someForm = (Form)this.Parent;
someForm.Close();
}
I'm using c# to make a mobile 6 application. I created another windows form in the project. This is the form that I would like to load first. This is what have tried:
MainMenu gameMenu = new MainMenu();
private void MainForm_Load(object sender, EventArgs e)
{
this.Hide();
gameMenu.ShowDialog();
.....
}
When I run this the emulator comes up but it just stays as the default windows screen. And I don't get any of my forms.
GameMenu's parent is MainForm, which is now hidden, so the Dialog isn't going to be visible. You need to adjust your logic to do one of the following:
show the GameMenu first (i.e. Application.Run(new GameMenu))
Don't hide MainForm
Use gameMenu.Show() instead of ShowDialog()
You may need to get rid of this.Hide() or use gameMenu.Show() instead of gameMenu.ShowDialog() or you may need to do both.
If you have to use gameMenu.Show() instead of gameMenu.ShowDialog(), you may also want to do the following:
Subscribe to MainForm's GotFocus event and call gameMenu.Show() again whenever the other form gains focus unintentionally. Set MainForm's Enabled property to false while the gameMenu is shown if you want to prevent any accidental interaction with the MainForm while the gameMenu is supposed to be shown.
I have a problem with modality of the forms under C#.NET. Let's say I have main form #0 (see the image below). This form represents main application form, where user can perform various operations. However, from time to time, there is a need to open additional non-modal form to perform additional main application functionality supporting tasks. Let's say this is form #1 in the image. On this #1 form there might be opened few additional modal forms on top of each other (#2 form in the image), and at the end, there is a progress dialog showing a long operation progress and status, which might take from few minutes up to few hours. The problem is that the main form #0 is not responsive until you close all modal forms (#2 in the image). I need that the main form #0 would be operational in this situation. However, if you open a non-modal form in form #2, you can operate with both modal #2 form and newly created non modal form. I need the same behavior between the main form #0 and form #1 with all its child forms. Is it possible? Or am I doing something wrong? Maybe there is some kind of workaround, I really would not like to change all ShowDialog calls to Show...
Image http://img225.imageshack.us/img225/1075/modalnonmodalproblem.png
Modal forms do exactly what "modal" means, they disable all other windows in the app. That's rather important, your program is in a somewhat perilous state. You've got a chunk of code that is waiting for the dialog to close. Really Bad Things could happen if those other windows were not disabled. Like the user could start the modal dialog again, now your code is nested twice. Or she could close the owner window of the dialog, now it suddenly disappears.
These are the exact kind of problems you'd run into if you call Application.DoEvents() inside a loop. Which is one way to get a form to behave modal without disabling other windows. For example:
Form2 mDialog;
private void button1_Click(object sender, EventArgs e) {
mDialog = new Form2();
mDialog.FormClosed += (o, ea) => mDialog = null;
mDialog.Show(this);
while (mDialog != null) Application.DoEvents();
}
This is dangerous.
It is certainly best to use modal forms the way they were designed to stay out of trouble. If you don't want a modal form then simply don't make it modal, use the Show() method. Subscribe to its FormClosing event to know that it is about to close:
private void button1_Click(object sender, EventArgs e) {
var frm = new Form2();
frm.FormClosing += new FormClosingEventHandler(frm_FormClosing);
frm.Show();
}
void frm_FormClosing(object sender, FormClosingEventArgs e) {
var frm = sender as Form2;
// Do something with <frm>
//...
}
The first thing that comes to mind would be something like this. You could disable form 1 when you launch form 2 and then have form 1 handle the closed event of the second form to re-enable itself. You would NOT open modal 2 using show dialog.
Now keep in mind, from a user perspective this is going to be quite cumbersome, you might look at doing a MDI application to get all windows inside of a single container.
Your main form will not be responsive until any modal dialogs that are in the same process space are closed. There is not work around for that.
It looks to me like you could use an MDI application setting the Form #0 IsMdiContainer property to true.
Then, you could do something alike:
public partial class Form0 {
public Form0 {
InitializeComponent();
this.IsMdiContainer = true; // This will allow the Form #0 to be responsive while other forms are opened.
}
private void button1_Click(object sender, EventArgs e) {
Form1 newForm1 = new Form1();
newForm1.Parent = this;
newForm1.Show();
}
}
Using the ShowDialog() as you stated in your question will make all of the forms Modal = true.
By definition, a modal form is:
When a form is displayed modally, no input (keyboard or mouse click) can occur except to objects on the modal form. The program must hide or close a modal form (usually in response to some user action) before input to another form can occur. Forms that are displayed modally are typically used as dialog boxes in an application.
You can use this property [(Modal)] to determine whether a form that you have obtained from a method or property has been displayed modally.
So, a modal form shall be used only when you require immediate assistance/interaction from the user. Using modal forms otherwise makes believe that you're perhaps running into a wrong direction.
If you do not want your main form to be an MDI container, then perhaps using multithreading is one solution through a simple BackgroundWorker class is the key to what you want to achieve. Thus, it looks to me like a design smell...
What is it you want to do, apart of making your main form responsive, etc.
What is it you have to do?
Explaining what you have to do, we might be able to guide you altogether into the right, or at least perhaps better, direction.
Actually the answer is very simple. Try
newForm.showDialog();
This will open a new form, while the parent one is inaccessible.