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
gui
waits for the user to make some inputs - The
gui
then commands theserver
to 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
StartInfo
of theserver
process 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
server
process andWaitForInputIdle
(like described here) to assure that theserver
is really ready - Also use
RegainFocus()
in thegui
app - In the DLL for the
server
i 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=true
works 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
gui
once 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!