Página 1 de 4

problema com a keysec() no Harbour

Enviado: 27 Out 2012 10:50
por cjp
Pessoal, tenho notado, desde que migrei do xharbour para o harbour, que há um problema com a função keysec(). Às vezes ela não espera o tempo designado para executá-la.

Já havia enfrentado problema semelhante no xharbour, que foi resolvido com a seguinte função, que me foi enviada por alguém daqui do grupo:

Código: Selecionar todos

function keysec(nkey, ntime, ncounter, lmode)
return __keysec(nkey, ntime, ncounter, lmode)
Mas acho que esta função estava em alguma lib que não dá pra usar no harbour.

Alguém saberia me dizer como resolver isto no harbour?

problema com a keysec() no Harbour

Enviado: 27 Out 2012 13:37
por Imatech
Olá !

KeySec( ... ) é integrante da lib hbCT

Código: Selecionar todos


/*
 *  $Id: keysec.prg 18376 2012-10-19 13:23:11Z vszakats $
 */

/*
 * Harbour Project source code:
 *   CT3 Miscellaneous functions: - KEYSEC()
 *
 * Copyright 2005 Pavel Tsarenko - <tpe2@mail.ru>
 * www - http://harbour-project.org
 */

THREAD STATIC t_hIdle

FUNCTION KeySec( nKey, nTime, nCounter, lMode )

   LOCAL nSeconds

   IF t_hIdle != NIL
      hb_idleDel( t_hIdle )
      t_hIdle := NIL
   ENDIF

   IF HB_ISNUMERIC( nKey )
      IF ! HB_ISNUMERIC( nTime )
         nTime := 0
      ELSEIF nTime < 0
         nTime := -nTime / 18.2
      ENDIF
      nTime *= 1000
      IF ! HB_ISNUMERIC( nCounter )
         nCounter := 1
      ENDIF
      IF ! HB_ISLOGICAL( lMode )
         lMode := .F.
      ENDIF

      nSeconds := hb_milliSeconds()
      t_hIdle := hb_idleAdd( {|| doKeySec( nKey, nTime, lMode, ;
         @nCounter, @nSeconds ) } )
      RETURN .T.
   ENDIF

   RETURN .F.

STATIC PROCEDURE doKeySec( nKey, nTime, lMode, nCounter, nSeconds )

   LOCAL nSec := hb_milliSeconds()

   IF lMode .AND. ! Empty( NextKey() )
      nSeconds := nSec
   ELSEIF nCounter != 0 .AND. nSec - nSeconds >= nTime
      hb_keyPut( nKey )
      IF nCounter > 0
         nCounter--
      ENDIF
      IF nCounter == 0
         hb_idleDel( t_hIdle )
         t_hIdle := NIL
      ELSE
         nSeconds := nSec
      ENDIF
   ENDIF

   RETURN


problema com a keysec() no Harbour

Enviado: 27 Out 2012 23:30
por cjp
Mas eu já estou compilando com essa lib.

O problema é o erro de contagem que tem nessa função. O mesmo problema que existe no xharbour, só que neste, tem essa função que eu citei acima consertando o problema. No harbour não tem?

problema com a keysec() no Harbour

Enviado: 29 Out 2012 13:27
por Jairo Maia
Olá Inácio,

Tente usar esta função ao invés da KeySec(), veja se vai funcionar.

Você pode apenas para facilitar, renomeá-la para KeySec e compilar junto com seus fontes para ver se funciona, isso evitaria ter que renomear ou redirecionar para My_KeySec.

Se desejar fazer o teste e retornar, agradeço.

Código: Selecionar todos

/*
 *
 * My_KeySec() // Insere um código de tecla no Buffer do teclado
 *
 * nKey     = Tecla a ser inserida no Buffer
 * nTime    = Tempo em segundos ( tempo mínimo 0.1 = 1/10 )
 *            para inserir nKey no Buffer
 * nCounter = Número de vezes a inserir nKey no Buffer
 * lMode    = Se .T. reseta nTime para inserir nCounter * nKey
 * lReturn  = Retorna .T. se o tempo foi esgotado, e .F. se foi
 *            pressionado alguma tecla dentro do tempo
 *
*/

