将焦点切换到另一个应用程序的正确方法(在 .NET 中)

发布于 2024-08-22 12:22:38 字数 386 浏览 5 评论 0原文

这就是我到目前为止所遇到的:

Dim bProcess = Process.GetProcessesByName("By").FirstOrDefault
If bProcess IsNot Nothing Then
    SwitchToThisWindow(bProcess.MainWindowHandle, True)
Else
    Process.Start("C:\Program Files\B\B.exe")
End If

它有两个问题。

  1. 有些人告诉我 SwitchToThisWindow 已被弃用。
  2. 如果应用程序 B 最小化,则从用户的角度来看,此功能会默默地失败。

那么这样做的正确方法是什么?

This is what I have so far:

Dim bProcess = Process.GetProcessesByName("By").FirstOrDefault
If bProcess IsNot Nothing Then
    SwitchToThisWindow(bProcess.MainWindowHandle, True)
Else
    Process.Start("C:\Program Files\B\B.exe")
End If

It has two problems.

  1. Some people have told me that SwitchToThisWindow is deprecated.
  2. If application B is minimized, this function silently fails from the user's perspective.

So what's the right way to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

浮萍、无处依 2024-08-29 12:22:38

获取窗口句柄(hwnd),然后使用这个 user32.dll 函数:

VB.net 声明:

Declare Function SetForegroundWindow Lib "user32.dll" (ByVal hwnd As Integer) As Integer 

C# 声明:

[DllImport("user32.dll")] public static extern int SetForegroundWindow(int hwnd) 

一个考虑因素是,如果窗口最小化,这将不起作用,因此我编写了以下也处理窗口句柄的方法这个案例。这是 C# 代码,将其迁移到 VB 应该相当简单。

[System.Runtime.InteropServices.DllImport("user32.dll")]
[return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)]
private static extern bool ShowWindow(IntPtr hWnd, ShowWindowEnum flags);

[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern int SetForegroundWindow(IntPtr hwnd);

private enum ShowWindowEnum
{
    Hide = 0,
    ShowNormal = 1, ShowMinimized = 2, ShowMaximized = 3,
    Maximize = 3, ShowNormalNoActivate = 4, Show = 5,
    Minimize = 6, ShowMinNoActivate = 7, ShowNoActivate = 8,
    Restore = 9, ShowDefault = 10, ForceMinimized = 11
};

public void BringMainWindowToFront(string processName)
{
    // get the process
    Process bProcess = Process.GetProcessesByName(processName).FirstOrDefault();

    // check if the process is running
    if (bProcess != null)
    {
        // check if the window is hidden / minimized
        if (bProcess.MainWindowHandle == IntPtr.Zero)
        {
            // the window is hidden so try to restore it before setting focus.
            ShowWindow(bProcess.Handle, ShowWindowEnum.Restore);
        }

        // set user the focus to the window
        SetForegroundWindow(bProcess.MainWindowHandle);
    }
    else
    {
        // the process is not running, so start it
        Process.Start(processName);
    }
}

使用该代码,就像设置适当的流程变量并调用BringMainWindowToFront(“processName”);一样简单

Get the window handle (hwnd), and then use this user32.dll function:

VB.net declaration:

Declare Function SetForegroundWindow Lib "user32.dll" (ByVal hwnd As Integer) As Integer 

C# declaration:

[DllImport("user32.dll")] public static extern int SetForegroundWindow(int hwnd) 

One consideration is that this will not work if the window is minimized, so I've written the following method which also handles this case. Here is the C# code, it should be fairly straight forward to migrate this to VB.

[System.Runtime.InteropServices.DllImport("user32.dll")]
[return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)]
private static extern bool ShowWindow(IntPtr hWnd, ShowWindowEnum flags);

