我们只想在任何时候运行一个应用程序实例。因此,在启动时,它会查看应用程序是否正在运行,如果是,则在主窗口上调用 SetForegroundWindow 。
这一切都很好...... 大部分......
当我们的应用启动时,它会显示启动画面和登录表单。这两种形式都有 ShowInTaskBar = false 。
因此,如果您在显示登录表单时尝试启动应用程序的另一个副本,则该登录表单不会显示在前面!
特别是当用户也无法在任务栏中看到任何内容时,他们认为所有应用程序都是duff且无法启动。没有迹象表明还有另一个实例正在运行。
有没有解决这个问题的方法?
答案 0 :(得分:47)
嗯,代码就在这里。即使ShowInTaskBar
为false
,您也应该能够将其带到前面。
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(String lpClassName, String lpWindowName);
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
public static void bringToFront(string title) {
// Get a handle to the Calculator application.
IntPtr handle = FindWindow(null, title);
// Verify that Calculator is a running process.
if (handle == IntPtr.Zero) {
return;
}
// Make Calculator the foreground application
SetForegroundWindow(handle);
}
注意:您应FindWindow
使用表单的类而不是名称,因为启动屏幕表单有时没有标题甚至控件箱。使用Spy ++深入挖掘。
在启动时使用FindWindow
。我认为这就是你想要做的事情 - 在加载主表单的同时将闪屏放在前面。
答案 1 :(得分:27)
我认为这是更好的解决方案,因为它可以从最小化状态恢复:
public static class WindowHelper
{
public static void BringProcessToFront(Process process)
{
IntPtr handle = process.MainWindowHandle;
if (IsIconic(handle))
{
ShowWindow(handle, SW_RESTORE);
}
SetForegroundWindow(handle);
}
const int SW_RESTORE = 9;
[System.Runtime.InteropServices.DllImport("User32.dll")]
private static extern bool SetForegroundWindow(IntPtr handle);
[System.Runtime.InteropServices.DllImport("User32.dll")]
private static extern bool ShowWindow(IntPtr handle, int nCmdShow);
[System.Runtime.InteropServices.DllImport("User32.dll")]
private static extern bool IsIconic(IntPtr handle);
}
简单的电话:
WindowHelper.BringProcessToFront(process);
答案 2 :(得分:0)
FindWindow(null, title);
将找到与查询匹配的第一个窗口。如果另一个窗口使用相同的标题,这可能会导致意外行为。
虽然这种情况发生的可能性似乎很少或不可能(单实例应用),但这很容易发生。例如,Windows资源管理器使用所选目录的名称作为窗口标题(尽管不可见)。现在,如果窗口标题是常用术语或与应用程序目录的名称匹配,则这可能是个问题。