Function My_KeySec( nKey, nTime, nCounter, lMode )

   Local nVezes := 0
   Local nTecla := 0
   Local nEspera := Nil

   nCounter := If( nCounter <= 0, 1, nCounter )
   Clear Typeahead  // limpa o buffer do teclado

   If Hb_IsNumeric( nKey )

      If !Hb_IsNumeric( nTime )
         nTime := 0
      EndIf

      IF !Hb_IsNumeric( nCounter )
         nCounter := 1
      EndIf

      If !Hb_IsLogical( lMode )
         lMode := .F.
      EndIf

      nTecla := InKey( nTime )
      If ( lMode .And. nTecla > 0 )

         While ( nVezes < nCounter )

            Hb_KeyPut( nKey )
            Inkey()
            nVezes++

         EndDo

      Else

         While ( nVezes < nCounter )

            Hb_KeyPut( nKey )
            Inkey()

            nVezes++
            nTecla := InKey( nTime )

         EndDo

      EndIf

   EndIf

Return ( nTecla = 0 )

problema com a keysec() no Harbour

Enviado: 30 Out 2012 00:54
por cjp
Valeu, meu caro. Já compilei no meu sistema e vou testar. Retornarei sim, com o resultado. Muito obrigado.


Num rápido teste que fiz, já constatei dois problemas:

Primeiro, deu um erro nessa função, assim descrito:

Código: Selecionar todos

Ocorreu o erro: Error BASE/1074  Erro nos parâmetros: <=
Data: 30/10/12; hora: 01:23:49
Programa......: C:\Agenda\agenda.exe
Na função.....: KEYSEC
Na linha......: 20284
Base em uso...: ATIVU
Pasta.........: tarefas
Usuário.......: I
Versão........: 31/03/12

Caminho Percorrido Antes do Erro:

Vindo de......: KEYSEC Linha: (20284)
Vindo de......: HORTAR Linha: (3701)
Vindo de......: AGCOM Linha: (870)
Vindo de......: MAIN Linha: (255)
A linha onde deu o erro é a seguinte:

Código: Selecionar todos

Local nEspera := Nil
Não entendi a causa do erro.

O outro problema é a inkey(), que está parando o programa a todo momento. Eu tenho que teclar algo sempre para ele prosseguir. Não era pra ser assim, certo? Até tentei tirar essa inkey(), mas daí o programa deu erro.

problema com a keysec() no Harbour

Enviado: 30 Out 2012 10:03
por Jairo Maia
Olá Inácio,

Obrigado pelo teste. Fiz as alterações com base em suas observações. Quando puder testar novamente e retornar, agradeço.

Código: Selecionar todos

/*
 *
 * My_KeySec( nKey, nTime, nCounter, lMode )
 *
 * Insere teclas no Buffer do teclado:
 *
 * nKey     = Tecla a ser inserida no Buffer.
 * nTime    = Tempo em segundos para inserir nKey no Buffer
 *            PS: Tempo m¡nimo 0.1 ( 1s / 10 ).
 * nCounter = Numero de vezes a inserir nKey no Buffer.
 * lMode    = Se .T. reseta nTime para inserir ( nCounter * nKey )
 *            apos pressionar alguma tecla.
 *
 * Retorna .T. se o tempo foi esgotado, e .F. se foi pressionado
 * alguma tecla dentro do tempo.
 *
*/

Function My_KeySec( nKey, nTime, nCounter, lMode )

   Local nVezes := 0
   Local nTecla := 0

   Clear Typeahead  // limpa o buffer do teclado

   If Hb_IsNumeric( nKey )

      If !Hb_IsNumeric( nTime ) .Or. nTime <= 0
         nTime := 0.1
      EndIf

      IF !Hb_IsNumeric( nCounter ) .Or. nCounter <= 0
         nCounter := 1
      EndIf

      If !Hb_IsLogical( lMode )
         lMode := .F.
      EndIf

      nTecla := InKey( nTime )
      If ( lMode .And. nTecla > 0 )

         While ( nVezes < nCounter )

            Hb_KeyPut( nKey )
            Inkey()
            nVezes++

         EndDo

      Else

         Hb_KeyPut( nKey )
         Inkey()
         nVezes++

         While ( nVezes < nCounter )

            If ( lMode .And. nTecla = 0 )
               nTecla := InKey( nTime )
            ElseIf !lMode
               nTecla := InKey( nTime )
            Endi

            Hb_KeyPut( nKey )
            Inkey()
            nVezes++

         EndDo

      EndIf

   EndIf

Return ( nTecla = 0 )

problema com a keysec() no Harbour