[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern int SetForegroundWindow(IntPtr hwnd);

private enum ShowWindowEnum
{
    Hide = 0,
    ShowNormal = 1, ShowMinimized = 2, ShowMaximized = 3,
    Maximize = 3, ShowNormalNoActivate = 4, Show = 5,
    Minimize = 6, ShowMinNoActivate = 7, ShowNoActivate = 8,
    Restore = 9, ShowDefault = 10, ForceMinimized = 11
};

public void BringMainWindowToFront(string processName)
{
    // get the process
    Process bProcess = Process.GetProcessesByName(processName).FirstOrDefault();

    // check if the process is running
    if (bProcess != null)
    {
        // check if the window is hidden / minimized
        if (bProcess.MainWindowHandle == IntPtr.Zero)
        {
            // the window is hidden so try to restore it before setting focus.
            ShowWindow(bProcess.Handle, ShowWindowEnum.Restore);
        }

        // set user the focus to the window
        SetForegroundWindow(bProcess.MainWindowHandle);
    }
    else
    {
        // the process is not running, so start it
        Process.Start(processName);
    }
}

Using that code, it would be as simple as setting the appropriate process variables and calling BringMainWindowToFront("processName");

情释 2024-08-29 12:22:38

还有另一种方法,它使用不为人所知的 UI 自动化 API:

AutomationElement element = AutomationElement.FromHandle(process.MainWindowHandle);
if (element != null)
{
    element.SetFocus();
}

大多数情况下,如果可以切换到该窗口,则这将起作用。 Windows 中有很多限制(安全性、UAC、特定配置等),这些限制可能会阻止您改变最终用户的关注点。

There is another way, which uses the not well-known UI Automation API:

AutomationElement element = AutomationElement.FromHandle(process.MainWindowHandle);
if (element != null)
{
    element.SetFocus();
}

Most of the time, this will work if it's possible to switch to that window. There are a lot of limitations in Windows (security, UAC, specific configuration, etc...) that can prevent you to change the end-user focus.

温柔戏命师 2024-08-29 12:22:38

在您的项目中创建一个新类并将以下代码复制粘贴到其中。

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;

namespace MyProject
{
    public class ProcessHelper
    {
        public static void SetFocusToExternalApp(string strProcessName)
        {
            Process[] arrProcesses = Process.GetProcessesByName(strProcessName);
            if (arrProcesses.Length > 0)
            {

                IntPtr ipHwnd = arrProcesses[0].MainWindowHandle;
                Thread.Sleep(100);
                SetForegroundWindow(ipHwnd);

            }
        }

    //API-declaration
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool SetForegroundWindow(IntPtr hWnd);

    }
}

现在将以下代码复制粘贴到您所需的区域。

string procName = Process.GetCurrentProcess().ProcessName;
ProcessHelper.SetFocusToExternalApp(procName);

在这里,您调用该函数将焦点转移到其他应用程序的窗口。

Create a New Class in your project and copy-paste the below code in it.

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;

namespace MyProject
{
    public class ProcessHelper
    {
        public static void SetFocusToExternalApp(string strProcessName)
        {
            Process[] arrProcesses = Process.GetProcessesByName(strProcessName);
            if (arrProcesses.Length > 0)
            {

                IntPtr ipHwnd = arrProcesses[0].MainWindowHandle;
                Thread.Sleep(100);
                SetForegroundWindow(ipHwnd);

            }
        }

    //API-declaration
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool SetForegroundWindow(IntPtr hWnd);

    }
}

Now copy-paste the below code in your required area.

string procName = Process.GetCurrentProcess().ProcessName;
ProcessHelper.SetFocusToExternalApp(procName);

Here you are calling the function to bring focus to the other application's window.

胡大本事 2024-08-29 12:22:38

在 VB.Net 中,您可以使用 AppActivate< /a> 函数。

Dim App As Process() = Process.GetProcessesByName("program.exe")
If App.Length > 0 Then
   AppActivate(App(0).Id)
End If

In VB.Net, you can use the AppActivate function.

Dim App As Process() = Process.GetProcessesByName("program.exe")
If App.Length > 0 Then
   AppActivate(App(0).Id)
End If
长伴 2024-08-29 12:22:38

我使用 SetForegroundWindow 来显示另一个应用程序的窗口。

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

如何给予另一个进程焦点来自 C#?

I used SetForegroundWindow to make the window from another application appear.

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

How can I give another Process focus from C#?

荒芜了季节 2024-08-29 12:22:38

这对我来说工作

[DllImport("user32.dll", SetLastError = true)]
static extern void SwitchToThisWindow(IntPtr hWnd, bool turnOn);
[STAThread]
        static void Main()
        {
            Process bProcess = Process.GetProcessesByName(processnamehere).FirstOrDefault() ;
            if (bProcess != null)
                    {
                        SwitchToThisWindow(bProcess.MainWindowHandle, true);
                    }
                GC.Collect();
        }   

This work for me

[DllImport("user32.dll", SetLastError = true)]
static extern void SwitchToThisWindow(IntPtr hWnd, bool turnOn);
[STAThread]
        static void Main()
        {
            Process bProcess = Process.GetProcessesByName(processnamehere).FirstOrDefault() ;
            if (bProcess != null)
                    {
                        SwitchToThisWindow(bProcess.MainWindowHandle, true);
                    }
                GC.Collect();
        }   
我的痛♀有谁懂 2024-08-29 12:22:38

导入:

Imports System.Runtime.InteropServices

将其放入模块中

<DllImport("user32.dll")> _
Private Function SetForegroundWindow(hWnd As IntPtr) As Boolean
End Function

Public Sub FocusWindow(ByVal ProcessName As String)
    Dim p As System.Diagnostics.Process = System.Diagnostics.Process.GetProcessesByName(ProcessName).FirstOrDefault
    If p IsNot Nothing Then
        SetForegroundWindow(p.MainWindowHandle)
        SendKeys.SendWait("~") ' maximize the application if it's minimized
    End If
End Sub

用法:

FocusWindow("Notepad")

来源: http://www.codeproject.com/Tips/232649/Setting-Focus-on-an-External-application#_ rating

Imports:

Imports System.Runtime.InteropServices

Put this in a Module

<DllImport("user32.dll")> _
Private Function SetForegroundWindow(hWnd As IntPtr) As Boolean
End Function

Public Sub FocusWindow(ByVal ProcessName As String)
    Dim p As System.Diagnostics.Process = System.Diagnostics.Process.GetProcessesByName(ProcessName).FirstOrDefault
    If p IsNot Nothing Then
        SetForegroundWindow(p.MainWindowHandle)
        SendKeys.SendWait("~") ' maximize the application if it's minimized
    End If
End Sub

Usage:

FocusWindow("Notepad")

Source: http://www.codeproject.com/Tips/232649/Setting-Focus-on-an-External-application#_rating

感悟人生的甜 2024-08-29 12:22:38

当我尝试使用从以下代码获取的 exe 以管理员身份运行 SQL Server Management Studio 和 Visual Studio 等应用程序时,以下内容对我有用。

切换帮助

public class ToggleHelper
{
    [System.Runtime.InteropServices.DllImport("user32.dll")]
    [return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)]
    private static extern bool ShowWindow(IntPtr hWnd, EnumForWindow enumVal);

    [System.Runtime.InteropServices.DllImport("user32.dll")]
    private static extern int SetForegroundWindow(IntPtr hwnd);

    private enum EnumForWindow
    {
        Hide = 0,
        ShowNormal = 1, ShowMinimized = 2, ShowMaximized = 3,
        Maximize = 3, ShowNormalNoActivate = 4, Show = 5,
        Minimize = 6, ShowMinNoActivate = 7, ShowNoActivate = 8,
        Restore = 9, ShowDefault = 10, ForceMinimized = 11
    };

    public void SetForeGroundMainWindowHandle(string processName)
    {

        Console.WriteLine("SetForeGroundMainWindowHandle Called - for "+ processName);
        Process p = Process.GetProcessesByName(processName).FirstOrDefault();

        if (p != null)
        {
            Console.WriteLine(p.MainWindowHandle.ToString());
            ShowWindow(p.MainWindowHandle, EnumForWindow.Restore);
            System.Threading.Thread.Sleep(5000);
            ShowWindow(p.MainWindowHandle, EnumForWindow.ShowMaximized);
            //System.Threading.Thread.Sleep(5000);
            SetForegroundWindow(p.MainWindowHandle);
        }
        else
        {
            Process.Start(processName);
        }
    }
}

