我想这可能是不可能的。请证明我错了。
以下设置:
gui
)通过创建一个server
打开另一个应用程序(让我们称之为new Process()
)server
(由其他人开发)以一个参数来启动,以隐藏其GUIgui
等待用户做出一些输入gui
命令server
执行一些任务server
的程序集/ DLL中定义现在因为需要针对重复操作优化整体使用体验,所以打开的GUI元素(窗口/窗体/对话框)需要预先选择/聚焦/激活。
第一个问题出现了,因为我没有找到difference between those属性(Focus,Active,Selected,TopMost)的明确解释。
现在真正的问题是,我如何确保所有GUI元素都处于活动状态并被选中,无论它们是由我的gui
进程还是server
进程启动的?
使用WINAPI可以更强大我阅读所以我定义了以下内容
// 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);
}
然后我到目前为止尝试的是:
StartInfo
过程的server
(所以新过程不会窃取gui
的焦点)
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.CreateNoWindow = true;
myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
server
流程和WaitForInputIdle
(如描述here)以确保server
真的准备好了RegainFocus()
应用程序中使用gui
server
的DLL中,我创建了一个新的Form()
并尝试(将窗口置于前面并选择它)
myForm = new Form();
myForm.Activated += dialog_Activated;
myForm.PerformLayout();
myForm.TopMost = true;
myForm.Activate();
myForm.BringToFront();
myForm.Focus();
myForm.Select();
DialogResult result = myForm.ShowDialog();
TopMost=true
致力于在gui
面前展示对话dialog_Activated()
方法使用FocusControl()
将Focus设置为第一个输入控件。这有效。结果是我的gui
顶部有一个窗口,它在第一个输入控件中闪烁,但是取消选择/不活动。当我点击<TAB>
时,我可以看到在背景中的gui
中选择了不同的控件。
我尝试在表格中喷涂RegainFocus()
电话,没有用。
我有进一步的想法,但无法实现它们:
gui
,但there is no unFocus()
Target Framework是.NET 4.5,目标操作系统是Windows 7和Windows 10。
感谢您的帮助和输入/ tipps!
我得到了一个似乎适用于Windows 10和Windows 7的解决方案。
在我的焦点丢失后,我使用RegainFocus()
函数重新获得焦点(并激活窗口),请参阅问题。注意:不要混合过程HANDLE
和MainWindowHandle
。当一个物体被隐藏时,它的MainWindowHandle
很可能是0
。
我删除了
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.CreateNoWindow = true;
myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
在启动server
进程时,为了不干扰可见性状态。我保留了[WaitForInputIdle][1]
。
在Windows 7上,这仍然不够,并且AllowSetForegroundWindow在创建的进程上不起作用(感谢评论),而不是将窗口带到前面,taskbar was flashing。这里的解决方案是set the registry value的
\HKEY_CURRENT_USER\Control Panel\Desktop\ForegroundLockTimeout
到0
并重新启动机器。然后代码对于Windows 7和10的行为相同。使用正确的权限,这甚至可能是done programatically。
由于这个问题有很多不同的答案和解决方案,我认为它取决于许多因素(如Windows版本,注册表设置,可能是UAC和主题设置,框架和运行时,一些more conditions,...)这就是我想要的原因提到我发现的其他方法。
SetForegroundWindow
WM_SHOWWINDOW
消息ShowWindow
与SW_RESTORE
和SW_SHOW
before SetForegroundWindow
[SetWindowPos][10]
和SetActiveWindow
的SetFocus
AttachThreadInput
锁定AllowSetForegroundWindow
[ASFW_ANY][11]
Disable SetForegroundWindow