Enviado: 31 Out 2012 00:03
por cjp
Meu caro, eu é que agradeço a tua disponibilidade em ajudar.

Testei, mas continua parando no inkey().

problema com a keysec() no Harbour

Enviado: 31 Out 2012 13:48
por Jairo Maia
Olá Inácio,
cjp escreveu:Testei, mas continua parando no inkey().
Sim. Fiz vários testes novamente, e a função está funcionando corretamente. Quanto a parar no inkey() o tempo definido está corretíssimo. Caso não seja isto que você quer, então não é a KeySec() que pode lhe atender. O que ocorre é que realmente em xHarbour e Harbour, esta função tem problema. O objetivo foi criar uma função que tinha os mesmos objetivos dela, e que funcionasse.

Veja como tem que funcionar a função KeySec():
KeySec()
Starts a timer to write a key code into the keyboard buffer.

Syntax

Keysec( <nKey> , ;
<nTime> , ;
[<nCounter>], ;
[<lMode>] ) --> lSuccess

Arguments

<nKey>
This is the numeric key code to write into the keyboard buffer. #define constants listed in the Inkey.ch file are used for <nKey>.

<nTime>
This is a numeric value specifying the time after which the character is written into the keyboard buffer. Positive values indicate the time in seconds, while negative values are interpreted as multiples of 1/18.2 seconds.

<nCounter>
This parameter specifies the number of times <nKey> should be placed into the keyboard buffer before the timer ends. The default value is 1.

<lMode>
This parameter defaults to .F. (false). When .T. (true) is passed, the timer is reset when a key is pressed.

Return
The function returns .T. (true) when the timer is successfully activated, otherwise .F. (false).
Note: when the function is called without a parameter, the timer is deactivated.
Verificando seus códigos postados, vi que você usa o seguinte por exemplo para esta função:

Código: Selecionar todos

KEYSEC(27,165,-1,.t.)
Veja que em nCounter, você sempre coloca -1, quando este parâmetro tem por objetivo informar a função a quantidade de vezes a ser colocada no Buffer do Teclado a tecla definada em nKey, tendo que ser necessariamente número positivo.

Pelo que percebo, sua expectativa não está contemplada nesta função. Na sua opinião, como ela deveria funcionar?

problema com a keysec() no Harbour

Enviado: 01 Nov 2012 01:27
por cjp
Meu caro,

Sempre usei a keysec() com o objetivo principal de avançar num wait "", ou um @...prompt, por exemplo, quando o usuário não tecla nada. Então, a keysec() servirá para "dar um enter" na opção default. Me entende?

No meu entendimento, a keysec() não poderia ter essa parada, porque essa parada está sendo feita a todo passo do programa, já que a keysec() se executa continuamente. Então, por exemplo: se o programa está num @...prompt, caso o usuário faça alguma escolha no menu, não era pra ter nenhuma parada, mas com esse inkey(), está tendo uma parada, o usuário tem que teclar outra tecla para prosseguir. Me entende?

A opção -1, segundo me ensinaram, significaria que a keysec() se repetiria indefinidamente. Não é isso? De toda forma, isso não altera o problema que está dando. Se eu colocar 2, 10, ou 100, o problema dará no mesmo.

problema com a keysec() no Harbour

Enviado: 04 Dez 2012 00:38
por cjp
Eric,

Realmente não resolveu o problema.

Estou usando a versão 3.0 do Harbour.

problema com a keysec() no Harbour

Enviado: 14 Mar 2013 22:18
por cjp
Caros colegas do grupo,

Encareço a ajuda de vocês para uma solução para esta função keysec().

Não entendo porquê, mas ela não está funcionando corretamente.

Aparentemente, ela está esperando que o usuário tecle alguma coisa para, só então, acionar a tecla pretendida na keysec(), o que é um contrassenso, pois a ideia da função é justamente ela simular o pressionamento da tecla em questão, sem intervenção do usuário.

Explico:

Usando assim:

Código: Selecionar todos

           keysec(27,45,-1,.t.)
A pretensão é que, passados 45 segundos sem qualquer ação do usuário, a função simule o pressionamento de ESC pelo usuário, saindo de um dbedit(), por exemplo.

Entretanto, ele não sai nunca do dbedit() espontaneamente. Mas, quando o usuário tecla qualquer tecla, daí sim ele acresce um ESC depois da tecla pressionada pelo usuário, com consequências imprevisíveis.

