我认为这可能是不可能的。请证明我错了。
以下设置:
gui
的.NET C#应用程序)通过创建server
new Process()
)
server
(由其他人开发)以隐藏其GUI的参数开头gui
等待用户进行一些输入gui
然后命令server
执行一些任务server
现在,由于需要优化整个用户体验以进行重复操作,因此需要预先选择/集中/激活打开的GUI元素(窗口/表单/对话框)。
出现第一个问题是因为我没有清楚地了解difference between those属性(焦点,活动,已选择,TopMost)是什么。
现在真正的问题是,无论我的gui
进程还是server
进程启动了我如何确保所有GUI元素都处于活动状态并被选中?
我阅读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()
将焦点设置在第一个输入控件上。这行得通。此操作的结果是在我的gui
上方的一个窗口,该窗口的光标在第一个输入控件中闪烁,但是未选中/处于不活动状态。当我按下<TAB>
时,我可以看到在后台的gui
中选择了另一个控件。
我也尝试在表单中喷射RegainFocus()
调用,但是没有用。
我还无法实现的其他想法:
gui
散焦,但是there is no unFocus()
目标框架是.NET 4.5,目标操作系统是Windows 7和Windows 10。
谢谢您的帮助和帮助!
答案 0 :(得分:2)
我有一个似乎可以在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
中的combination,最后是AttachThreadInput
AllowSetForegroundWindow
与[ASFW_ANY][11]
AppActivate
from VB.NET in C#