2010-02-23 9 views
28

Esto es lo que tengo hasta ahora:manera correcta (en .NET) para cambiar el foco a otra aplicación

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 

Tiene dos problemas.

  1. Algunas personas me han dicho que SwitchToThisWindow está privado.
  2. Si la aplicación B se minimiza, esta función falla silenciosamente desde la perspectiva del usuario.

¿Cuál es la forma correcta de hacerlo?

Respuesta

27

Obtener el identificador de ventana (hWnd), y luego utilizar esta función user32.dll: declaración

VB.net:

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

C# declaración:

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

Una consideración es que esto no funcionará si la ventana está minimizada, entonces he escrito el siguiente método que también maneja este caso. Aquí está el código C#, debería ser bastante sencillo migrar esto 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); 
    } 
} 

El uso de ese código, sería tan simple como el establecimiento de las variables de proceso adecuadas y llamando BringMainWindowToFront("processName");

+0

¿Por qué se declaran como entero en lugar de IntPtr? –

+0

Parece que no funciona. ¿Puede mostrarme cómo usarlo junto con el código en la pregunta original? –

+0

Obtengo un cero para el valor de retorno de SetActiveWindow, que indica un error. Pero también obtengo 0 para GetLastWin32Error, lo que indica éxito. ¿Alguna idea de dónde mirar después? –

32

Hay otra manera, que utiliza la no muy conocida API de UI Automation:

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

La mayoría de las veces, esto funcionará si es posible cambiar a esa ventana. Existen muchas limitaciones en Windows (seguridad, UAC, configuración específica, etc.) que pueden impedirle cambiar el enfoque del usuario final.

+0

Ese debería ser el elemento! = Nulo – trampster

+0

Gracias, lo he corregido :) –

+0

+1 Para resaltar una técnica poco conocida. Muy lindo y gracias por ampliar mi conocimiento. – Basic

1

Importaciones:

Imports System.Runtime.InteropServices 

poner esto en un módulo

<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 

Uso:

FocusWindow("Notepad") 

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

2

Cree una nueva clase en su proyecto y copie y pegue el código siguiente en ella.

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

    } 
} 

Ahora copie y pegue el siguiente código en su área solicitada.

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

Aquí está llamando a la función para llevar el foco a la ventana de la otra aplicación.

2

En VB.Net, puede usar la función AppActivate.

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