Em suma, parece que ele está esperando a ação do usuário para entrar no keysec(), o que não é correto.

Alguém poderia me ajudar?

problema com a keysec() no Harbour

Enviado: 15 Mar 2013 10:29
por Pablo César
Oi Inácio, seus tópicos são sempre extensos... rs

Olha eu fiz um teste com o seguinte código (preste atenção ao código):

Código: Selecionar todos

// #include <hmg.ch>

REQUEST HB_GT_WIN_DEFAULT

Function Main()
Local cText:="Teste no MemoEdit"

SetMode(25,80)
SetColor("b/w")

// SET SCOREBOARD Off

keysec(27,15,-1,.t.)
cTexto:=MemoEdit(cText,05,10,18,60)
Alert(cTexto)
Return Nil
Veja eu compilei com REQUEST HB_GT_WIN_DEFAULT para que pudesse ser em modo console pela IDE da HMG, o que basicamente é praticamente quase igual que compilar com puro Harbour. A versão do Harbour é 3.2.0dev (Rev. 18443). Fiz um teste simples, só que reduzi para 15 segundos (para não ter que esperar muito) e anexei o executável para você ver com os próprios olhos e perceber que tudo ocorre normal. A única diferença que há é quando você remove o comentário da linha onde está o comando SET SCOREBOARD Off, isto é, deixando ele válido, portanto não irá aparecer aquela famosa pergunta na parte superior direita "Abort edit Y/N ?". Também preste atenção que desabilitado a linha SET SCOREBOARD Off, só irá perguntar mesmo, se o usuário fizer alguma alteração no texto, senão, nem pergunta.

Portanto há NADA de errado com o KeySec.

problema com a keysec() no Harbour

Enviado: 15 Mar 2013 12:11
por cjp
Realmente, Pablo, o teu exemplo funciona perfeitamente.

A única coisa que tenho diferente aqui é a versão do Harbour (estou usando a 3.0) e a HB_GT_WIN_DEFAULT, que não uso. Será que o problema é num desses fatores?

De qualquer forma, vou testar estes dois pontos e verificar como fica.

Obrigado.

problema com a keysec() no Harbour

Enviado: 15 Mar 2013 12:31
por Pablo César
Eu ja apresentei o HMG para você... então por quê sofrer ??? Use a IDE do HMG em modo console também e seja feliz !

problema com a keysec() no Harbour

Enviado: 15 Mar 2013 19:44
por cjp
Infelizmente ainda não aprendi o suficiente para usá-la. Não tive tempo para estudá-la o suficiente.

Fiz alguns testes. Percebi que o problema ocorre só (ou principalmente) em uma função minha. Pode não ser problema da keysec(), mas não consigo achar nenhum problema na minha função que justifique isso. Estou postando a função para ver se alguém poderia ajudar:

Código: Selecionar todos

                usebase(arq)
                go bottom
                skip -15
                set color to w/r
                clear
                @ 0,0 to maxrow(),maxcol() double
                if us#"I"
                   @ maxrow()-4,2 say "Tempo máximo para esta tarefa: "+alltrim(str(te))+" minutos"
                endif
                @ maxrow()-2,1 say "R-responder; B-atualiza índice só desta tarefa; setas-sobe e desce"
                @ maxrow()-1,1 say "1 a 9-adiam a tarefa por 1 a 9 horas; M-adia meia hora; F-adia 5 minutos"
                set cursor on
                if us="I"
                   private v1[7]
                   private v3[7]
                else
                   private v1[3]
                   private v3[3]
                endif
                if us#"I"
                   v1[1]="substr(dtoc(data),1,5)"
                else
                   v1[1]="Data"
                endif
                v1[2]="substr(hora,1,5)"
                v1[3]="Tarefa"
                v3[1]="Data"
                v3[2]="Hora"
                if us="I"
                   v1[4]="Tempoestim"
                   v1[5]="Tempousado"
                   v1[6]="Tempocompu"
                   v1[7]="Vinculo"
                   v3[4]="Tpe"
                   v3[5]="Tpu"
                   v3[6]="Tpc"
                endif
                prvez="S"
                sele 3
                if usebase(ativ)=.t.
                   append blank
                   repl data with date()
                   repl hora with time()
                   repl acao with "ENT-III"
                endif
                use
                sele (substr(arq,1,at(".",arq)-1))
             if keysec(27,77,-1,.t.)#.t.
		mandmail1("","Keysec retornou falso no responde2 8429")
	     endif
		 
             dbedit(1,1,maxrow()-6,maxcol()-1,v1,"responde2",,v3)

