22 de marzo de 2016

Detectar inactividad

Pueden utilizar la siguiente función para detectar un período de inactividad, ya sea en todo Windows o solamente en la aplicación.

CLEAR
PUBLIC tmrCheck
tmrCheck = NEWOBJECT("DetectActivity")
RETURN

DEFINE CLASS DetectActivity as Timer
  * Sólo detecta inactividad mientras está en este programa?
  JustInThisApp = .T.
  * Intervalo de inactividad tras el cual dispara OnInactivity (en segundos)
  InactivityInterval = 5
  * Intervalo cada el que chequea actividad
  Interval = 1000
  LastCursorPos = ""
  LastKeybState = ""
  LastActivity = DATETIME()
  CursorPos = ""
  KeybState = ""
  IgnoreNext = .T.

  PROCEDURE Init
    DECLARE INTEGER GetKeyboardState IN WIN32API STRING @ sStatus
    DECLARE INTEGER GetCursorPos IN WIN32API STRING @ sPos
    DECLARE INTEGER GetForegroundWindow IN WIN32API
  ENDPROC

  PROCEDURE Destroy
    CLEAR DLLS GetKeyboardState, GetCursorPos, GetForegroundWindow
  ENDPROC

  PROCEDURE Timer
    WITH This
      IF ! .CheckActivity()
        * Si no hubo actividad veo si es tiempo de disparar OnInactivity
        IF ! ISNULL(.LastActivity) AND ;
            DATETIME() - .LastActivity > .InactivityInterval
          .LastActivity = NULL && Prevengo disparo múltiple de OnInactivity
          .OnInactivity()
        ENDIF
      ENDIF
    ENDWITH
  ENDPROC

  * Chequeo si hay actividad
  PROCEDURE CheckActivity
    LOCAL lRet
    WITH This
      IF .JustInThisApp
        IF GetForegroundWindow() <> _VFP.hWnd
          * Estoy en otro programa
          RETURN lRet
        ENDIF
      ENDIF
      .GetCurState()
      IF (!.CursorPos == .LastCursorPos OR !.KeybState == .LastKeybState)
        IF ! .IgnoreNext && La 1ra vez no ejecuto
          lRet = .T. && Hubo actividad
          .OnActivity()
          .LastActivity = DATETIME()
        ELSE
          .IgnoreNext = .F.
        ENDIF
        .LastCursorPos = .CursorPos
        .LastKeybState = .KeybState
      ENDIF
    ENDWITH
    RETURN lRet
  ENDPROC

  * Devuelve el estado actual
  PROCEDURE GetCurState
    LOCAL sPos, sState
    WITH This
      sPos = SPACE(8)
      sState = SPACE(256)
      GetCursorPos (@sPos)
      GetKeyboardState (@sState)
      .CursorPos = sPos
      .KeybState = sState
    ENDWITH
  ENDPROC

  PROCEDURE OnInactivity
    WAIT WINDOW "Inactividad a las " + TIME() NOWAIT
  ENDPROC

  * Hubo actividad
  PROCEDURE OnActivity
    WAIT WINDOW "Actividad a las " + TIME() NOWAIT
  ENDPROC
ENDDEFINE

Mario Lopez

7 comentarios :

  1. Genial esta clase. Funciona a la perfección. Muchas gracias por el aporte!!

    ResponderBorrar
    Respuestas
    1. Hola... en que parte de tu sistema la pusiste? en el main.prg? en cada form? ... Muchas Gracias

      Borrar
  2. Hola Mario
    Estuve viendo tu rutina para detectar inactividad en la aplicacion.
    Quiero preguntarte:
    - En donde pongo la rutina?. En el PRG de inicio, En el Formulario del MAIN (inicio)
    - En cada formulario debo poner un TIMER() ?
    - Si es asi, que debo poner dentro de cada TIMER() ?.

    Bueno Mario por ahora esas son mis dudas.

    Si pueden enviarme tu correo electronico asi, te consulto por el Mismo.

    Gracias

    saludos

    Esteban Micossi
    foxteban646@gmail.com

    ResponderBorrar
    Respuestas
    1. Hola Esteban, lograste resolver donde colocar esta rutina?

      Borrar
    2. Pregunto exactamente lo mismo... donde pongo esta rutina? en el main.prg? el intervalo está dado por milisegundos?

      Borrar
  3. Pregunto lo mismo... donde pongo la rutina? en el main.prg? en cada Form? o cómo la llamo en cada form? Muchas gracias... mi mail es eduardo.cleversoft@gmail.com ... muchas gracias

    ResponderBorrar
  4. ESTIMADO MARIO, POR FAVOR, DONDE PONES LA RUTINA EN EL FORM? PARA PODER CERRAR EL PROGRAMA LA RUTINA NO FUNCIONA FUERA DE UN FORMSET.
    SALUDOS

    GIANFRANCO SQUARTINI MANNIELLO
    G.SQUARTINI@ITALSOFT.CL

    ResponderBorrar

Los comentarios son moderados, por lo que pueden demorar varias horas para su publicación.