Cómo mostrar forma delante en C#
forms z-order (11)
Gente
Por favor, ¿alguien sabe cómo mostrar un Formulario desde una aplicación que de otra manera sería invisible, y obtener el foco (es decir, aparecer en la parte superior de otras ventanas)? Estoy trabajando en C # .NET 3.5.
Sospecho que he tomado "completamente el enfoque equivocado" ... No hago Application.Run (new TheForm ()) en su lugar (new TheForm ()). ShowModal () ... El formulario es básicamente un diálogo modal, con algunas casillas de verificación; un cuadro de texto, y los botones Aceptar y Cancelar. El usuario marca una casilla de verificación y escribe una descripción (o lo que sea), luego presiona OK, el formulario desaparece y el proceso lee la entrada del usuario desde el Formulario, la desecha y continúa el procesamiento.
Esto funciona, excepto cuando el formulario muestra que no recibe el foco, en cambio, aparece detrás de la aplicación "host", hasta que hace clic en él en la barra de tareas (o lo que sea). Este es el comportamiento más molesto, el cual predigo que causará muchas "llamadas de soporte", y la versión VB6 existente no tiene este problema, por lo que estoy retrocediendo en usabilidad ... y los usuarios no aceptarán eso (y ni deberían ellos).
Entonces ... estoy empezando a pensar que necesito repensar todo el shebang ... Debería mostrar el formulario al frente, como una "aplicación normal" y adjuntar el resto del proceso al evento de clic con el botón clic. Debería funcionar, pero eso llevará un tiempo que no tengo (ya he superado el tiempo / presupuesto) ... así que primero tengo que intentar que el enfoque actual funcione ... incluso con rapidez y ... métodos sucios
Entonces, ¿alguien sabe cómo "forzar" un formulario .NET 3.5 (por medios justos o aves) para obtener el enfoque? Estoy pensando en las llamadas API "mágicas" de windows (lo sé
Twilight Zone: esto solo parece ser un problema en el trabajo, estamos usando Visual Studio 2008 en Windows XP SP3 ... No pude reproducir el problema con un SSCCE (ver más abajo) en casa en Visual C # 2008 en Vista Ulimate ... Esto funciona bien. Eh WTF?
Además, juraría que ayer en el trabajo mostraba la forma cuando ejecuté el EXE, pero no cuando F5''ed (o Ctrl-F5''ed) directamente del IDE (que acabo de soportar) ... En casa la forma se muestra bien de cualquier manera. Totalmente confusterpating!
Puede o no ser relevante, pero Visual Studio se estrelló y se quemó esta mañana cuando el proyecto se estaba ejecutando en modo de depuración y editando el código "sobre la marcha" ... se atascó lo que presumí fue un bucle infinito de error mensajes El mensaje de error era algo acerca de "no se puede depurar este proyecto porque no es el proyecto actual, o algo así ... Así que simplemente lo eliminé con el explorador de procesos. Comenzó de nuevo bien, e incluso ofreció recuperar el" perdido "Archivo, una oferta que acepté.
using System;
using System.Windows.Forms;
namespace ShowFormOnTop {
static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//Application.Run(new Form1());
Form1 frm = new Form1();
frm.ShowDialog();
}
}
}
Antecedentes: estoy portando una implementación VB6 existente a .NET ... Es un "complemento" para una aplicación GIS de "cliente" llamada MapInfo . El cliente existente "trabajó de manera invisible" y mis instrucciones son "para mantener la nueva versión lo más cerca posible de la versión anterior", que funciona lo suficientemente bien (después de años de parches); se acaba de escribir en un idioma no compatible, por lo que necesitamos portarlo.
Acerca de mí: soy prácticamente un novato de C # y .NET en general, aunque tengo un certificado de borrado de fondos, he sido programador profesional durante 10 años; Así que tipo de "saber algunas cosas".
Cualquier información sería bienvenida ... y gracias a todos por tomarse el tiempo de leer hasta aquí. La coherencia no es (aparentemente) mi fuerte.
Aclamaciones. Keith.
- Usted dijo que funciona bien cuando usa
Application.Run
. ¿Por qué no quieres usarApplication.Run
, entonces? - ¿Ha intentado llamar a
BringToFront()
desdeOnLoad
oOnShown
?
Esta es la solución final que escribí después de 20 intentos diferentes:
/* A workaround for showing a form on the foreground and with focus,
* even if it is run by a process other than the main one
*/
public static void ShowInForeground(this Form form, bool showDialog = false)
{
if (showDialog)
{
//it''s an hack, thanks to http://.com/a/1463479/505893
form.WindowState = FormWindowState.Minimized;
form.Shown += delegate(Object sender, EventArgs e) {
((Form)sender).WindowState = FormWindowState.Normal;
};
form.ShowDialog();
}
else
{
//it''s an hack, thanks to http://.com/a/11941579/505893
form.WindowState = FormWindowState.Minimized;
form.Show();
form.WindowState = FormWindowState.Normal;
//set focus on the first control
form.SelectNextControl(form.ActiveControl, true, true, true, true);
}
}
Esto es lo que uso para traer un formulario abierto que es parte de mi solicitud al frente. Incluso puedes usarlo con un botón. Pero el formulario debe estar abierto o la aplicación se romperá.
"YourOpenForm" tiene que ser el nombre de su formulario en la ventana de propiedades.
private void button1_Click(object sender, EventArgs e)
{
Application.OpenForms["YourOpenForm"].BringToFront();
}
¡Buena suerte!
Esto hizo el trabajo perfectamente:
formxx.WindowState = FormWindowState.Normal;
formxx.BringToFront();
formxx.Topmost=true;
formxx.Focus();
Hay una sobrecarga de Form.ShowDialog () que toma un objeto IWin32Window. Ese IWin32Window se trata como la ventana principal para el formulario.
Si tiene la ventana principal como System.Windows.Forms.Form, adelante y solo pásela. De lo contrario, obtenga el HWND (tal vez por P / Invoking to FindWindow ()), y cree una implementación de IWin32Window ficticia que solo devuelva el HWND ( Más detalles ).
He hackeado esto desde una aplicación en la que he estado trabajando. Tenemos una gran aplicación que carga una serie de módulos escritos por diferentes equipos. Hemos escrito uno de estos módulos, y necesitamos tener un cuadro de diálogo de inicio de sesión abierto durante esta inicialización. Se estableció en ''.TopMost = true'', pero eso no funcionó.
Utiliza el WindowsFormsSynchronizationContext para abrir un cuadro de diálogo y luego recuperar el resultado del cuadro de diálogo.
Rara vez hago codificación GUI, y sospecho que esto puede ser excesivo, pero podría ayudar a alguien si se atasca. Tuve problemas para entender cómo se pasa el estado a SendOrPostCallback, ya que todos los ejemplos que encontré no lo usaron.
También se ha tomado de una aplicación que funciona, pero he eliminado varios bits de código y he cambiado algunos de los detalles. Disculpas si no se compila.
public bool Dummy()
{
// create the login dialog
DummyDialogForm myDialog = new DummyDialogForm();
// How we show it depends on where we are. We might be in the main thread, or in a background thread
// (There may be better ways of doing this??)
if (SynchronizationContext.Current == null)
{
// We are in the main thread. Just display the dialog
DialogResult result = myDialog.ShowDialog();
return result == DialogResult.OK;
}
else
{
// Get the window handle of the main window of the calling process
IntPtr windowHandle = Process.GetCurrentProcess().MainWindowHandle;
if (windowHandle == IntPtr.Zero)
{
// No window displayed yet
DialogResult result = myDialog.ShowDialog();
return result == DialogResult.OK;
}
else
{
// Parent window exists on separate thread
// We want the dialog box to appear in front of the main window in the calling program
// We would like to be able to do ''myDialog.ShowDialog(windowHandleWrapper)'', but that means doing something on the UI thread
object resultState = null;
WindowsFormsSynchronizationContext.Current.Send(
new SendOrPostCallback(delegate(object state) { resultState = myDialog.ShowDialog(); }), resultState);
if (resultState is DialogResult)
{
DialogResult result = (DialogResult) resultState;
return result == DialogResult.OK;
}
else
return false;
}
}
}
Parece que el comportamiento es específico de XP ... Por lo tanto, no puedo reproducirlo en Vista.
http://www.gamedev.net/community/forums/topic.asp?topic_id=218484
EDIT: PS: Ya pasó la hora de irme a la cama (2 AM ;-).
Gracias a todos por sus respuestas ... hay algunas "cosas" que puedo intentar ... incluso podría ir a la oficina mañana para probarlas ... Sí, sí ... una vez tuve una vida, pero la cambié Para un corte de pelo y un trabajo ;-)
Saludos a todos. Keith.
Simplemente
yourForm.TopMost = true;
Tengo un código en el proyecto.
private static extern bool SetForegroundWindow(
IntPtr hWnd);
public static void ShowToFront(Form form)
{
FormWindowState oldState = form.WindowState;
form.WindowState = FormWindowState.Minimized;
form.Show();
form.Activate();
form.TopLevel = false;
form.TopLevel = true;
form.SelectNextControl(form.ActiveControl, true, true, true, true);
SetForegroundWindow(form.Handle);
form.Focus();
form.WindowState = oldState;
}
Activate()
trabajó para mí también.
BringToFront()
no hizo nada en este caso, no sé por qué.
Form.Activate()
trabajó en mi caso.