I'm creating a System Tray application. Upon initializing the app, I want to:
Initialize and load a form so it runs in the background
But keep the form hidden (until the user doubleclicks the tray icon)
It is important that the form is loaded and runs in the background, because the form contains an embedded browser that will initialize a web socket connection to receive data. But it needs to be hidden. I tried solving this by playing with the Visible property of the form. So far, I have this (only relevant code shown):
public TrayApp()
{
var ni = new NotifyIcon();
InitializeForm();
ni.DoubleClick += this.ShowForm;
}
private void InitializeForm()
{
//load the form in the background so it can start receiving incoming data, but don't actually show the form
myForm = new MyForm();
myForm.Show();
myForm.Visible = false;
}
private void ShowForm(object sender, EventArgs e)
{
myForm.Visible = true;
}
This works quite well, except for one small detail: upon starting the app, I briefly see the form flashing before it is hidden. I suppose the Show method also sets the Visible flag to true, causing the flash to occur.
Other things I tried, based on comments:
Do not call myForm.Show(), only initialize the form. This avoids the flash but won't load the browser and hence the websocket connection is not initialized
Do myForm.Hide(): same effect as previous
Set Opacity to 0 before calling Show() and set it to 1 after setting Visible to false: this actually works, but I was hoping for a cleaner solution
How to avoid the flash and keep the form running but hidden?
You could try to set the hide property before you show your form.
myForm = new MyForm();
myForm.Visible = false;
myForm.Show();
You could try to write a function that initializes the socket. Put this function inside your MyForm class and call it from inside the InitializeForm().
Hope this helps.
Related
Hello I'm making my first Windows Forms app in C# using Visual Studio and I have a little problem.
While I'm opening a new form and closing the previous one, when I run the app it looks like it's closing the previous form before it opens a new one.
It doesn't look good and I want to avoid it.
UserPanel MDIUserPanel = new UserPanel(Username);
MDIUserPanel.MdiParent = this.MdiParent;
MDIUserPanel.Show();
this.Close();
I don't know what is going wrong. I will be thankful for any help.
Wirth regards,
DarQScreaM
#Edit
This doesn't seem to be the case actually. Propably its that :
I have 3 forms MainForm, Login, LoggedUser.
MainForm is MDI container with FormBorderStyle set on Fixed Single
Login is child of MainForm with FormBorderStyle set on None
LoggedUser is child of MainForm with FormBorderStyle set on None
When application is runned Login form is created in MainForm. MainForm is never closed since its container.
But when i move from Login form to LoggedUser form and vice-versa its created with FormBorderStyle = Fixed Single (normal windows window) and after 0.5~second its changed into None.
Editing it into that didn't really help :
MDIUserPanel.FormBorderStyle = FormBorderStyle.None;
MDIUserPanel.Show();
#Edit2
This change fixed it for me. I don't know why setting it on Form properties didn't work properly. It looked like form was created as FormBorderStyle.FixedSingle and then it was changed into FormBorderStyle.None. If I made this manually in Load it worked but U had to fix the size of my window too. It doesn't seem to be good though. It should work from the beginning since Form properties in Designer are like that from the very beginning.
private void UserPanel_Load(object sender, EventArgs e)
{
this.FormBorderStyle = FormBorderStyle.None;
this.Size = new Size(649, 357);
}
You can use the form's Shown event to ensure that the new form have been showed before you close the old one.
UserPanel MDIUserPanel = new UserPanel();
MDIUserPanel.Shown += ((s, ee) =>
{
this.Close();
});
MDIUserPanel.Show();
If this form you are trying to close, is the main form that opens when you run your application, then that's the reason. Closing the main form will exit your application. Try instead to just hide this form instead of closing it. And to make sure you can exit your application ('cause you've hidden your main form), just override the closing event of your current form, and put an "Application.Exit()" in it.
Hope this helps you !
First Step:
this.Hide();
Second Step:
MDIUserPanel.Show();
I want to access variables of a form from another form. On clicking a button inside my Main form, I want to set my Main form as Parent, then bring up another form (child form) wherein I will access variables of the Main form. My click handler is as follow:
private void btnSystem_Click(object sender, EventArgs e)
{
Form_EnterPassword EP = new Form_EnterPassword();
EP.Parent = this; //error: Top-level control cannot be added to a control
EP.ShowDialog();
}
It compiles fine without any error. However, when I run the Main form and click on the System button, it throws me an exception. I do something similar in another code (not mine) with the same button click, and encounter no error (just with setting Main form as Parent).
What am I doing wrong? Is there something in my Main code that cause this?
Best way would be to use EP.ShowDialog(this) and later use Owner property.
You need the EP.TopLevel property to be set to false. It will let you to set a parent to it.
Further reading.
In case you only want to access variables and controls of another form, then maybe you can reach it in other ways, not trough a Parent relationship.
OK,
apparently the way to do it is to call
Form_Child.ShowDialog(this)
and then I can call
FromParent_aVariable = ((Form_Parent)this.Owner).aVariable;
or if I define aVariable in the namespace Properties then
FromParent_aVariable = NameSpace.Properties.Settings.Default.aVariable;
there are two ways.
Form_EnterPassword EP = new Form_EnterPassword();
EP.MdiParent = this;
EP.Show();
try this way, it helps for me. you need to set principalform as isMdicontainer = true at the form properties
I had a similar situation recently.
I was attempting something similar but by controlling the Child Forms from a different class.
Note(s):
You're trying to set the Child Form(s) "TopMost" to something that does not allow it.
In this case the "MdiContainer".
To accomplish this:
• Disable MainForm "isMdiContainer" property (its use is kind of obsolete anyway).
• Set the Form(s) TopMost properties to true.
• You should now be able to accomplish your feature.
**Code Example:**
/* On your Main Form Class */
private void btnSystem_Click(object sender, EventArgs e)
{
// Instantiate the Form_EnterPassword by passing the MainForm
Form_EnterPassword EP = new Form_EnterPassword(this);
EP.Show(); // No longer as modal Form to display in front.
}
/* Under your EnterPassword Form Class */
// Do not create a new Instance of MyMainForm.
// You want to use the same thread as your MainForm
private MyMainForm mainForm;
/* Constructor */
public Form_EnterPassword(MyMainForm form)
{
mainForm = form;
this.Owner = mainForm; // "this" refers to the: EnterPassword Form.
}
Remarks:
The only additional thing that you (may) have to do, (to achieve perfection) is to check the MainForm > WindowState; and create a code block to minimize or bring the Forms to their specific state.
i.e:
if (WindowState == FormWindowState.Minimized)
{ /* Code to Minimize all the Child Forms. */ }
else { /* Code to bring all Forms to their "Normal" State */ }
Writing this way, made the dialog display on the center of the parent form.
Form_Child.StartPosition = FormStartPosition.CenterParent;
Form_Child.ShowDialog(this);
I'm maintaining a C# .net program that uses Castle Windsor as a framework. It also uses Skincrafter to decorate the forms.
In it we have functionality that detects the presence of a file on a USB device and produces another form to deal with it. The software checks for the file either when a USB Event is raised by Windows or when the user presses a button that forces a recheck.
When the user forces a recheck, if the file is found the form appears on top of the main form and is decorated by Skincrafter. If a USB event is raised then the form is produced, but doesn't appear on top (Have to click on it in the task bar to see it) and is not decorated by Skincrafter.
Both methods for detecting the file reach the same function which tells another part of the program to produce the form to deal with the file. The only difference I have found when debugging is that the force recheck method uses the Main Thread whilst the USB Event method has it's own child thread that goes through to the form being shown.
Is it the seperate thread that's causing Windows not to produce the form on top (And presumably be ignored by Skincrafter) or is there likely some other issue?
I can post code if required, but the code paths are identical other than the method calling the file check and the data is identical.
Edit - Code:
This is a simple reconstruction that I produced. New WinForms project with System.Management added to references. Just make a form (FormStartPosition set to CenterScreen) with a button and use this code:
public partial class Form1 : Form
{
private ManagementEventWatcher _eventWatcher = null;
int devices = 0;
public Form1()
{
InitializeComponent();
WqlEventQuery q = new WqlEventQuery();
q.EventClassName = "__InstanceOperationEvent";
q.WithinInterval = new TimeSpan(0, 0, 3);
q.Condition = #"TargetInstance ISA 'Win32_USBControllerDevice' ";
_eventWatcher = new ManagementEventWatcher(q);
_eventWatcher.EventArrived += new EventArrivedEventHandler(UsbEventArrived);
_eventWatcher.Start(); // Start listen for events
}
private void UsbEventArrived(object sender, EventArrivedEventArgs e)
{
if(System.Environment.GetLogicalDrives().Length - devices != 0) {
ShowThingy();
devices = System.Environment.GetLogicalDrives().Length;
}
}
private void button1_Click(object sender, EventArgs e)
{
ShowThingy();
}
private void ShowThingy()
{
Form form2 = new Form();
form2.Size = new Size(50, 50);
form2.StartPosition = FormStartPosition.CenterParent;
form2.TopMost = true;
form2.ShowDialog();
}
}
Run and insert a USB Device and the form2 Form should appear behind the main form.
This doesn't seem to recreate the problem each time. But the first time I plug a USB device always seems to create the second form behind the first. Clicking the button produces the second form on top every time.
I should note that I'm running Windows 7.
You're not setting the owner for the modal window, and the default is the active window (which may not be your main window).
What happens if you use the overload of ShowDialog that takes an owner?
form2.ShowDialog(this);
If that doesn't work, it smells strongly of a threading issue. Can you try changing your USB event handler to use Invoke on the form?
I would like to display a form in the middle of a console application to display some status information and automatically close the form when a particular event occurs. Will the following code portion will be enough for this purpose?
Display the form
ModuleInitializerForm moduleInitializerDlg = new ModuleInitializerForm()
{
Parent = parent,
TopMost = true,
TopLevel = true,
Text = Common.MESSAGE_INFO_TITLE,
ControlBox = false,
FormBorderStyle = FormBorderStyle.FixedDialog,
KeyPreview = false,
};
moduleInitializerDlg.Initialize();
moduleInitializerDlg.ShowDialog();
Close the form
public void OnModuleInitializationCompleted(object sender, EventArgs e)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new ECEventsHandler(OnModuleInitializationCompleted), sender, e);
}
else
{
this.Close();
}
}
Since you are using ShowDialog(), the thread where this is done will be blocked until the user (or you) close the form.
Note that if you used Show() instead, the thread will continue. However, if you have no-one pumping windows messages on that thread, the form will be "dead", i.e. it won't respond to anything. If you start with a normal console app project, then this will be the case. If you use ShowDialog(), it creates a local message loop so the window responds.
So you will need have a separate thread for the Windows Forms UI where you show the form. I would use Application.Run(moduleInitializerDlg); instead of ShowDialog(), since it better sets up/tears down the message pumping architecture as far as I can tell. That call will block the thread in the same way as ShowDialog() by the way.
go to the properties of the form wich should open on click...
go to the Layout section and put Start position to Centerscreen or if u have a parent in wich u want to dock it each time, use CenterParent...
enjoy!
Does anyone know how can I know if the Windows Form Application (C#) is open or that the client closed it?
(In my App I have a Windows Form Application (Form1) that allow the user to open another Forms (Form2). I want to know if the Form2 is open or close.)
I need to know that because I run the Form2 from a thread, and I want to make the thread runnig until the user close Form2.
Many thanks!
You can check if a form of a given type is open in your application like this (using LINQ):
if (Application.OpenForms.OfType<Form2>().Count() > 0)
{
// there is an instance of Form2 loaded
}
You need to elaborate on your question a bit more. Are you talking about monitoring the application from another application? Or that one form needs to know if another one is open? Or a form needs to know when another form closes?
There are a couple of ways to monitor forms closing within the same application.
Calling ShowDialog() on your form instead of Show() will ensure that code following the ShowDialog() call doesn't get executed until the user closes the form.
The Form class has a Visible property, which returns true/false depending on whether the form is visible or not.
As for the application itself, there is an ApplicationExit event on the static Application class which gets called just before the application closes so you could listen to that event if, for example, you need to perform some clean-up on exit.
If you want to run only single instance of application, check this link.
There you will also see how to check whether a process is still active.
If you mean MDI application with its child forms:
private Dictionary<Type, Form> SingleInstanceForms = new Dictionary<Type, Form>();
public Form ActivateForm<T>() where T : Form, new()
{
Cursor.Current = Cursors.WaitCursor;
if (!this.SingleInstanceForms.ContainsKey(typeof(T)))
{
T newForm = new T();
//setup child
newForm.MdiParent = this;
newForm.WindowState = FormWindowState.Maximized;
//newForm.Icon = Icon;
newForm.FormClosed += new FormClosedEventHandler(delegate(object sender, FormClosedEventArgs e)
{
this.SingleInstanceForms.Remove(sender.GetType());
});
this.SingleInstanceForms.Add(typeof(T), newForm);
newForm.Show();
this.Refresh();
}
Form formToActivate = this.SingleInstanceForms[typeof(T)];
formToActivate.Activate();
Cursor.Current = Cursors.Default;
return formToActivate;
}
this will create the form child if hasn't been created yet and activate it if it has been created.
sample: ActivateForm<dlgChildOne>();