Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Problemas al presiona las teclas NumLock, CapsLock y BloqDes (https://www.clubdelphi.com/foros/showthread.php?t=24214)

Sr.Scorpion 11-08-2005 20:42:18

Problemas al presiona las teclas NumLock, CapsLock y BloqDes
 
Hola:

Quiero hacer una aplicacion con un StatusBar en donde me controle cuando esta encendida tanto el NumLock, CapsLock y BloqDes, la funcion la pongo en el OnKeyPress de la forma y resulta que cuando aprieto cualquiera de estas tres teclas no se activa el OnKeyPress.... que puede ser eso ???

Saludos

jmariano 11-08-2005 21:10:02

Saludos!

Es mejor que uses el evento "OnKeyDown" que permite procesar teclas especiales como las que dices ("OnKeyPress" ocurre mas bien cuando se pulsan teclas normales de caracteres). Mira en la ayuda sobre los códigos virtuales de cada tecla ("Virtual key codes") y asi saber los que corresponden a las teclas que necesitas.

Chao!

Sr.Scorpion 11-08-2005 22:38:59

Gracias.... como tu bien dices se actica el evento cuando presiono las teclas especiales.
El problema ahora es que el GetKeyState(VK_NUMLOCK) no me funciona siempre me da diferente de 0... en fin que no puedo controlar cuando esta o no activa..

Saludos

dec 11-08-2005 23:10:18

Hola,

No es preciso que lo hagas en ningún evento específico, aunque puedes hacerlo así si es mejor o lo prefieres. Personalmente estoy utilizando un procedimiento para hacer lo que tú precisas y parte del procedimiento es este:

Código Delphi [-]
   if GetKeyState(VK_CAPITAL) = 1 then
     bEstado.Panels[8].Text := rsBloqMayus
   else
     bEstado.Panels[8].Text := '';
   if GetKeyState(VK_NUMLOCK) = 1 then
     bEstado.Panels[9].Text := rsBloqNum
   else
     bEstado.Panels[9].Text := '';
   if GetKeyState(VK_SCROLL) = 1 then
     bEstado.Panels[10].Text := rsScrolLock
   else
     bEstado.Panels[10].Text := '';
Puedo llamar al procedimiento desde "OnKeyDown", pero, también desde cualquier otro lugar, ya que en el mismo no se precisa de los parámetros que proporciona "OnKeyDown", por poner un caso. En cuanto a que no te funcione "VK_NUMLOCK"... lo único que puedo decirte es que en Delphi 7 y Windows Xp SP2 sí que funciona correctamente.

jmariano 11-08-2005 23:21:09

Saludos!

Es que GetKeyState() devuelve la información, mas bien, a base de bits. Pero si al resultado de esta función le sumas simplemente 127, verás que te devolverá 0, cuando el NumLock está activo, y -1, cuando no lo está.

Código Delphi [-]
procedure TForm.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if Key = VK_NUMLOCK then
    case (GetKeyState(VK_NUMLOCK) + 127) of
      0: ShowMessage('Activo'); // Permite usar el teclado numérico
     -1: ShowMessage('Inactivo'); // Sólo funciona las teclas cursoras
    end;
end;

jmariano 11-08-2005 23:33:33

Saludos dec!

Justo vi tu respuesta despues de publicar la mia y quería preguntarte, ¿Te devuelve a ti "GetKeyState" un valor entre 0 y 1 al comprobar el NumLock? Porque tengo el mismo sistema operativo que tu (XP2) y la misma versión de Delphi (v7) y lo que me devuelve, en realidad, es un número entero negativo (-127 y -128, según esté o no activo), y al mirar la ayuda sobre esta función comenta que lo que cambia al activar o desactivar es el bit menos significativo (por eso da un número negativo).

Chao!

dec 12-08-2005 10:55:18

Hola,

Cita:

Empezado por jmariano
¿Te devuelve a ti "GetKeyState" un valor entre 0 y 1 al comprobar el NumLock?

Así es jmariano. Un 0 si la tecla en cuestión no está "activada" y un 1 si lo está...

Sr.Scorpion 12-08-2005 16:13:28

Gracias a los dos por responderme..... problema resuelto. Eso si la funcion de DEC no me funciona, sigue como estaba antes... tuve que sumarle 127 como decia jmariano y asi fue como me trabajo.


Saludos y Gracias

Sr.Scorpion 12-08-2005 17:54:31

Bueno al final tuve que hacer dos procedimientos... uno para el estado de las teclas y otro para cuando se presionan. En el evento OnShow de la Forma principal llamo al procedimiento KeyState.. el cual se ejecuta solamente una vez.

Código:


procedure TMain.KeyState();
begin
If GetKeyState(VK_NUMLOCK) = 1 Then
 StatusBar.Panels[2].Style:= psText
else
 StatusBar.Panels[2].Style:= psOwnerDraw;
If GetKeyState(VK_CAPITAL) = 1 Then
 StatusBar.Panels[3].Style:= psText
else
 StatusBar.Panels[3].Style:= psOwnerDraw;
If GetKeyState(VK_SCROLL) = 1 Then
 StatusBar.Panels[4].Style:= psText
else
 StatusBar.Panels[4].Style:= psOwnerDraw;
end;

y el otro procedimiento es KeyPressed que lo llamo solamente en el OnKeyDown y se le pasa como parametro la variable Key del OnKeyDown

Código:


procedure TMain.KeyPressed(Key: DWORD);
begin
If Key = VK_NUMLOCK then
 if (GetKeyState(VK_NUMLOCK) + 127) = 0 Then
  StatusBar.Panels[2].Style:= psText
  else
  StatusBar.Panels[2].Style:= psOwnerDraw;
If Key = VK_CAPITAL then
 if (GetKeyState(VK_CAPITAL) + 127) = 0 Then
  StatusBar.Panels[3].Style:= psText
  else
  StatusBar.Panels[3].Style:= psOwnerDraw;
If Key = VK_SCROLL then
 if (GetKeyState(VK_SCROLL) + 127) = 0 Then
  StatusBar.Panels[4].Style:= psText
  else
  StatusBar.Panels[4].Style:= psOwnerDraw;
end;

Si pueden mejorarlo pues bienvenido sea.... esto por lo menos soluciona el problema.

roman 12-08-2005 18:27:00

No entiendo bien por qué la discrepancia en el funcionamiento. A mi me funciona como dice dec. Ahora, según la documentación, la comparación tendría que hacerse así:

Código Delphi [-]
if GetKeyState(VK_CAPITAL) and 1 = 1 then
  ...

Por otra parte, si lo que se desea es mostrar el estado de estas teclas en una barra de estado, yo me olvidaría del OnKeyDown y pondría un Timer que se ejecute cada 10 ms en donde haría la comprobación. De esta manera, sólo tienes que poner el código en un lugar y además el estado se reflejará correctamente aun cuando el estado de la tecla cambie por razones distintas a oprimir la tecla (al menos a mi me pasa cada tanto que la tecla NumLock se apaga luego de correr alguna aplicación).

// Saludos

Sr.Scorpion 12-08-2005 19:52:58

Esa sentencia merece un aplauso y una reverencia..... esto hace que el procedimiento sea unico y no haya que introducirle parametros de tecla. Por lo tanto el procedimiento quedaria asi...

Código:

procedure TMain.KeyState();
begin
If GetKeyState(VK_NUMLOCK) and 1 = 1 Then
 StatusBar.Panels[2].Style:= psText
else
 StatusBar.Panels[2].Style:= psOwnerDraw;
If GetKeyState(VK_CAPITAL) and 1 = 1 Then
 StatusBar.Panels[3].Style:= psText
else
 StatusBar.Panels[3].Style:= psOwnerDraw;
If GetKeyState(VK_SCROLL) and 1 = 1 Then
 StatusBar.Panels[4].Style:= psText
else
 StatusBar.Panels[4].Style:= psOwnerDraw;
end;

roman... en cuanto a lo del Timer no me gusta mucho esa idea debido a que no tiene un efecto inmediato, es decir yo aprieto el CapsLock y se me demora 10 o 5 segundos en mostrarse ese cambio en mi aplicacion. Por lo menos en cuanto a mi respecta me gusta mas la onda del OnKeyDown, tiene un efecto mas inmediato. No obstante te agradezco que hayas intervenido en este post tu sentecia de verdad que me fue muy util

Saludos y Gracias

roman 12-08-2005 20:13:58

Cita:

Empezado por Sr.Scorpion
roman... en cuanto a lo del Timer no me gusta mucho esa idea debido a que no tiene un efecto inmediato

:eek: ¿¿¿¡¡¡¡¡10 milisegundos no se te hace inmediato!!!!????? :eek:

Simplemente pon la propiedad Interval del timer en 10 (incluso 50 0 100 debe ser suficiente). Te aseguro que el efecto es inmediato.

// Saludos

roman 12-08-2005 20:21:57

¿Has pensado que sucede si el usuario activa otra aplicación y estando en ella cambia el estado de alguna de estas teclas? ¿Crees que tu aplicación lo detectará? Haz la prueba.

// Saludos

Sr.Scorpion 12-08-2005 20:34:47

Primero disculpa.... pense que habias dicho 10 segundos cuando en realidad eran 10 milisegundos. Bueno pensandolo bien no esta nada mal eso.... en esa parte tiene razon....
Ahora pregunto yo.... no seria mucho que a cada 10 mseg. se este ejecutando una accion, traiga esto como consecuencia algun error en la aplicacion o que esta intervenga en la ejecucion de otra o algo por el estilo ???

Saludos

roman 12-08-2005 20:48:41

Cita:

Empezado por Sr.Scorpion
Ahora pregunto yo.... no seria mucho que a cada 10 mseg. se este ejecutando una accion, traiga esto como consecuencia algun error en la aplicacion o que esta intervenga en la ejecucion de otra o algo por el estilo ???

No te lo puedo asegurar pero dudo que hay problema. Si cada 10 ms exportaras una tabla de 100,000 registros seguramente habría algún problema pero el código que se ejecutaría en el OnTimer es sumamente rápido.

// Saludos

Sr.Scorpion 12-08-2005 20:59:35

bueno pues entonces .... caso resuelto. Se queda el Timer que es mas abarcador que el OnKeyDown. Mil Gracias Roman por tus consejos.

Saludos

dec 13-08-2005 01:51:01

Hola,

Vamos a ver... yo estoy utilizando el procedimiento tal como lo mostré arriba en un editor de texto: muestro en una barra de estado, entre otras cosas, el estado de las teclas que nos ocupan. Utilizo el evento "OnKeyUp" del formulario en que está el editor para llamar al procedimiento "ActualizarBarraEstado" y también llamo a dicho procedimiento cuando es preciso, por ejemplo, cuando se abre un archivo en el editor, pero también en otros lugares... pues bien, ¡no tengo en absoluto ningún problema, puede verse el editor funcionando, en lo que toca a ese aspecto, perfectamente!

vtdeleon 13-08-2005 05:32:26

Saludos
dec, probando tu fabuloso editor encontre lo que comenta roman
Cita:

Empezado por roman
¿Has pensado que sucede si el usuario activa otra aplicación y estando en ella cambia el estado de alguna de estas teclas?

Haciendo pruebas con el Caps, Numlock e Insert.:rolleyes:

roman 13-08-2005 21:19:54

Cita:

Empezado por dec
Utilizo el evento "OnKeyUp" del formulario en que está el editor para llamar al procedimiento "ActualizarBarraEstado" y también llamo a dicho procedimiento cuando es preciso, por ejemplo, cuando se abre un archivo en el editor, pero también en otros lugares

Este es precisamente el punto. De la forma que propongo sólo tienes que preocuparte en un lugar. En el XEditor, si oprimes CapsLock o NumLock estando tu aplicación inactiva, la barra de estado no se actualiza sino hasta que la vuelves a activar. De hecho, tal como lo tienes ahora podrías lograrlo usando una componente TApplicationEvents y poniendo el código en su evento OnIdle con lo cual la barra de estado estaría siempre al día al menos mientras esté activa la aplicación, pero el problema es cuando no está activa. Es un problema menor, tan sólo de apariencia, pero yo prefiero que la barra se actualice aun sin estar activa la aplicación.

// Saludos

dec 13-08-2005 22:47:06

1 Archivos Adjunto(s)
Hola,

roman, lo que dices sobre XEditor bien puede ser cierto, pero, seguro que habrá formas de arreglarlo. Yo, por mi parte, he preparado el siguiente ejemplo, muy sencillo, pero que, muestra a las claras cómo creo que puede solucionarse el asunto: salvando que, como tú dices, cuando la aplicación no esté activa no se dará cuenta de los cambios en las teclas especiales que nos ocupan: como digo, no creo que sea mayor problema solucionarlo, bien como tú dices, utilizando el evento "OnIdle" u otro parecido. En todo caso ahí está el ejemplo.

Actualización: Por cierto, roman, es posible que no uses XEditor hace tiempo ;) puesto que haciendo compruebo que bastaría hacer clic con el ratón en el mismo para que la barra de estado se actualizase, esto es, no sería preciso "comenzar a escribir". Tal vez todavía esta no sea la mejor solución, pero, no me descontenta para el caso.

Otra actualización: Soy estúpido a las veces. Acabo de probar lo que decías roman de utilizar el evento "OnIdle" y XEditor va de lujo así, mucho mejor, mucho más serio, como más pendiente de lo que le toca. He actualizado también el ejemplo adjunto de manera que también hace uso del evento susomentado. Gracias roman.


La franja horaria es GMT +2. Ahora son las 16:02:37.

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