gpt4 book ai didi

c# - 确保派生进程的窗口位于主应用程序的前面?

转载 作者:可可西里 更新时间:2023-11-01 14:45:13 26 4
gpt4 key购买 nike

在我的 GUI 应用程序中,我使用 C# Process 类来生成可能启动窗口的外部进程。子进程窗口可能会通过第三方 API 调用显示,因此并非总能获得窗口句柄。有没有办法确保子进程的窗口显示在主应用程序窗口的前面?

最佳答案

通常的方法是:

1 。获取 Process.Start() 返回的 Process 类实例
2.查询进程.MainWindowHandle
3.调用非托管 Win32 API 函数“ShowWindow”或“SwitchToThisWindow”

您的问题的诀窍在于“子流程窗口可能会通过第三方 API 调用显示”。在这种情况下,您将需要获取生成的 exe 的窗口句柄和枚举子窗口。一旦您拥有 API 调用后显示的表单的句柄,您就可以使用 BringWindowToTop API .

我用 How To Enumerate Windows Using the WIN32 API 做了一个小测试作为灵感。创建具有 1 个窗体和 2 个按钮的 Windows 应用程序:

public partial class Form1 : Form
{
[DllImport("user32.dll", SetLastError = true)]
static extern bool BringWindowToTop(IntPtr hWnd);

[DllImport("user32")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i);

public Form1()
{
InitializeComponent();
}

private System.IntPtr hWnd;
private void button1_Click(object sender, EventArgs e)
{
Process p = Process.Start(@"C:\TFS\Sandbox\3rdPartyAppExample.exe");
try
{
do
{
p.Refresh();
}
while (p.MainWindowHandle.ToInt32() == 0);

hWnd = new IntPtr(p.MainWindowHandle.ToInt32());
}
catch (Exception ex)
{
//Do some stuff...
throw;
}
}

private void button2_Click(object sender, EventArgs e)
{
3rdPartyAppExample.Form1 f = new 3rdPartyAppExample.Form1();
f.ShowForm2();
//Bring main external exe window to front
BringWindowToTop(hWnd);
//Bring child external exe windows to front
BringExternalExeChildWindowsToFront(hWnd);
}

private void BringExternalExeChildWindowsToFront(IntPtr parent)
{
List<IntPtr> childWindows = GetChildWindows(hWnd);
foreach (IntPtr childWindow in childWindows)
{
BringWindowToTop(childWindow);
}
}

// <summary>
/// Returns a list of child windows
/// </summary>
/// <param name="parent">Parent of the windows to return</param>
/// <returns>List of child windows</returns>
public static List<IntPtr> GetChildWindows(IntPtr parent)
{
List<IntPtr> result = new List<IntPtr>();
GCHandle listHandle = GCHandle.Alloc(result);
try
{
EnumWindowProc childProc = new EnumWindowProc(EnumWindow);
EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
}
finally
{
if (listHandle.IsAllocated)
listHandle.Free();
}
return result;
}

/// <summary>
/// Callback method to be used when enumerating windows.
/// </summary>
/// <param name="handle">Handle of the next window</param>
/// <param name="pointer">Pointer to a GCHandle that holds a reference to the list to fill</param>
/// <returns>True to continue the enumeration, false to bail</returns>
private static bool EnumWindow(IntPtr handle, IntPtr pointer)
{
GCHandle gch = GCHandle.FromIntPtr(pointer);
List<IntPtr> list = gch.Target as List<IntPtr>;
if (list == null)
{
throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
}
list.Add(handle);
// You can modify this to check to see if you want to cancel the operation, then return a null here
return true;
}

/// <summary>
/// Delegate for the EnumChildWindows method
/// </summary>
/// <param name="hWnd">Window handle</param>
/// <param name="parameter">Caller-defined variable; we use it for a pointer to our list</param>
/// <returns>True to continue enumerating, false to bail.</returns>
public delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter);

}

3rdPartyAppExample 是一个具有 2 个表单的 Winform 应用程序。我引用这个应用程序并调用 Form1 的公共(public)方法来显示 Form2:

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void ShowForm2()
{
var f = new Form2();
f.Show();
}

您可能希望选择 check the Windows Caption :

  hInst = ProcessStart("calc.exe")

// Begin search for handle
hWndApp = GetWinHandle(hInst)

If hWndApp <> 0 Then
// Init buffer
buffer = Space$(128)

// Get caption of window
numChars = GetWindowText(hWndApp, buffer, Len(buffer))

另一个解决方案(不是很稳定)在这里讨论: http://www.shloemi.com/2012/09/solved-setforegroundwindow-win32-api-not-always-works/

诀窍是让窗口“认为”我们的进程和目标窗口 (hwnd) 通过附加线程(使用 AttachThreadInput API)相关。

关于 myTopForm.TopMost = true 答案,它不适用于外部应用程序。

关于c# - 确保派生进程的窗口位于主应用程序的前面?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13881634/

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