Show Form on applications main window - c#

Two windows apps communicate through .net remoting. The host publishes an instance of a class that the client can call methods on through remoting.
The class has a method which pops up a form if not already visible, using form.Show() and performs some functions in a thread.
When the thread completes the form disappears even though I don't explicitely close it. The instance of the class does not go out of scope, and the class instance maintains a reference to the form.
I don't want the form to disappear and am thinking that if I use the Form.Show(System.Windows.Forms.IWin32Window) overload this would work if I pass the applcation main form to the Show method. The problem is my class instance knows nothing about the application. Is there any way to find the applications main form?
The form is being created and shown inside the thread.

Related

Windows form controlled by main loop

How can I control windows form class in the main loop?
Can I still run my code in the main loop like a console program but use windows form to display stuff? I already done that I've got windows form application and console in one but once main calls windows form that's it, it doesn't come back to main.
Can I pass variables to windows form?
You can't.
When you call Application.Run, the method only returns when there is no active Form any more. This is because Application.Run keeps the message loop running. It blocks the current method form returning. See it as a while (mainFormActive). It will never end unless the main form is closed.
If you want to execute code in the mean time, set up a Task, a Thread or similar, before you start the form.
And yes, you can pass variables in, just like in any constructor.

Close form override

I’ve created a winform application with lots of forms, (in mdi and dialog)
but every time a close a form it stays in the memory,
so I would like to use de .Dispose() option.
but I don’t want to add this code to ALL of the forms,
I just want to place one code that’s activates on a FormClose command,
can i use en override.onFormClose command?
and where in the application do I put this code,
I tried it at the MDI form, but without success
Thanks,
Bram
ps
i'm using DevExpress components
If you call GC.Collect() and the forms are still in memory, then it is because there is a reference held to them somewhere.
You need to trace all references and make sure they are being released.
Craete a separate base class, implement your dispose method, and then inherit all forms from this class

Start a C# Application without a form, but that include forms

I am using MVC in my application, but with a small difference: 4 layers. It contains Model, View, Control and an Orchestrator. This is the main controller, and is the one who says which view controller is active at a time.
Therefore, I must have my entry point calling this Orchestrator class, which will create a controller and this controller will create the view, which will be shown. Whenever the views are closed, the application must stop and finish also.
However, I am not able using Application.Run inside the Main function, in Program.cs to run a class which is not a form. How is it possible to do implement the architecture I wish?
Sounds like you want the overload of Application.Run that takes an ApplicationContext.
The example on that page shows how to use ApplicationContext to exit the app when all of your forms are closed (rather than the default, of exiting when the main form is closed). You should be able to adapt this to your use.

After showing and closing a dialog win32 GetForegroundWindow() still returns that window

My application doesn't have a main Form. Initialization is done in Program.Main() and then Application.Run() is called.
When the user is in a different application they press a keyboard shortcut which triggers the following in my application:
Instantiate my form.
Show the form.
Call the win32 API GetForegroundWindow() to find out which window is active.
Do some stuff.
Call form.Close()
Set form = null
I can execute the above a few times and all is well. However, if my application calls MessageBox() at any time all subsequent calls to GetForegroundWindow() will return the form which was closed even if the current focus is in a different application. This also happens if CredUIPromptForCredentials() prompted the user for a login and password. The call ProcessInfo.GetActiveProcess() also returns my process instead of the other app that has the focus.
Any idea what I might be doing wrong? Is there maybe something I can call to remove the focus from my app; kind-of the reverse of SetForeGroundWindow?
EDIT 1
It's actually a non-modal form, not a dialog. I'm using Show() with no argument to show the form. I tried calling Dispose() after Close() but the behavior is the same. I confirmed that the app works correctly if I never call Show() on my form. The form has all the defaults you get when you create it in VS2010 except for changing the title. The form only contains one label.
Per the docs from Form.Close:
The two conditions when a form is not disposed on Close is when (1) it is part of a multiple-document interface (MDI) application, and the form is not visible; and (2) you have displayed the form using ShowDialog. In these cases, you will need to call Dispose manually to mark all of the form's controls for garbage collection.
I am presuming your form is a dialog since that is what is mentioned in the title. It looks like you will need to explicitly call Dispose to deallocate the win32 resources.

Blocking function call

I am writing a small test application to test a communication interface. The communication interface is written in C++ (a DLL) and the test application using C#. The communication interface in turn talks to a low level hardware stack which uses windows messages to transmit and receive data. In order to achieve this, the commuication interface DLL creates an invisible child window whose parent is the C# test application window. The sequence to talk to the hardware is as follows :
Initialize the communication library. This step expects the main window handle and application instance which is passed to the low level stack for windows messaging.
Connect using the device address
Read/Write
Close
Deinitialize the communication library.
Now in the 2nd step, the DLL creates an invisible window to communicate with the low level hardware stack. Since the 2nd step is a blocking call, I want my UI to be responsive during this time in case it takes a long time to connect. Therefore, I try to connect asynchronously using a thread or a BeginInvoke call. But I observe that after the connection is established, the application window hangs as long as the child window exists. The child window seems to block all incoming messages to the main window. This seems to be because the child window gets created in another thread.
But I dont want want the connect to be in the main thread as it hangs the UI.
I would welcome any ideas on how to avoid this problem ? Thanks in advance.
-Harish
All communication with a window handle must be done on the thread this handle was created on. This probably means that all calls to the DLL should be done on the secondary thread.
You can try the following:
Before initializing the DLL, start a background thread;
On that thread, create a WinForms window you do not show. You can do this like this:
-
public static Form BackgroundForm;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
new Thread(new ThreadStart(Secondary)).Start();
Application.Run(new MainForm());
}
static void Secondary()
{
BackgroundForm = new Form();
// Calling Handle creates the system HWND. You do not have to call Show
// or something similar on this Form to make the handle available or use
// Invoke or BeginInvoke.
var handle = BackgroundForm.Handle;
// Initialize the DLL here with the handle.
Application.Run();
// Unintialize the DLL.
}
Then, initialize the DLL with the handle you got from the background form;
When you need to do calls to the DLL, do this using Invoke and BeginInvoke to this background form;
Once it's time to shut down your application, do an Application.ExitThread() through a Invoke or BeginInvoke.
The problem you are seeing with the main form being blocked, is probably because the child window created in the DLL has the main form's handle as it's parent Window, but that's just a guess. This should probably also be solved using this system.

Categories