I think this might be impossible. Please proof me wrong.
Following setup:
- My .NET C# Application with GUI (lets call it
gui) opens another application (lets call itserver) by creating anew Process() - The
server(developed by somebody else) is started with a parameter to hide its GUI - The
guiwaits for the user to make some inputs - The
guithen commands theserverto perform some tasks - Those tasks are defined in an assembly/DLL which i provide to the
server - One of those tasks is to open a Form/Dialog and ask the user some more questions
Now because the whole userexperience needs to be optimized for repeated operation, the GUI elements (windows/forms/dialogs) that open need to be pre-selected/focused/active.
The first problem arises as i did not find a clear explanation of what the difference between those properties (Focus, Active, Selected, TopMost) is.
Now the real question is, how can i ensure that all GUI elements are active and selected, regardless of whether they are started by my gui process or the server process?
Using the WINAPI can be more powerful i read so i defined the following
// required to use WINAPI for RegainFocus();
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern int SetForegroundWindow(IntPtr hwnd);
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern IntPtr SetActiveWindow(IntPtr hwnd);
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
static private void RegainFocus()
{
// set focus back to and show application for faster input
// SW_RESTORE = 9
ShowWindow(Process.GetCurrentProcess().MainWindowHandle, 9);
SetForegroundWindow(Process.GetCurrentProcess().MainWindowHandle);
SetActiveWindow(Process.GetCurrentProcess().MainWindowHandle);
}
Then what i have tried so far is:
- Set the
StartInfoof theserverprocess like this (so the new process does not steal the focus ofgui)myProcess.StartInfo.UseShellExecute = false; myProcess.StartInfo.CreateNoWindow = true; myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; - Start the
serverprocess andWaitForInputIdle(like described here) to assure that theserveris really ready - Also use
RegainFocus()in theguiapp - In the DLL for the
serveri create a newForm()and try (to bring the window to front and have it selected)myForm = new Form(); myForm.Activated += dialog_Activated; myForm.PerformLayout(); myForm.TopMost = true; myForm.Activate(); myForm.BringToFront(); myForm.Focus(); myForm.Select(); DialogResult result = myForm.ShowDialog(); - The
TopMost=trueworks in bringing the dialog in front ofgui - The
dialog_Activated()method sets the Focus on the first input control usingFocusControl(). This works.
The result of this is a window on top of my gui which has the cursor blinking in the first input control but is deselected/inactive. When i hit <TAB> i can see a different control gets selected in the gui which is in the background.
I tried spraying RegainFocus() calls in the Form as well, didnt work.
Further ideas that i have but no way of achieving them:
- Defocus the
guionce the input is done there, but there is nounFocus() - override some important events in my Form class, but how and which ones?
Target Framework is .NET 4.5, target operating systems are Windows 7 and Windows 10.
Thank you for any help and inputs/tipps!