2011-12-14 12 views
6

Tengo estas dos líneas en mi principal, pero no puedo cerrar el asa al final. Estoy tratando de obtener un control para llorar las ventanas de Windows y cerrarlo después de eso, pero no funciona. Y tengo todo lo relevante que necesito.¿Por qué no puedo cerrar el identificador de ventana en mi código?

#include <windows.h> 
#include <stdio.h> 

en el principal

HWND wh = FindWindow("Minesweeper", "Minesweeper"); 
CloseHandle (wh); 

Por printf de wh veo el valor es idéntico a este criado en Spy ++.

Y estoy consiguiendo el error

"dirección de Excepción: 0x7c90e4ff"

¿Qué me falta?

BTW: Manecilla de cierre de un proceso funciona bien si cambio las dos líneas de arriba.

+0

¿Está 'wh' null cuando llamas a CloseHandle? –

Respuesta

14

Aquí hay un par de problemas básicos. En primer lugar, no llame al CloseHandle con un asa de ventana. No es ese tipo de control. Utiliza CloseHandle cuando tiene un HANDLE pero un HWND no es un HANDLE. Si desea destruir un identificador de ventana, debe llamar al DestroyWindow.

Sin embargo, los documentation para DestroyWindow estados:

Un hilo no puede utilizar DestroyWindow para destruir una ventana creada por un subproceso diferente.

Así que no puedes hacer eso tampoco.

Lo que puede hacer es enviar un mensaje WM_CLOSE a la ventana. Eso debería ser suficiente para persuadirlo de cerrar con gracia.

Tenga en cuenta que WM_CLOSE se envía en lugar de publicado. Esto se puede discernir con esta línea desde documentation:

Una ventana recibe este mensaje a través de su función WindowProc.

actualización

John Knoller señala que estoy malinterpretando la documentación de Windows que no fue escrito para cubrir la situación en la que una aplicación intenta cerrar otra aplicación.

consejo de John es:

De hecho, es más prudente para enviar WM_CLOSE a otro proceso utilizando PostMessage o SendNotifyMessage. Si usa SendMessage, se quedará bloqueado si el proceso no está generando mensajes. Es incluso mejor usar WM_SYSCOMMAND/SCCLOSE que es básicamente lo mismo que hacer clic en el botón de cerrar de la ventana.

+3

Estás leyendo mal la última línea. De hecho, es más inteligente enviar WM_CLOSE a otro proceso utilizando PostMessage o SendNotifyMessage. Si usa SendMessage, se quedará bloqueado si el proceso no está generando mensajes. Es incluso mejor usar WM_SYSCOMMAND/SCCLOSE, que es básicamente lo mismo que hacer clic en el botón de cerrar la leyenda de la ventana. –

+0

@John OK, lo actualizaré. Pero para que quede claro, y por interés, ¿cómo entrega Windows el mensaje sin quedarse atascado? –

+1

te refieres al hacer clic en el mensaje de cerrar el botón? eso es solo un mensaje WM_NCMOUSECLICK 'publicado' en la cola de mensajes de la secuencia. Los eventos de entrada de usuario siempre se colocan en la cola del subproceso utilizando un mecanismo similar a un post. (en realidad no es mensaje de correo). Solo se convierte en WM_SYSCOMMAND/NCCLOSE cuando el hilo llama a GetMessage()/DispatchMessage(). –

6

¿No uso CloseHandle, CloseWindow o DestroyWindow. Envíe un mensaje WM_CLOSE a la ventana usando SendMessage.

+0

¿Por qué no publicas 'WM_CLOSE'? – Deanna

+0

@Deanna PostMessage también está bien. La razón por la que generalmente uso SendMessage es que espera que el procedimiento de ventana de la ventana de destino maneje el mensaje. De modo que después de que SendMessage regrese, puede verificar inmediatamente si la ventana de destino está realmente cerrada. – kol

+0

¿No es solo una alternativa asquerosa y equivalente a CloseWindow()? – Lundin

4

Los controladores de Windows (HWND) no son controladores del sistema (MANIJAS). CloseHandle() es para objetos del sistema.

Considera PostMessage(wh, WM_CLOSE, 0, 0);, como this article describe.

+0

¡Gracias por un ejemplo real! Olvidé qué parámetros pasar a 'PostMessage()'. – ebyrob

Cuestiones relacionadas