Reputation: 735
I know that there are event handlers for classes which are inherited from form class. By using these events we can understand if a form is created or not. for example Form Load event handler. I am working on the almost large-scale project which consists of too many forms. In this project, the user can create multiple workspaces and open the different forms in each workspace. When the user closes a workspace all the related form should be closed. For implementing this feature, I have considered a dictionary with the keys of the workspace id that values are the related open forms. Therefore, I should add the values when the user opens the forms. this can be done if I add a line code to each form loaded event handler but it takes the time. I want to know if I can understand that a form is opened from the main form.
p.s: I am familiar with the Application.Openforms. it is not helpful in this scenario.
Upvotes: 0
Views: 419
Reputation: 735
Thank @Jimi and @TnTinMn.
The easiest solution(required less effort) is using WindowOpenedEvent. This event listener identifies a window which has been opened. It is worth to mention that when any window is opened on your operating system this event is raised. We can compare the process ID of the opened/created window to our application process ID to understand which form is related to the application. Please notice that UIAutomationClient and UIAutomationType DLL should be added to the project. These DLL are located in :
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\UIAutomationClient.dll
I have added below code to Program.cs file.
MainForm mainForm = new MainForm();
Automation.AddAutomationEventHandler(
WindowPattern.WindowOpenedEvent, AutomationElement.RootElement,
TreeScope.Subtree, (uiElm, evt) =>
{
AutomationElement element = uiElm as AutomationElement;
if (element == null) return;
try
{
if (element.Current.ProcessId == Process.GetCurrentProcess().Id)
{
IntPtr elmHandle = (IntPtr)element.Current.NativeWindowHandle;
Form form = Application.OpenForms.OfType<Form>()
.Where(f => (f.AccessibilityObject as Control.ControlAccessibleObject).Handle == elmHandle)
.FirstOrDefault();
mainForm.UpdateTabFormsDict(form); // adding a open form to the current tab
}
}
catch (ElementNotAvailableException)
{ /* May happen when Debugging => ignore or log */
}
});
For more information you can see Run event when any Form loads. WindowPattern also provides WindowClosedEvent.
Upvotes: 1
Reputation: 5986
I had a similar issue in the past, first thing that crossed my mind back there was to use System.Reflection
but it is impossible because you can not identify in run time what instance was created.
I have not found any "magic" solution for that issue, but The most easy and safe solution I found was to extend Form
base class (to my custom SuperForm
) and using this base class to coordinate and update a static list of all instances from this base class (by overriding OnLoad()
and OnClosed()
methods).
Obviously all application forms must inherit from SuperForm
.
Also, I found that in a vast winforms application, making all forms to inherit a class that you extend by yourself is a good practice because it gives you much more control over the application and can make your life easier in the future.
here is a sample of the architecture:
SuperForm Class:
public class SuperForm : Form
{
private bool _isFormActive = false;
public bool isFormActive
{
get
{
return this._isFormActive;
}
set
{
this._isFormActive = value;
}
}
protected override void OnLoad(EventArgs e)
{
this.isFormActive = true;
AppForms.Add(this);
base.OnLoad(e);
}
protected override void OnClosed(EventArgs e)
{
this.isFormActive = false;
AppForms.Remove(this);
base.OnClosed(e);
}
}
Static class with static list to handle application forms instances:
public static class AppForms
{
private static List<SuperForm> _AppFormsList;
public static List<SuperForm> AppFormsList
{
get
{
if (_AppFormsList == null)
{
_AppFormsList = new List<SuperForm>();
}
return _AppFormsList;
}
set
{
_AppFormsList = value;
}
}
public static void Add(SuperForm instance)
{
AppFormsList.Add(instance);
}
public static void Remove(SuperForm instance)
{
AppFormsList.Remove(instance);
}
}
Implementation:
public partial class Form1 : SuperForm
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
// you dont have to use polymorphism...
SuperForm f = new Form2();
f.Show();
}
private void button2_Click(object sender, EventArgs e)
{
// you dont have to use polymorphism...
SuperForm f = new Form3();
f.Show();
}
private void button3_Click(object sender, EventArgs e)
{
// show all the forms that are active
foreach (var frm in AppForms.AppFormsList)
{
MessageBox.Show(((SuperForm)frm).isFormActive.ToString());
}
}
}
Upvotes: 1