Create new form by method - c#

public void IsOpen(Form f)
{
bool open = false;
FormCollection fc = Application.OpenForms;
foreach (Form form in fc)
{
if (form == f)
{
if (form.WindowState == FormWindowState.Minimized)
{
form.WindowState = FormWindowState.Normal;
}
form.BringToFront();
open = true;
}
}
if (open == false)
{
f = new Form();
f.Show();
}
}
So i've got this bit of code here. It's meant to check the open forms in the application and determine if a form is already open. Now i'm using this because there's a couple of forms I don't want opened twice at the same time. My issue being is that I can't open the type of form that i want. I want to get the formtype of F and open the form of that specific type. Ex:
private void mnuSettings_Click(object sender, EventArgs e)
{
Settings set = new Settings();
IsOpen(set);
}
So i pass the form here, so f should equal the settings form. But I need the method to dynamically open different forms. So say I use Form1 instead of settings, I need to open an instance of Form1 if it's not open. Any help is greatly appreciated.

public Dictionary<Type, Form> forms = new Dictionary<Type, Form>();
public void OpenSingletonForm<T>() where T : Form, new() {
if (!forms.ContainsKey(typeof(T)) {
forms.Add(typeof(T), new T());
}
forms[typeof(T)].Show();
}
And use it like so:
OpenSingletonForm<SettingsDialog>();

Related

How can I find the form name of the previous form?

I have a dialogue window (just a form) class which can be called by several forms. I want the title of this dialogue to change dependent on which form called it.
Is there a way, within the dialogue class, of finding out the form name of the form which called it (without altering the code of the several forms which can call it)?
I have tried it just with a simple example, but using GetWindowLongPtr you can get the parent form of your dialog.
First of all you have to add this definitions in your dialog:
[DllImport("user32.dll", EntryPoint = "GetWindowLong")]
static extern IntPtr GetWindowLongPtr(IntPtr hWnd, GWL nIndex);
public enum GWL
{
GWL_WNDPROC = (-4),
GWL_HINSTANCE = (-6),
GWL_HWNDPARENT = (-8),
GWL_STYLE = (-16),
GWL_EXSTYLE = (-20),
GWL_USERDATA = (-21),
GWL_ID = (-12)
}
And then,in your dialog, you can do this:
private void Form2_Load(object sender, EventArgs e)
{
IntPtr parentHandle = GetWindowLongPtr(this.Handle, GWL.GWL_HWNDPARENT);
FormCollection fc = Application.OpenForms;
foreach (Form frm in fc)
{
if (frm.Handle==parentHandle)
{
Console.WriteLine(frm.Name); //this is your parent form
}
}
}
Anyway, I think it's easier to just call ShowDialog(this), but if you can't really change the calling forms, this method may be handy.
You can try this on the dialogform, make sure you do this before the dialogform becomes active to prevent it from finding itself.
public Form GetActiveForm()
{
Form activeForm = Form.ActiveForm;
if (activeForm.IsMdiContainer && activeForm.ActiveMdiChild != null)
{
activeForm = activeForm.ActiveMdiChild;
}
return activeForm;
}
FormCollection may help you:
FormCollection fc = Application.OpenForms;
foreach (Form frm in fc)
{
MessageBox.Show(frm.Name.ToString());
}
Assuming that You are creating other dialogs(forms) from the main form, You can do:
public partial class MyForm : Form
{
//Some code
public void OpenDialog_Click(...)
{
MyOtherForm form = new MyOtherForm();
form.Parent = this;
form.ShowDialog();
}
}
And Your 2nd form:
public partial class MyOtherForm : Form
{
public MyOtherForm()
{
var parent = this.Parent as Form;
if(parent != null)
this.Title = parent.Title;
}
}

C# win forms create form child using custom method [duplicate]

I want to simplify some of my code. Therefore I want to make a function which checks, if a certain form is already open. Right now I have the code below behind every button on my start-form.
private void button_parts_Click(object sender, EventArgs e)
{
FormCollection fc = Application.OpenForms;
foreach (Form frm in fc)
{
if (frm is frm_parts) { return; }
}
frm_Teile newForm = new frm_parts();
newForm.Show();
}
Now I would like to have something like:
private void button_parts_Click(object sender, EventArgs e)
{
StartNewForm(frm_parts);
}
private void StartNewForm(Type myForm)
{
FormCollection fc = Application.OpenForms;
foreach (Form frm in fc)
{
if (frm is myForm) { return; }
}
myForm newForm = new myForm();
newForm.Show();
}
But I cannot pass a type to a function
EDIT: You certainly can, but I didn't know how and where to start.
Is there a(nother) way to achieve what I need?
You can use either of these options.
Using a generic method:
private void StartNewForm<T>()
where T : Form, new()
{
FormCollection fc = Application.OpenForms;
foreach (Form frm in fc)
{
if (frm is T) { return; }
}
var newForm = new T();
newForm.Show();
}
Here is the usage: StartNewForm<Form1>();
Create your form using Activator.CreateInstance
private void StartNewForm(Type myForm)
{
FormCollection fc = Application.OpenForms;
foreach (Form frm in fc)
{
if (frm.GetType() == myForm) { return; }
}
var newForm = (Form)Activator.CreateInstance(myForm);
newForm.Show();
}
Here is the usage: StartNewForm(typeof(Form1));
Note:
The non-generic version is here just because you thought you can't do it using Type. But you should know the better option is using generic version because it performs type checking at compile time while in the non-generic version you should perform some validations, for example you should check if myForm is of type of Form.
I didn't change your code, but for example you can do it this way:
private void StartNewForm<T>() where T : Form, new()
{
var f = (Application.OpenForms.OfType<T>().FirstOrDefault() ?? new T());
f.Show();
}
Improvements over previous answer:
You should implement some kind of interface and check if the form should or shouldnt be open more than once. Also you can set more properties if needed. IOnlyOnceForm or something like that.
Consider having a base class for all of the forms you want to control. This way you can, for example, just .Show() them and continue the method or abort it and pop up the current open instance of that type. MySuperDuperAppFormBase (you are free to choose a better name!)
Also check with Application.OpenForms.OfType instead of the forearch.

how to prevent my program to open the same window Form twice

i am working on a project, i am creating a instance and opening a specific form in my program, like i use following code to open a form:
frm2 cs = new frm2();
cs.Show();
but the problem here is each time i click on the button it just open a new windows and the previous one is also opened, all i want to do here is when i click on button and that window is already open then it simply go to already opened windows except opening the new one.
hope you guys understand my question and will help me doing it.
EDIT:
i tried this code : the code i wrote in frm2.cs file is:
public partial class frm2 : Form
{
private static frm2 _form2 = null;
public frm2()
{
InitializeComponent();
}
public static frm2 Instance
{
get
{
if (_form2 == null)
{
_form2 = new frm2();
}
return _form2;
}
}
and in frmMain.cs file where i code to access the instance and open the project is :
private void addProductToolStripMenuItem_Click(object sender, EventArgs e)
{
frm2.Instance.Show();
//frm2 cs = new frm2();
//cs.Show();
}
it work fine the first time, but when i open the frm2 , close it and then again try to open it the compiler give error at frm2.Instance.Show(); and the error comes is
: Cannot access a disposed object.
Object name: 'frm2'.
Save the instance of the form opened in a global class variable and then, if this variable is not null just call Show instead of opening againg. Some tips should be followed though
public class Form1: Form
{
private frm2 _currentInstance = null;
....
if(_currentInstance == null)
{
_currentInstance = new frm2();
_currentInstance.FormClosed += instanceHasBeenClosed;
_currentInstance.Show();
}
_currentInstance.BringToFront();
....
private void instanceHasBeenClosed(object sender, FormClosedEventArgs e)
{
_currentInstance = null;
}
}
It is important to subscribe to the FormClosed event for the _currentInstance. In this way your Form1 will be notified when your user closes the instance. And you could reset the internal variable to null, so at the subsequent click you could reopen again the instance
There is also the possibility to use the Application.OpenForms collection to check if your form is shown
frm2 f = Application.OpenForms["NameOfForm2"];
if(f != null)
f.BringToFront();
else
{
frm2 f = new frm2();
f.Show();
}
I know you don't want to write that much code but it seems this is the only way to go.
At least, you can separate that code from your forms by writing a generic code.
var f = FormManager.Show<Form2>(); //create a new form.
f = FormManager.Show<Form2>(); //show the existing form.
f.Close();
f = FormManager.Show<Form2>(); //create a new form
public static class FormManager
{
static Dictionary<Type, Form> _Forms = new Dictionary<Type, Form>();
public static T Show<T>() where T: Form, new()
{
var type = typeof(T);
Form f = null;
if(_Forms.TryGetValue(type,out f))
{
f.BringToFront();
}
else
{
f = new T();
f.FormClosing += (s, e) => _Forms.Remove(s.GetType());
_Forms.Add(type, f);
f.Show();
}
return (T)f;
}
}
you can use singleton design pattern to return always the same instance
public partial class Form2 : Form
{
private static Form2 _form2 = null;
private Form2()
{
InitializeComponent();
}
public static Form2 Instance
{
get
{
if (_form2 == null)
{
_form2 = new Form2();
}
return _form2;
}
}
}
// use this to call the instance
Form2.Instance.Show();
Singleton pattern may be a way to go - just apply it to windows forms (you can check this link for the description of the singleton pattern in C#: http://msdn.microsoft.com/en-us/library/ff650316.aspx).
Check on multiple buttons in that Form is open or not:
private bool isOpen(string name)
{
IsOpen = false;
foreach (Form f in Application.OpenForms)
{
if (f.Text == name)
{
IsOpen = true;
f.Focus();
break;
}
}
if (IsOpen == false)
{
return IsOpen;
}
return IsOpen;
}
Call this in the button click to Check the current Form:
if (isOpen("Item Import Master")) ;
else
{
Item_Import_Master obj1 = new Item_Import_Master();
obj1.Show();
}
You need to check if a form is Disposed before you show it again, otherwise you get Cannot access a disposed object exeption
something like this should work
private static AdvancedRDSWindow form2;
private AdvancedRDSWindow()
{
InitializeComponent();
}
public static AdvancedRDSWindow Instance
{
get
{
if (form2 == null || form2.IsDisposed)
{
form2 = new AdvancedRDSWindow();
}
return form2;
and then you can show it with a button for instance
private void AdvancedRDS_Click(object sender, EventArgs e)
{
AdvancedRDSWindow.Instance.Show();
}
Use this code in the button click event
If the form is already opened, it will bring the form to front
# Here is my code.. #
foreach (Form form in Application.OpenForms)
{
if (form.GetType() == typeof(frm2))
{
form.Activate();
return;
}
}
frm2 frm = new frm2();
frm.Show();

c# how check if the form is already open in compact framework

FormCollection fc = Application.OpenForms;
foreach (Form frm in fc)
{
//iterate through
}
OR
Form fc = Application.OpenForms["FORMNAME"]; if (fc != null) fc.Close(); fm.Show();
but non of this works in compact framework 3.5. How can i check if form is already opened in CF 3.5?
As #Barry wrote, you will have to do it yourself. Easiest way is to use a dictionary. Your key can be a form's type, its name, or whatever you need.
private static readonly Dictionary<string, MyForm> _dict
= new Dictionary<string, MyForm>();
public MyForm CreateOrShow(string formName)
{
Form f = null;
if (!_dict.TryGetValue(formName, out f))
{
f = new MyForm();
_dict.Add(formName, f);
}
return f;
}
Or, if you want to support multiple form types and want to avoid casting, use a generic method:
private static readonly Dictionary<string, Form> _dict
= new Dictionary<string, Form>();
public T CreateOrShow<T>(string formName) where T : Form, new()
{
Form f = null;
if (!_dict.TryGetValue(formName, out f))
{
f = new T();
_dict.Add(formName, f);
}
return (T)f;
}
public T CreateOrShow<T>(string formName, Func<T> ctor) where T : Form
{
Form f = null;
if (!_dict.TryGetValue(formName, out f))
{
f = ctor();
_dict.Add(formName, f);
}
return (T)f;
}
There are two generic overloads. One of them is used like this:
// use this if MyFormType has a parameterless constructor
var form = CreateOrShow<MyFormType>("Form1");
or, if you need to pass parameters to your form during init:
// use this if MyFormType accepts parameters in constructor
var form = CreateOrShow<MyFormType>("Form1", () => new MyFormType(someData));
The Application.OpenForms collection doesn't exist in the Compact Framework.
You would have to roll your own collection and keep track of them that way.
There is nice tutorial here that explains how to achieve this.
You could have a static boolean field on all your forms. Then you'd have to create a couple methods to toggle it, and bind the Opening and Closing event handlers to it. Not the most elegant solution admittedly.
partial class Form1 : Form
{
static bool IsFormOpen;
public Form1()
{
InitializeComponent();
this.Load += SignalFormOpen;
this.FormClosing += SignalFormClosed;
}
void SignalFormOpen(object sender, EventArgs e)
{
IsFormOpen = true;
}
void SignalFormClosed(object sender, EventArgs e)
{
IsFormOpen = false;
}
}
Either that or make a collection of forms somewhere, and each time a form loads make it store a reference to itself in it, and iterate against that to check if the form is open/exists

How can I make a single instance form (not application)?

In my C# application I have an option dialog that can be opened from a menu command.
I want to ensure that the option dialog have only one instance (user cannot open more than one option window at a given time) without making it modal.
Also if the user already have this window opened, and he clicks in the menu item to open it again, the app just makes the already visible form became the top most window.
Can anyone point me directions on how accomplish these tasks?
Thank you very much.
Well, the simplest way is to have a static field which stores a reference to the single instance or null, and then a method to retrieve it or create a new one.
Note that this isn't the same as making it a singleton - because I assume if the form is closed, you'd want to create a new instance next time. (The alternative - hiding it and reusing it - is shown in STO's answer.) You may want something like this:
public class OptionsDialog : Form
{
private static OptionsDialog openForm = null;
// No need for locking - you'll be doing all this on the UI thread...
public static OptionsDialog GetInstance()
{
if (openForm == null)
{
openForm = new OptionsDialog();
openForm.FormClosed += delegate { openForm = null; };
}
return openForm;
}
}
You may want to make the method perform the "bring it to the front" steps as well, of course.
You need to prevent the form from closing. If you don't, the form will be disposed and becomes unusable. You can do this by implementing the FormClosing event:
protected override void OnFormClosing(FormClosingEventArgs e) {
if (e.CloseReason == CloseReason.UserClosing) {
this.Hide();
e.Cancel = true;
}
}
To make it a singleton, just keep track of the life time of the form in your main form class:
frmOptions options;
private void btnShowOptions_Click(object sender, EventArgs e) {
if (options == null) {
options = new frmOptions();
// To make absolutely sure:
options.FormClosed += (o, ea) => options = null;
}
else {
options.WindowState = FormWindowState.Normal;
}
options.Show();
}
You will need this form as property
Form1 myForm = null;
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
myForm = null;
}
private void ShowForm()
{
if (myForm != null)
{
myForm.BringToFront();
}
else
{
myForm = new Form1;
myForm.Show();
}
}
you may use code like this:
private MyDialogForm _FormInstance;
public void ShowOptions()
{
if (_FormInstance == null)
{
_FormInstance = new MyDialogForm();
_FormInstance.FormClosing += (s,e) =>
{
e.Cancel = true;
_FormInstance.Hide();
}
}
_FormInstance.Show();
}
I assume you have at least two forms. One form, call it frmMain, allows you to open frmOptions. In frmMain, add a variable of type frmOptions like this:
public partial class frmMain : Form
{
private frmOptions optionsInstance = null;
...
In the routine that opens the Options dialog, add this:
if (optionsInstance == null || !optionsInstance.Visible)
{
optionsInstance = new frmOptions();
optionsInstance.Show();
}
When frmOptions closes, optionsInstance will not be null, so that's why you check if it's visible before instantiating a frmOptions instance.
If this doesn't work for you, you could try a mutex, but that's probably overkill.
Based on Jon Skeet's answer, I'm using the following code for showing a form as a modal dialog box.
if (this.aboutForm == null)
{
this.aboutForm = new AboutForm();
this.aboutForm.FormClosed += (sender2, e2) => { this.aboutForm = null; };
this.aboutForm.ShowDialog(this);
}
else
{
this.aboutForm.Focus();
}
I have to do this because I have a menu item to display the About form in the menu of the main form, and in the context menu of the notify icon. If I open the About form using the menu of the main form, I still can open another instance by using the context menu item of the notify icon.
Main_Frm _main_Frm = null;
private void Show_bt_Click(object sender, EventArgs e)
{
if (_main_Frm != null)
{
_main_Frm .BringToFront();
}
else
{
_main_Frm = new Comission_Frm();
_main_Frm .Show();
}
//This condition used when you closed the form the form will disposed and when you reopen.
if (_main_Frm .IsDisposed)
{
_main_Frm = new _Main_Frm ();
_main_Frm .Show();
}
}
This May Help!
Note: The following code was taken from the article Below:
https://www.dotnetcurry.com/ShowArticle.aspx?ID=150
static class Program
{
///<summary>
/// The main entry point for the application.
///</summary>
[STAThread]
static void Main()
{
bool instanceCountOne = false;
using (Mutex mtex = new Mutex(true, "MyRunningApp", out instanceCountOne))
{
if (instanceCountOne)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
mtex.ReleaseMutex();
}
else
{
MessageBox.Show("An application instance is already running");
}
}
}
}

Categories