gpt4 book ai didi

c# - 如何激活由另一个进程启动的窗口

转载 作者:太空宇宙 更新时间:2023-11-03 22:38:25 29 4
gpt4 key购买 nike

我认为这可能是不可能的。请证明我错了。

以下设置:

  • 我的带有 GUI 的 .NET C# 应用程序(我们称之为 gui)通过创建一个 server 打开另一个应用程序(我们称之为 new Process())
  • server (由其他人开发)以隐藏其 GUI 的参数启动
  • gui等待用户进行一些输入
  • 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);
}

那么到目前为止我尝试的是:

  • 设置StartInfoserver像这样的过程(所以新过程不会窃取 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()也在表格中调用,但没有用。

我还有其他想法但无法实现:

目标框架是 .NET 4.5,目标操作系统是 Windows 7 和 Windows 10。

感谢您的任何帮助和意见/建议!

最佳答案

我得到了一个似乎适用于 Windows 10 和 Windows 7 的解决方案。

失去焦点后,我使用 RegainFocus() 函数重新获得焦点(并激活窗口),请参阅问题。注意:不要混合处理 HANDLEMainWindowHandle。当一个对象被隐藏时,它的 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 ,...)和这就是为什么我想提及我发现的其他方法。

关于c# - 如何激活由另一个进程启动的窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53706056/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com