Voie correcte (in.NET) pour passer à une autre application

c'est Ce que j'ai jusqu'à présent:

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

Il a deux problèmes.

  1. certains m'ont dit que ce commutateur est déprimé.
  2. si l'application B est minimisée, cette fonction échoue silencieusement du point de vue de l'utilisateur.

Alors, quelle est la bonne façon de le faire?

31
demandé sur caesay 2010-02-23 04:31:27

7 réponses

Obtenir le handle de la fenêtre (hwnd), et ensuite utiliser cette user32.dll fonction:

VB.net déclaration:

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

C# déclaration:

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

une considération est que cela ne fonctionnera pas si la fenêtre est minimisée, donc j'ai écrit la méthode suivante qui gère aussi ce cas. Voici le code C#, il devrait être assez simple de migrer ceci vers 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);
    }
}

en utilisant ce code, il serait aussi simple que de définir le variables de processus et appel BringMainWindowToFront("processName");

32
répondu caesay 2017-12-04 23:24:38

Il y a une autre façon, qui utilise L'API D'automatisation de L'interface utilisateur peu connue:

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

La plupart du temps, cela fonctionnera s'il est possible de passer à cette fenêtre. Il y a beaucoup de limitations dans Windows (Sécurité, UAC, configuration spécifique, etc.)...) qui peut vous empêcher de changer l'accent de l'utilisateur final.

34
répondu Simon Mourier 2010-11-21 09:29:11

J'ai utilisé SetForegroundWindow pour faire apparaître la fenêtre d'une autre application.

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

Comment puis-je me concentrer sur un autre processus à partir de C#?

4
répondu Daniel N 2012-06-19 16:57:29

Créer une Nouvelle Classe dans votre projet et copiez-collez le code ci-dessous.

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);

    }
}

maintenant, copiez-collez le code ci-dessous dans votre zone requise.

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

ici vous appelez la fonction pour attirer l'attention sur la fenêtre de l'autre application.

3
répondu Tijo Tom 2014-08-13 05:12:06

Importations:

Imports System.Runtime.InteropServices

mettez ceci dans un 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

Utilisation:

FocusWindow("Notepad")

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

2
répondu CrazyTim 2013-05-08 03:45:46

Dans VB.Net, vous pouvez utiliser le AppActivate fonction.

Dim App As Process() = Process.GetProcessesByName("program.exe")
If App.Length > 0 Then
   AppActivate(App(0).Id)
End If
2
répondu Snake 2014-10-10 06:01:36

Ce travail pour moi

[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();
        }   
1
répondu Pro Kelin 2018-06-13 06:52:55