Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   C++ Builder (https://www.clubdelphi.com/foros/forumdisplay.php?f=13)
-   -   bloqueador de teclado antigatos (https://www.clubdelphi.com/foros/showthread.php?t=90044)

escafandra 03-04-2016 21:16:16

No he tenido esa experiencia con Hooks, pero puede ser que tu app se niegue a terminar la sesión. Para resolverlo tendrás que manejar los mensajes WM_QUERYENDSESSION y WM_ENDSESSION

Suelo reescribir la función virtual WndProc del formulario para estos menesteres:
Código:

private:
  void __fastcall WndProc(Messages::TMessage &Message);

Código:

void __fastcall TForm1::WndProc(Messages::TMessage &Message)
{
  switch(Message.Msg){
    case WM_QUERYENDSESSION:
      Message.Result = 1;
      break;
    case WM_ENDSESSION:
      if(hKeyboardHook) UnhookWindowsHookEx(hKeyboardHook);
      if(hMouseHook)    UnhookWindowsHookEx(hMouseHook);
      break;
  }
  TForm::WndProc(Message);
}

Pruébalo y nos cuentas.

Saludos.

aguml 03-04-2016 23:43:15

Mañana lo probaré pero me surgen un par de dudas al ver tu código:
1. ¿que hace Message.Result=1 exactamente? Es que solo veo esa instrucción para ese evento.
2. Al apagarse windows este cierra todas las aplicaciones antes ¿usa TerminateProcess para ello? ¿al cerrarla no pasa por el evento OnClose al cerrarse?

escafandra 04-04-2016 00:13:10

Cita:

Empezado por aguml (Mensaje 504012)
1. ¿que hace Message.Result=1 exactamente? Es que solo veo esa instrucción para ese evento.

Si una aplicación devuelve 0 al procesar WM_QUERYENDSESSION, se deniega a Windows la petición de cerrar la sesión, y ésta no se cerrará.
Cita:

Empezado por aguml (Mensaje 504012)
2. Al apagarse windows este cierra todas las aplicaciones antes ¿usa TerminateProcess para ello? ¿al cerrarla no pasa por el evento OnClose al cerrarse?

Windows no usa TerminateProcess, eso cierra a lo bruto una app sin esperar a que termine por medios naturales. Eso es lo que usa el administrador de tareas.
Cuando windows pide que una sesión se cierre porque se va a cerrar la sesión, lo hace a través de WM_QUERYENDSESSION, si las aplicación responde con un número distinto de 0, entonces envía WM_ENDSESSION. La respuesta a ese mensaje debería hacer cerrar la app por su vía natural.

Por algún motivo tu app se niega a cerrarse en el mensaje WM_QUERYENDSESSION y WM_ENDSESSION no es enviado o no está siendo bien tratado. Estas circunstancias no deberían aparecer en una app VCL, pero al parecer te ha sucedido. Es por eso que te propongo que tu mismo trates esos mensajes.

Ahora que te escribo estas líneas, cambia el tratamiento de mensajes por este otro, para forzar la respuesta de WM_QUERYENDSESSION:
Código:

void __fastcall TForm1::WndProc(Messages::TMessage &Message)
{
  switch(Message.Msg){
    case WM_QUERYENDSESSION:
      Message.Result = 1;
      return;                        // La VCL no podrá procesar el mensaje
    case WM_ENDSESSION:
      if(hKeyboardHook) UnhookWindowsHookEx(hKeyboardHook);
      if(hMouseHook)    UnhookWindowsHookEx(hMouseHook);
      break;
  }
  TForm::WndProc(Message);
}

Saludos.

aguml 04-04-2016 00:36:08

Pero si haciendo lo que haces en el primer case se supone que ya se cerrará por su vía normal se supone que ya irá al evento OnClose y allí ya me encargo de terminar los hooks ¿para que controlar el segundo evento que pones?

escafandra 04-04-2016 01:06:11

Cita:

Empezado por aguml (Mensaje 504014)
Pero si haciendo lo que haces en el primer case se supone que ya se cerrará por su vía normal se supone que ya irá al evento OnClose y allí ya me encargo de terminar los hooks ¿para que controlar el segundo evento que pones?

Porque como no puedo reproducir tu circunstancia, he querido asegurar el tiro tratando los dos mensajes y, además, es más didáctico. :)

PD/ He actualizado el control TSysTrayIcon

Saludos.

aguml 04-04-2016 07:12:02

¿Que le has hecho?

escafandra 04-04-2016 08:21:47

Cita:

Empezado por aguml (Mensaje 504021)
¿Que le has hecho?

Cita:

Empezado por escafandra
Me he seguido entreteniendo con este componente y he mejorado el efecto de la propiedad Hide eliminando el efecto de "insinuación" en la barra de tareas al minimizarse y he añadido los eventos que responden a los mensajes NIN_BALLOONSHOW, NIN_BALLOONHIDE, NIN_BALLOONUSERCLICK y NIN_BALLOONTIMEOUT

El componente está probado en Builder 5 y 6 y en delphi 6 y 7. Posiblemente funcione en versiones posteriores.

..
Saludos.

aguml 04-04-2016 10:37:16

¿Qué es eso del efecto insinuación?
Otra cosa, he estado haciendo pruebas para ver si con lo que me pusiste pasaba por los eventos FormClose y FormCloseQuery y he podido comprobar como cierra la aplicacion sin pasar por ninguno de esos eventos. No se como lo hará entonces.
Así lo he dejado al final:
Código PHP:

void __fastcall TFormMain::WndProc(Messages::TMessage &Message)
{
  switch(
Message.Msg){
    case 
WM_QUERYENDSESSION:
      
Message.Result 1;
      return;                        
// La VCL no podrá procesar el mensaje
    
case WM_ENDSESSION:
      
//CloseApp = true;
      //SysTrayCanClose = CloseApp;
      
if(hKeyboardHook != NULL){
         
SysTrayIcon->Minimize();
         
SysTrayIcon->ShowBalloon("Oye tu","¿Como te atreves a cerrar la sesión cuando estoy bloqueando?\nEsto no quedará así, me he quedado con tu cara");
         
Sleep(6000);
         
UnhookWindowsHookEx(hKeyboardHook);
         
hKeyboardHook NULL;
      }
      if(
hMouseHook != NULL){
         
UnhookWindowsHookEx(hMouseHook);
         
hMouseHookNULL;
      }
      break;
  }
  
TForm::WndProc(Message);


Un ultimo detalle sobre el componente, estaría muy bien el crear una propiedad que indique el tiempo que se mantendrá abierto el bocadillo para poder indicar el tiempo que queremos que se quede abierto. Eso es muy util para poner menos tiempo a mensajes cortos y mas a mensajes largos por ejemplo. ¿Es posible eso o viene un tiempo establecido que no es configurable?

aguml 04-04-2016 12:10:26

Otro detalle, he instalado la nueva version del componente y lo he probado con mi proyecto. En mi proyecto al dar al boton cerrar de la barra de titulo del formulario se minimiza el formulario al systray y veo que en tu ejemplo al minimizar no se produce el efecto ese que parece que se encoje el formulario hacia la barra de tareas pero en mi caso si se produce ese efecto. No se si es normal con la nueva version de tu componente o no.

escafandra 08-04-2016 02:35:18

He vuelto a actualizar SysTrayIcon y le he añadido el TimeOut de notificaciones en la propiedad BalloonInterval el enlace lo tienes aquí, junto con la versión anterior

Saludos.

aguml 08-04-2016 07:53:57

Muchas gracias.

aguml 08-04-2016 17:31:17

Lo he instalado y probado y esta genial. Solo dos cosillas, el limite inferior se lo he cambiado de 5000 a 1000 y el superior lo he dejado pero 300000 me parece mucho ya que son 5 minutos. Creo que es demasiado pero nunca se sabe para que puede servir tener un bocadillo 5 minutos en pantalla jajaja.

escafandra 08-04-2016 20:02:18

El problema está en que win 8 y 10 no admiten valores menores de 5000 y el límite alto es de 5 minutos. En WINXP no hay problema para establecer el límite que quieras. Es por eso que puse los límites que ves.

Saludos.

aguml 08-04-2016 23:52:13

Aaaa ok ok. De todos modos es genial.


La franja horaria es GMT +2. Ahora son las 15:43:19.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi