如何聚焦外窗?

Jud*_*red 16 .net c# focus

我有一个应用程序,一次只能打开一个自己的实例.为了强制执行此操作,我使用以下代码:

        System.Diagnostics.Process[] myProcesses = System.Diagnostics.Process.GetProcesses();
        System.Diagnostics.Process me = System.Diagnostics.Process.GetCurrentProcess();
        foreach (System.Diagnostics.Process p in myProcesses)
        {
            if (p.ProcessName == me.ProcessName)
                if (p.Id != me.Id)
                {
                    //if already running, abort this copy.
                    return;
                }
        }
        //launch the application.
        //...
Run Code Online (Sandbox Code Playgroud)

它工作正常.我还希望它能够集中已经运行的副本的形式.也就是说,在返回之前,我想将此应用程序的其他实例置于前台.

我怎么做?

Re:SetForeGroundWindow:

SetForeGroundWindow工作,到一点:

    [System.Runtime.InteropServices.DllImport("user32.dll")]
    public static extern bool SetForegroundWindow(IntPtr hWnd); 

    //...
                if (p.Id != me.Id)
                {
                    //if already running, focus it, and then abort this copy.
                    SetForegroundWindow(p.MainWindowHandle);
                    return;
                }
    //...
Run Code Online (Sandbox Code Playgroud)

如果窗口没有最小化,这会将窗口置于前台.真棒.但是,如果窗口IS最小化,它将保持最小化.

它需要取消最小化.

通过SwitchToThisWindow解决方案(Works!):

    [System.Runtime.InteropServices.DllImport("user32.dll")]
    public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);

    [STAThread]
    static void Main()
    {
        System.Diagnostics.Process me = System.Diagnostics.Process.GetCurrentProcess();
        System.Diagnostics.Process[] myProcesses = System.Diagnostics.Process.GetProcessesByName(me.ProcessName);
        foreach (System.Diagnostics.Process p in myProcesses)
        {
            if (p.Id != me.Id)
            {
                SwitchToThisWindow(p.MainWindowHandle, true);
                return;
            }
        }
        //now go ahead and start our application ;-)
Run Code Online (Sandbox Code Playgroud)

sco*_*ttm 10

我有同样的问题,SwitchToThisWindow()对我来说效果最好.唯一的限制是您必须安装XP sp1.我玩SetForegroundWindow,ShowWindow,他们都有问题拉窗口进入视图.

  • 但请注意,链接的 MSDN 页面上写着“[此功能不适用于一般用途。它可能会在 Windows 的后续版本中更改或不可用。]” (2认同)

Nig*_*ist 6

C# 相当于 Tom Juergens 的回答。对我来说就像一种魅力。

private const  int SW_SHOWNORMAL = 1;

[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool ShowWindow(IntPtr hwnd, int nCmdShow);

[DllImport("user32.dll", SetLastError = true)]
private static extern bool SetForegroundWindow(IntPtr hwnd);

public void SetForeground()
{
    Process[] processes = Process.GetProcessesByName("process name");

    foreach (Process p in processes) {
        ShowWindow(p.MainWindowHandle, SW_SHOWNORMAL);
        SetForegroundWindow(p.MainWindowHandle);
    }
}
Run Code Online (Sandbox Code Playgroud)


Tom*_*ens 5

与 OP 相同,我发现SetForegroundWindow当窗口最小化时,仅靠它是不够的。由于我不想使用SwitchToThisWindow,我选择ShowWindowSetForegroundWindow

对我来说效果很好!

private const SW_SHOWNORMAL = 1

<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Function ShowWindow(ByVal hwnd As IntPtr, ByVal nCmdShow As integer) As Boolean
End Function

<DllImport("user32.dll", SetLastError:=True)> _
Private Function SetForegroundWindow(ByVal hwnd As IntPtr) As Boolean
End Function

Sub SetForeground()
    Dim processes As Process() = Process.GetProcessesByName("myprocess")

    For Each p as Process in processes
        ShowWindow(p.MainWindowHandle, SW_SHOWNORMAL)
        SetForegroundWindow(p.MainWindowHandle)
    Next
End Sub
Run Code Online (Sandbox Code Playgroud)