c# - sirve - textbox1 focus()
¿Cómo enfoco una ventana extranjera? (6)
Tengo una aplicación que solo puede tener una instancia de sí mismo abierta a la vez. Para hacer cumplir esto, uso este código:
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.
//...
Funciona bien. También me gustaría que sea capaz de enfocar la forma de la copia que ya está ejecutándose. Es decir, antes de regresar, quiero poner la otra instancia de esta aplicación en primer plano.
¿Cómo puedo hacer eso?
Re: SetForeGroundWindow:
SetForeGroundWindow funciona, hasta cierto punto:
[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;
}
//...
Esto trae la ventana al primer plano si no se minimiza. Increíble. Sin embargo, si la ventana ES minimizada, permanece minimizada.
Necesita des-minimizar.
Solución a través de 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 ;-)
¿Puedes tomar la propiedad MainWindowHandle del objeto Process y enviarle un mensaje WM_USER que puedas interpretar como "alguna otra instancia quiere llevarme al frente".
Creo que querrás usar SetForegroundWindow
Nota lateral completa ...
Puedes usar
Process.GetProcessesByName(me.ProcessName)
en lugar de recorrer todos los procesos que se ejecutan en el sistema ...
ACTUALIZAR
Reglas de invocación para este tipo de cosas ...
Tuve el mismo problema y SwitchToThisWindow () funcionó mejor para mí. La única limitación es que debe tener XP sp1 instalado. Jugué con SetForegroundWindow, ShowWindow, y ambos tuvieron problemas para ver la ventana.
Igual que OP, descubrí que SetForegroundWindow
sí solo no era suficiente cuando se minimizaba la ventana. Como no quería usar SwitchToThisWindow
, elegí ShowWindow
seguido de SetForegroundWindow
.
¡Me funciona bien!
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
C # equivalente a la respuesta de Tom Juergens. Funciona como un encanto para mí.
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);
}
}