BNT*_*BNT 2 .net c# winapi winforms
我想这可能是不可能的。请证明我错了。
以下设置:
gui)通过创建一个来打开另一个应用程序(让我们称之为它server)new Process()server由其他人开发)以一个参数启动以隐藏其 GUIgui用户进行一些输入gui命令server执行一些任务server现在,由于整个用户体验需要针对重复操作进行优化,因此打开的 GUI 元素(窗口/表单/对话框)需要预先选择/聚焦/活动。
第一个问题的出现是因为我没有找到这些属性(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);
}
Run Code Online (Sandbox Code Playgroud)
那么到目前为止我尝试过的是:
StartInfo进程的server(这样新进程就不会抢走焦点gui)
Run Code Online (Sandbox Code Playgroud)myProcess.StartInfo.UseShellExecute = false; myProcess.StartInfo.CreateNoWindow = true; myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
server过程WaitForInputIdle(如此处所述)以确保server真正准备好RegainFocus()在gui应用程序中使用server我创建一个新的Form()并尝试(将窗口置于前面并选择它)
Run Code Online (Sandbox Code Playgroud)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将对话框放在前面的工作guidialog_Activated()方法使用 将焦点设置在第一个输入控件上FocusControl()。这有效。其结果是在我的顶部出现一个窗口gui,其中光标在第一个输入控件中闪烁,但已取消选择/不活动。当我点击时,我可以看到在后台<TAB>选择了不同的控件。gui
我也尝试RegainFocus()在表单中喷洒电话,但没有成功。
我有更多想法但无法实现:
目标框架是.NET 4.5,目标操作系统是Windows 7和Windows 10。
感谢您的任何帮助和意见/提示!
我得到了一个似乎适用于 Windows 10 和 Windows 7 的解决方案。
在我失去焦点后,我使用该RegainFocus()功能重新获得焦点(并激活窗口),请参阅问题。注意:不要将 processHANDLE和MainWindowHandle. 当一个对象被隐藏时,它MainWindowHandle很可能是隐藏的0。
我删除了
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.CreateNoWindow = true;
myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
Run Code Online (Sandbox Code Playgroud)
当启动server进程时,为了不弄乱可见性状态。但我还是保留了[WaitForInputIdle][1]。
在Windows 7上,这仍然不够,并且创建的进程上的AllowSetForegroundWindow不起作用(不过感谢您的评论),任务栏不是将窗口带到前面,而是闪烁。这里的解决方案是设置注册表值
\HKEY_CURRENT_USER\Control Panel\Desktop\ForegroundLockTimeout
Run Code Online (Sandbox Code Playgroud)
并0重新启动机器。然后,代码在 Windows 7 和 10 上的行为相同。如果有正确的权限,甚至可以通过编程来完成此操作。
由于这个问题有很多不同的答案和解决方案,我认为它取决于许多因素(如 Windows 版本、注册表设置、可能 UAC 和主题设置、框架和运行时、更多条件,...),这就是为什么我我还想提一下我发现的其他方法。
SetForegroundWindowWM_SHOWWINDOWShowWindow与SW_RESTORE和SW_SHOW 之前 SetForegroundWindow[SetWindowPos][10]SetActiveWindowSetFocusAttachThreadInputAllowSetForegroundWindow与使用[ASFW_ANY][11]AppActivate VB.NET | 归档时间: |
|
| 查看次数: |
3509 次 |
| 最近记录: |