2010-01-07 17 views

Respuesta

79

así:

private void MyForm_FormClosing(object sender, FormClosingEventArgs e) 
{ 
    if (e.CloseReason == CloseReason.UserClosing) 
    { 
     e.Cancel = true; 
     Hide(); 
    } 
} 

(a través de Tim Huffman)

+0

muchas gracias a ambos. – iTEgg

+0

¿cómo vuelvo a activar e.cancel = false? para que pueda cerrar el formulario más tarde? – iTEgg

+0

Creo que tendré que agregar una bandera que me permita ahora si quiero cerrarla de verdad o no. – iTEgg

8

De MSDN:

Para cancelar el cierre de un formulario, establezca la propiedad Cancel del FormClosingEventArgs pasado a su controlador de eventos para true.

Así que cancele y oculte.

3

Tenga en cuenta que al hacer esto (varias respuestas se han publicado), que también tiene que encontrar una manera de permitir que el usuario cierre el formulario cuando realmente quieren hacerlo Esto realmente se convierte en un problema si el usuario intenta apagar la máquina cuando la aplicación se está ejecutando, porque (al menos en algunos sistemas operativos) esto impedirá que el sistema operativo se cierre correctamente o de manera eficiente.

La forma en que resolví esto fue verificar el seguimiento de la pila: hay diferencias entre cuando el usuario intenta hacer clic en X cuando el sistema intenta finalizar la aplicación como preparación para el apagado.

private void Form1_FormClosing(object sender, FormClosingEventArgs e) 
{ 
    StackTrace trace = new StackTrace(); 
    StackFrame frame; 
    bool bFoundExitCommand = false; 
    for (int i = 0; i < trace.FrameCount; i++) 
    { 
     frame = trace.GetFrame(i); 
     string methodName = frame.GetMethod().Name; 
     if (methodName == "miExit_Click") 
     { 
      bFoundExitCommand = true; 
      Log("FormClosing: Found Exit Command ({0}) - will allow exit", LogUtilityLevel.Debug3, methodName); 
     } 
     if (methodName == "PeekMessage") 
     { 
      bFoundExitCommand = true; 
      Log("FormClosing: Found System Shutdown ({0}) - will allow exit", LogUtilityLevel.Debug3, methodName); 
     } 
     Log("FormClosing: frame.GetMethod().Name = {0}", LogUtilityLevel.Debug4, methodName); 
    } 
    if (!bFoundExitCommand) 
    { 
     e.Cancel = true; 
     this.Visible = false; 
    } 
    else 
    { 
     this.Visible = false; 
    } 
} 
+0

completamente de acuerdo con lo que ha dicho. – Alex

+0

im hablando de su comentario anterior, no el último. sí, aunque el código anterior funciona en mi formulario hijo. pero debido al e.Cancelar, ¡ya no puedo cerrar el formulario principal! ¿alguna pista? – iTEgg

+0

para que el código anterior funcione, necesito agregar espacio de nombres para StackTrace. por favor, ayuda indicando el espacio de nombres. – iTEgg

2

Este es el comportamiento de las formas modales. Cuando utiliza form.ShowDialog(), es que pregunta para este comportamiento. La razón de esto es que form.ShowDialog no regresa hasta que el formulario está oculto o destruido. Entonces, cuando el formulario está oculto, la bomba dentro de la forma. ShowDialog lo destruye para que pueda regresar.

Si desea mostrar y ocultar un formulario, a continuación, usted debe utilizar el modelo de diálogo no modal http://msdn.microsoft.com/en-us/library/39wcs2dh(VS.80).aspx

form.Show() vuelve inmediatamente, puede mostrar y ocultar esta ventana todo lo que quieren y que no será destruido hasta lo destruyes explícitamente

Cuando utiliza formularios no modales que no son hijos de un formulario modal, entonces también necesita ejecutar un mensaje de bomba usando Application.Run o Application.DoEvents en un bucle. Si el hilo que crea un formulario sale, entonces el formulario será destruido. Si ese hilo no ejecuta una bomba, las formas que posee no responderán.