function responde2
             nTecla2:=lastkey()
             save scre to tlresp2
	     nsec=0


         if nTecla2=27 .or. reccount()=0
            keysec(277,125,-1,.t.)
            rest scre from tlresp2
            keyb "y"
            return(0)

         elseif upper(chr(nTecla2))="B"
                if usebase("consulta")=.t.
                   locate for arquivo=arq
                   if found()
                      rcindres=recno()
                      atindres()
                   endif
                endif
                if usebase("consedit")=.t.
                   go rc
		   rlbs()
                   replace exibe with ex
                endif
                keyb "y"
                return(0)

         elseif upper(chr(nTecla2))="V" .and. us="I"
                usebase("consedit")
                go rc
                arq=arquivo
                ftecv()
                keyb "y"
                return(0)

         elseif chr(nTecla2)="0" .and. us="I"
                usebase("consedit")
                go rc
                arq=arquivo
                fteczero()
                keyb "y"
                return(0)

         elseif upper(chr(nTecla2))="-" .and. us="I"
                usebase("consedit")
                go rc
                arq=arquivo
                ftecmen()
                keyb "y"
                return(0)

         elseif upper(chr(nTecla2))="+" .and. us="I"
                usebase("consedit")
                go rc
                arq=arquivo
                ftecmais()
                keyb "y"
                return(0)

         elseif upper(chr(nTecla2))="E" .and. us="I"
                usebase("consedit")
                go rc
                arq=arquivo
                ftece()
                keyb "y"
                return(0)

         elseif upper(chr(nTecla2))="K" .and. us="I"
                usebase("consedit")
                go rc
                fteck()
                keyb "y"
                return(0)

         elseif upper(chr(nTecla2))="S" .and. us="I"
                if usebase("consedit","S")=.t.
                   go rc
                   ftecs()
	        endif
                keyb "y"
                return(0)

         elseif upper(chr(nTecla2))="X" .and. us="I"
                if usebase("consedit","S")=.t.
                   go rc
                   ftecx()
	        endif
                keyb "y"
                return(0)

         elseif upper(chr(nTecla2))="M" .or. upper(chr(nTecla2))="F" .or. (nTecla2>48 .and. nTecla2<58) .or. (us="I" .and. (upper(chr(nTecla2))="D" .or. upper(chr(nTecla2))="Q" .or. upper(chr(nTecla2))="U" .or. upper(chr(nTecla2))="Z" .or. upper(chr(nTecla2))="G" .or. upper(chr(nTecla2))="O" .or. upper(chr(nTecla2))="P" .or. upper(chr(nTecla2))="W"))
                clear
                if usebase("consedit")=.t.
                   go rc
	        endif   
                tpa=val(chr(nTecla2))
                tpa2=nTecla2
                keyb "y"
                ftecmnr()
                return(0)

         elseif upper(chr(nTecla2))="A" .and. us="I"
                if usebase("consedit")=.t.
                   go rc
                   arq=arquivo
                endif
                if usebase(arq,"S")=.t.
                   browse()
                   pack
	        endif   
                usebase("com"+substr(arq,1,1))
                append blank
                repl comandos with (arq)
                @ 23,1 clear to 23,79
                @ 23,5 say "Tarefa salva para enviar mais tarde"
                inkey(2)
                if usebase("consedit","S")=.t.
                   go rc
                   dele
                   pack
		endif
                use (arq)
                keyb "y"
                return(0)

         elseif nTecla2=7 .and. us="I" //DEL
                if usebase("consedit","S")=.t.
                   go rc
                   ftecdel()
		endif
                keyb "y"
                return(0)

         elseif upper(chr(nTecla2))="R"
                ftecr()
                keyb "y"
                return(0)

         elseif upper(chr(nTecla2))="T" .and. us="I"
                ftect()
                keyb "y"
                return(0)

         elseif upper(chr(nTecla2))="I"
                fteci()
                keyb "y"
                return(0)
      endif    
return(2)


Alguém saberia me dizer se tem alguma coisa que esteja impedindo a keysec() de funcionar direito nesse dbedit()?

Noto que o problema ocorre assim que entra no dbedit(), sem que se tecle qualquer outra coisa depois de entrar no dbedit().