2010-02-23 18 views
28

Questo è quello che ho finora:modo corretto (NET) per passare l'attivo a un'altra applicazione

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 

Ha due problemi.

  1. Alcune persone mi hanno detto che SwitchToThisWindow è privato.
  2. Se l'applicazione B viene ridotta a icona, questa funzione non riesce automaticamente dal punto di vista dell'utente.

Quindi qual è il modo giusto per farlo?

risposta

27

Ottenere l'handle della finestra (hwnd), e quindi utilizzare questa funzione user32.dll: dichiarazione

VB.net:

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

C# dichiarazione:

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

Una considerazione è che questo non funzionerà se la finestra è ridotta a icona, quindi ho scritto il seguente metodo che gestisce anche questo caso. Ecco il codice C#, dovrebbe essere abbastanza semplice per migrare a 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); 
    } 
} 

Utilizzando tale codice, sarebbe più semplice impostazione delle variabili di processo adeguate e chiamando BringMainWindowToFront("processName");

+0

Perché dichiararlo come numero intero anziché IntPtr? –

+0

Non sembra funzionare. Puoi mostrarmi come usarlo in combinazione con il codice nella domanda originale? –

+0

Ricevo uno zero per il valore di ritorno di SetActiveWindow, che indica un errore. Ma sto ottenendo anche 0 per GetLastWin32Error, che indica il successo. Qualche idea su dove guardare dopo? –

32

C'è un altro modo, che utilizza il non noto API UI Automation:

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

La maggior parte delle volte funziona se è possibile passare a quella finestra. Esistono molte limitazioni in Windows (sicurezza, controllo dell'account utente, configurazione specifica, ecc.) Che possono impedire di modificare l'attenzione dell'utente finale.

+0

Questo dovrebbe essere element! = Null – trampster

+0

Grazie, l'ho corretto :) –

+0

+1 Per evidenziare una tecnica poco conosciuta. Molto bello e grazie per aver ampliato le mie conoscenze. – Basic

1

Importazioni:

Imports System.Runtime.InteropServices 

mettere questo in un modulo

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

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

2

Creare una nuova classe nel progetto e copiare e incollare il codice riportato di seguito.

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

    } 
} 

Ora copia-incolla il codice seguente nell'area richiesta.

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

Qui si chiama la funzione per mettere a fuoco l'altra finestra dell'applicazione.

2

In VB.Net, è possibile utilizzare la funzione AppActivate.

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