Editar: esto suena como el tipo de cosa que el ApplicationContext está diseñado para resolver. http://msdn.microsoft.com/en-us/library/system.windows.forms.applicationcontext.aspx

Básicamente, se derive una clase de Application Context, pasar a una instancia de Application Context como argumento para Application.Run()

// Create the MyApplicationContext, that derives from ApplicationContext, 
// that manages when the application should exit. 

MyApplicationContext context = new MyApplicationContext(); 

// Run the application with the specific context. 
Application.Run(context); 

su contexto de aplicación tendrá que saber cuándo está bien para salir de la aplicación y al tener la formulario (s) ocultos no deben salir de la aplicación. Cuando es hora de que la aplicación salga.El contexto o formulario de su aplicación puede llamar al método ExitThread() del contexto de la aplicación para finalizar el ciclo del mensaje. En ese punto regresará Application.Run().

Sin saber más sobre la jerarquía de sus formularios y sus reglas para decidir cuándo ocultar formularios y cuándo salir, es imposible ser más específico.

+0

podría extender en Application.doevents, por favor? Creo que lo necesito. añadiendo e.Cancel = false; en forma parental, el cierre tampoco funcionó. – iTEgg

+0

¿Es esta tu única forma? ¿tu único hilo? –

+0

lo siento, no estaba claro. la aplicación se cierra cuando hago clic en la X. pero Application.Exit(); no funciona – iTEgg

51

He comentado en una respuesta anterior, pero pensé en proporcionar la mía. En base a su pregunta a este código es similar a la respuesta superior, pero añade la característica de otra menciona:

private void Form1_FormClosing(object sender, FormClosingEventArgs e) 
{ 
    if (e.CloseReason == CloseReason.UserClosing) 
    { 
     e.Cancel = true; 
     Hide(); 
    } 
} 

Si el usuario es simplemente golpeando el X en la ventana, la forma oculta; en todo caso, como el Administrador de tareas, Application.Exit(), o cierre de Windows, el formulario está cerrado correctamente, ya que se ejecutará la instrucción return.

+2

¡Tu uso de e.CloseReason me salvó! ¡buena respuesta! –

4

Si desea utilizar el método de mostrar/ocultar De hecho, he hecho esto a mí mismo por una estructura de menú de un juego que he hecho recientemente ... Esto es cómo lo hice:

mismo crea un botón y por lo que le gustaría hacer, por ejemplo, un botón "Siguiente" y unir el siguiente código a su programa. Para un botón al lado en este ejemplo el código sería:

btnNext.Enabled = true; //This enabled the button obviously 
this.Hide(); //Here is where the hiding of the form will happen when the button is clicked 
Form newForm = new newForm(); //This creates a new instance object for the new form 
CurrentForm.Hide(); //This hides the current form where you placed the button. 

Aquí hay un fragmento del código que utilicé en mi juego para ayudarle a entender lo que estoy tratando de explicar:

private void btnInst_Click(object sender, EventArgs e) 
    { 
     btnInst.Enabled = true; //Enables the button to work 
     this.Hide(); // Hides the current form 
     Form Instructions = new Instructions(); //Instantiates a new instance form object 
     Instructions.Show(); //Shows the instance form created above 
    } 

Entonces, hay un método mostrar/esconder algunas líneas de código, en lugar de hacer una pieza masiva de código para una tarea tan simple. Espero que esto ayude a resolver su problema.

1

Basado en otra respuesta, se puede poner en el código del formulario:

protected override void OnFormClosing(FormClosingEventArgs e) 
    { 
     base.OnFormClosing(e); 
     if (e.CloseReason == CloseReason.UserClosing) 
     { 
      e.Cancel = true; 
      Hide(); 
     } 
    } 

Se prefiere la anulación: MSDN "El método OnFormClosing también permite que las clases derivadas controlen el evento sin asociar un delegado Esto es. la técnica preferida para manejar el evento en una clase derivada. "

Cuestiones relacionadas