Programación General > Visual Basic 6.0 e inferiores
API - WaitMessage
epko:
¿Alguien sabría porqué el WaitMessage de la siguiente situación no funciona?:
Proyecto VB6
Declaro la función:
Private Declare Function WaitMessage Lib "user32" () As Long
Private Declare Function GetQueueStatus Lib "user32" (ByVal fuFlags As Long) As Long
Declaro todas las constantes asociadas a SendMessage y WaitMessage, y entre ellas:
Const QS_SENDMESSAGE = &H40
En el proc Private Sub Form_Load(), pongo:
MsgBox Str(GetQueueStatus(QS_SENDMESSAGE))
'Sigue = WaitMessage
WaitMessage
MsgBox "Ha pasado"
Y el resultado es que aparece el primer MsgBox con cero como contenido de la cola, y directamente, al aceptar ese MsgBox, sale el segundo diciendo que "ha pasado" por el WaitMessage sin que le mandara ningún mensaje, o sea, que se lo ha saltado.
La linea Sigue = WaitMessage puesta activa también produce lo mismo. La variable Sigue la he declarado como Long.
Entiendo que WaitMessage debería producir la suspensión de la ejecución hasta que le llegue un mensaje enviado p. ej. con SendMessage.
¿Alguien sabría qué puede pasar?
Gracias
Nebire:
Tienes un pequeño error de concepto respecto de lo que supones que ocurre
Desde el momento que sale el msgbox, como es una ventana modal, cuando el usuario pulsa el botón para cerrar la ventana modal, acontece en ese momento un mensaje, por tanto ya hay mensajes en la cola y por tanto waitmessage, deja de ceder el control a otros hilos. ...Aparte de los mensajes de mover el ratón (mousemove)...
El problema lo tienes porque tu sólo chequeas si en la cola hay eventos de sendmessage sin procesar, te devuelve 0, es decir no hay mensajes de ese tipo en la cola, pero hay mensajes serán de otro tipo, pero los hay... coloca el mismo código dentro de un evento click de un botón verás como 'z' devuelve diferentes valores del load del formulario... que aparte tiene pendiente un show...
prueba con esto y lo verás tu mismo.
--- Código: Visual Basic --- Private Sub Form_Load() const TodosLosEventos = 191 z = GetQueueStatus(TodosLosEventos) sigue = WaitMessage WaitMessage MsgBox sigue & " Ha pasado " & zEnd Sub
WaitMessage lo puedes poner para recibir un tipo de datos boolean... si te resulta más cómodo.
epko:
Muchas gracias por la respuesta, Nebire.
La cuestión que he puesto es porque estoy buscando la forma de suspender la ejecución de código VB6 en medio de un procedimiento, hasta que se produzca un evento, y consumiendo los menores recursos posibles (procesador, memoria).
Se puede hacer a lo bestia con un bucle que no salga de él hasta que se produzca el evento, pero te comes el procesador aunque le pongas un DoEvents en medio.
Una de las formas alternativas que estoy mirando es esta; un "Esperar a que llegue el mensaje de que ha ocurrido el evento" mediante llamadas a la API, que no cosumen recursos; algo así como la espera de un MsgBox, que suspende la ejecución hasta que el usuario hace algo en el MsgBox, pero en este caso, el "seguir" lo produce un evento que ocurra en nuestro programa o en otro.
La verdad es que me está extrañando que esto no esté más resuelto, tanto a nivel VB6, como a nivel API, con funciones pensadas para ello, o sea un "WaitEvent".
A raiz de tu respuesta, que es cierto, aunque no le lleguen mensajes desde un SendMessage, sí hay mensajes en la cola de otras muchas cosas, se me han ocurrido algunas vías por donde tirar:
1) Filtrar los mensajes en la cola hasta detectar uno procedente de un SendMessage que sea el requerido, lo cual tiene su miga, y sobre todo, ya estamos metiendo bucles...
2) Se me ocurre investigar la función de la API SleepEx, que no me ha dado tiempo a mirarla bien, pero parece que aparte de despertar por tiempo, puede despertar por un par de condiciones que todavía no sé cómo sacarles partido para lo que quiero:
A) An I/O completion callback function is called
B) An asynchronous procedure call (APC) is queued to the thread
Si a alguien se le ocurre algo...
P.D.: Vuelvo a decir que me quedo sorprendido de que esto no esté resuelto... y reitero las gracias
Nebire:
El problema que planteas está resuelto, otra cosa es que tu no veas claramente como se logra.
La respuesta son los eventos. Un evento es precisamente eso, compartimentar código de ejecución...
Y efectivamente se necesita una función callback para 'estudiar' los eventos y cuando suceda el deseado producir el evento.
Dado que tu quieres que no se precesen en resto de eventos mientras no llegue un evento de tipo determinado, debes cerrar en la función de callback el reenvío hacia adelante de todo los eventos.
Te pondré un sencillo ejemplo que puedas calcar y hacer los cambios que precises... si sigues interesado, dame un par de días, que encuentre una hora disponible para realizarlo...
p.d.: también puedes optar por la función SignalObjectAndWait y / ó WaitForSingleObject.
epko:
Me acabo de dar cuenta releyendo tu mensaje, que me ofrecías más ayuda "si sigo interesado". SÍ, sigo MUY interesado y agradecido.
No me quedé parado por mi parte, lo que pasa es que entre que cada uno tiene su nivel..., y que la documentación y ejemplos sobre esto, yo al menos, no la encuentro fácil, pues voy despacio.
De momento, sigo pensando que la función SleepEx puede valer, al menos en parte. De hecho, la instrucción SleepEx(INFINITE, TRUE), creo que suspendería la ejecución adecuadamente en espera de "algo" en la linea de lo que yo planteo. Ahora hay que diseñar el "algo" convenientemente, y quizá con las funciones QueueUserAPC y APCProc Callback se consiga. En ello estoy, pero despacio y no sé si conseguiré finalizar el objetivo.
Si me ayudas, te lo agradecería.
Saludos
Navegación
[#] Página Siguiente
Ir a la versión completa