客户端

class Program
{
    static void Main(string[] args)
    {
        //RUN AS Administrator
        var y = Process.GetProcesses().Where(pr => pr.MainWindowHandle != IntPtr.Zero);
        foreach (Process proc in y)
        {
            Console.WriteLine(proc.ProcessName);
        }

        ToggleHelper t = new ToggleHelper();

        int a = 0;
        while (a <= 1)
        {
            t.SetForeGroundMainWindowHandle("Ssms");
            System.Threading.Thread.Sleep(30000);
            t.SetForeGroundMainWindowHandle("devenv");
            System.Threading.Thread.Sleep(18000);
        }
        Console.ReadLine();
    }
}

Following worked for me, when I tried for applications like SQL Server Management Studio and Visual Studio, running as Administrator, using the exe got from the following code.

Toggle Helper

public class ToggleHelper
{
    [System.Runtime.InteropServices.DllImport("user32.dll")]
    [return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)]
    private static extern bool ShowWindow(IntPtr hWnd, EnumForWindow enumVal);

    [System.Runtime.InteropServices.DllImport("user32.dll")]
    private static extern int SetForegroundWindow(IntPtr hwnd);

    private enum EnumForWindow
    {
        Hide = 0,
        ShowNormal = 1, ShowMinimized = 2, ShowMaximized = 3,
        Maximize = 3, ShowNormalNoActivate = 4, Show = 5,
        Minimize = 6, ShowMinNoActivate = 7, ShowNoActivate = 8,
        Restore = 9, ShowDefault = 10, ForceMinimized = 11
    };

    public void SetForeGroundMainWindowHandle(string processName)
    {

        Console.WriteLine("SetForeGroundMainWindowHandle Called - for "+ processName);
        Process p = Process.GetProcessesByName(processName).FirstOrDefault();

        if (p != null)
        {
            Console.WriteLine(p.MainWindowHandle.ToString());
            ShowWindow(p.MainWindowHandle, EnumForWindow.Restore);
            System.Threading.Thread.Sleep(5000);
            ShowWindow(p.MainWindowHandle, EnumForWindow.ShowMaximized);
            //System.Threading.Thread.Sleep(5000);
            SetForegroundWindow(p.MainWindowHandle);
        }
        else
        {
            Process.Start(processName);
        }
    }
}

Client

class Program
{
    static void Main(string[] args)
    {
        //RUN AS Administrator
        var y = Process.GetProcesses().Where(pr => pr.MainWindowHandle != IntPtr.Zero);
        foreach (Process proc in y)
        {
            Console.WriteLine(proc.ProcessName);
        }

        ToggleHelper t = new ToggleHelper();

        int a = 0;
        while (a <= 1)
        {
            t.SetForeGroundMainWindowHandle("Ssms");
            System.Threading.Thread.Sleep(30000);
            t.SetForeGroundMainWindowHandle("devenv");
            System.Threading.Thread.Sleep(18000);
        }
        Console.ReadLine();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文