Página 1 de 3
Temporizador no MiniGui
Enviado: 02 Fev 2014 18:18
por Hasse
Boa tarde colegas.
Tenho uma rotina para baixar arquivos de um banco de dados remoto. Esta rotina é temporizada. A cada 5 minutos faz uma verificação se há ou não arquivos para baixar.
No modo xHarbour puro funciona perfeitamente, mas na MIniGui apresenta comportamento anormal.
Vejam a parte do código em questão:
Código: Selecionar todos
WHILE .T.
...
...
...
n_Tempo := 300 && 5 minutos de intervalo.
*
Principal.label_2.FontColor := BLUE
*
n_Seconds := TimeToSec() + n_Tempo
*
l_Exit := .F.
*
WHILE TimeToSec() < n_Seconds
*
n_Sec := TimeToSec()
n_Min := Int( ( n_Seconds - n_Sec ) / 60 )
n_seg := ( n_Seconds - n_Sec ) - n_Min * 60
c_Tempo := Alltrim( Str( n_Min ) ) + ":" + strzero( n_Seg, 02 )
*
Principal.label_2.Value := 'Pr¢xima leitura em ' + c_Tempo + ' minutos.'
*
Inkey( 0.5 )
IF Lastkey() = 13
l_Exit := .T.
EXIT
ELSEIF LASTKEY() = 27
l_Exit := .T.
EXIT
ENDIF
*
ENDDO
*
Principal.label_2.Value := '=== Download em andamento ==='
*
IF l_Exit .AND. LastKey() = 27
EXIT
ENDIF
*
ENDDO
*
IF l_Exit
RETURN( NIL )
ENDIF
Quando o processamento do download do arquivo termina entra no modo de espera pelo loop acima, informando a cada segundo quanto ainda falta para o download seguinte, ou pressionando <ENTER> inicia outro download imediatamente, independente do tempo já decorrido, ou ainda <ESC>. para encerrar o processamento.
Na MiniGui, quando se clica em qualquer área ou pressiona qualquer tecla temos:
1)-o contador de tempo pára de registrar o tempo decorrido, apesar de continuar a contar;
2)-por vezes apresenta a informação que o processamento "não está respondendo";
3)-o processamento continua funcionar normalmente;
4)-todos os label's que informam o andamento das operações, informações do arquivo em download e outros, param de funcionar.
Certamente há uma forma correta de fazer este trabalho na MIniGui.
Como devo fazer isto ?
Temporizador no MiniGui
Enviado: 02 Fev 2014 23:59
por Toledo
Hasse, tenta o seguinte:
Código: Selecionar todos
SetProperty("Principal","label_2","Value", 'Pr¢xima leitura em '+c_Tempo+' minutos.' )
Abraços,
Temporizador no MiniGui
Enviado: 04 Fev 2014 14:07
por asimoes
Tentou colocar no seu while... o comando: do events
Temporizador no MiniGui
Enviado: 04 Fev 2014 21:51
por Hasse
Boa noite colegas.
Toledo:
Vou testar assim que possível e retorno.
Asimoes:
Não. Ando preciso de muito auxílio. Acho que nem saberia usar este Do Events. Até pode ser que descubra como, consultando os muitos exemplos que há na pasta samples. Neste momento nem saberia por onde iniciar.
Temporizador no MiniGui
Enviado: 21 Fev 2014 20:16
por Hasse
Boa noite colegas.
Toledo:
Testei a tua sugestão e não funcionou.
Asimoes:
Como funciona esse comando DO EVENTS ?
Temporizador no MiniGui
Enviado: 21 Fev 2014 21:04
por Hasse
Outro detalhe:
No momento ainda estou compilando com o REQUEST abaixo para que a janela DOS me informe valores, mas assim que o aplicativo estiver funcinando como deve, elimino esta opção.
REQUEST HB_GT_WIN_DEFAULT
Imprimo nesta janela os valores das teclas pressionadas com:
? LastKey()
Problema:
Quando o foco está na janela DOS a função LastKey() captura adequadamente os valores das teclas pressionadas, mas assim que passo, com o mouse, o foco para o aplicativo MiniGui, ele não captura mais os valores das tecla pressionadas, sendo impresso somente o valor 0 (zero).
Como devo proceder para que isto funcione ?
Temporizador no MiniGui
Enviado: 22 Fev 2014 06:57
por asimoes
Hasse.
Utiliza o comando ON KEY procura na pasta samples da instalação do minigui que você vai achar exemplos de uso.
lastkey() não vai funcionar com minigui.
[]´s
Temporizador no MiniGui
Enviado: 23 Fev 2014 15:43
por Hasse
Boa tarde Asimoes.
Tentei o uso do comando ON KEY mas gerou "Erro de Build".
Suponho que erro ocorra porque usei o comando ON KEY fora do loop do DEFINE WINDOW, já que nos exmplos, todos os comandos ON KEY estão dentro do loop do DEFINE WINDOW, estou correto ?
Ou seja, o erro foi causado porque usei o ON KEY em uma função externa ao DEFINE WINDOW.
Se a minha suposição estiver correta, devo definir um novo WINDOW para o temporizador, tipo "DEFINE WINDOW Temporizador".
Neste caso tenho 2 opções:
a)-Criar uma janela "invisivel" - sei que isto é possível, mas não me lembro mais como pesquisar por um exemplo.
b)-Criar uma janela exatamente igual a principal, fazer a sobre-posição com o mesmo tamanho e coordenadas.
Na tua opinião qual é a melhor opção ?
E mais: quando vou "fechar" a segunda janela, a primeira estará visível ou preciso dar um refresh ?
No caso do refresh, como se faz isto ?
E mais ainda: No código abaixo que uso para sair de 2 LOOP's do tipo WHILE:
A linha seguinte vai funcionar ?
Ou existe outra forma de fazer isto ?
Temporizador no MiniGui
Enviado: 24 Fev 2014 06:32
por asimoes
A linha seguinte vai funcionar ?
Hasse veja o arquivo i_keybd.ch na pasta include.
Veja que não pode ser qualquer tecla tem que ver o valores de VK_* a função responsável pelo comando é _DefineHotKey
#xcommand ON KEY ESCAPE [ OF <parent> ] ACTION <action> ;
=> ;
_DefineHotKey ( <"parent"> , 0 , VK_ESCAPE , <{action}> )
Temporizador no MiniGui
Enviado: 02 Mar 2014 19:14
por Hasse
Boa tarde colegas.
Asimoes: A leitura das teclas pressionadas funciona corretamente, conforme tua orientação acima. Obrigado.
Preciso ainda de auxílio para superar mais 2 dificuldades. Vejamos:
Código: Selecionar todos
...
Aqui estão todos os Includes, os Defines, os xcommand e os Request.
....
FUNCTION MAIN()
...
definições iniciais.
abertura de arquivos
etc.
...
DEFINE WINDOW Principal AT 00, 750 WIDTH 600 HEIGHT 100 ;
TITLE c_CodApar + ' = = ' + c_NmHospLg + ' = = ' MAIN ;
ON INIT { Testa_Connect( c_CntStrng ), Baixa_Prescr() } ; && Testa a conexão e faz a primeira Leitura.
ON RELEASE { || Fecha_Connect() }
*
@ 12,15 LABEL label_1 WIDTH n_Lrg-60 HEIGHT 20 ;
VALUE 'ConexÆo INATIVA' ;
FONT 'Times New Roman' SIZE 14
Principal.label_1.FontColor := RED
@ 40,15 LABEL label_2 WIDTH n_Lrg-60 HEIGHT 20 ;
VALUE '===============' ;
FONT 'Times New Roman' SIZE 14
Principal.label_2.FontColor := BLUE
ON KEY ESCAPE ACTION { || ThisWindow.Release }
ON KEY RETURN ACTION { || n_Interv_5 := n_Minutos * 60 * 1000, Baixa_Prescr() }
*
DEFINE TIMER Timer_1 INTERVAL n_Interv_5 ACTION Baixa_Prescr() && 5 minutos.
*
END WINDOW
ACTIVATE Window principal
*
*
*
*==================================================================================================
FUNCTION Temporizador()
*
n_Interv_5 := n_Interv_5 - n_Interv_1
*
Principal.label_1.Value := '<ESC> Encerrar <ENTER> Iniciar outra leitura'
*
WHILE n_Interv_5 > 0
*
n_Sec := n_Interv_5 / 1000
n_Min := Int( ( n_Sec ) / 60 )
n_seg := n_Sec - ( n_Min * 60 )
c_Tempo := Alltrim( Str( n_Min ) ) + ":" + StrZero( n_Seg, 02 )
*
Principal.label_2.Value := 'Pr¢xima leitura em ' + c_Tempo + ' minutos.' + str( n_Interv_5 )
*
IF n_Interv_5 < 1100
*
* KeyBoard CHR( 13 )
* KeyBoard RETURN && Estas 5 opções testei todas, e
* KeyBoard VK_RETURN && nenhuma funciona.
* ON Key RETURN ACTION Baixa_Prescr()
* ON Key VK_RETURN ACTION Baixa_Prescr()
*
Principal.label_2.Value := '-- Iniciando outra leitura -------------' + str( n_Interv_5 )
*
EXIT
*
ENDIF
*
DO EVENTS
*
ENDDO
*
RETURN( NIL )
PERGUNTAS:
1)-Como simular tecla pressionada, tipo KEYBOARD CHR(13) do Clipper/xHarbour ?
Finalidade: simular um <ENTER> na Function Temporizador() acima, que enviaria o processamento para a FUNCTION Baixa_Prescr()
As 5 opções foram testadas e nenhuma funciona.
Ver na FUNCTION Temporizador()
2)-Ainda não consegui fazer funcionar corretamente a informação do tempo restante no LABEL.
Quando o foco está na janela MiniGui, o LABEL atualiza corretamente.
Quando o foco está numa janela de outro aplicativo, em DOS, o LABEL não atualiza.
O que devo fazer para que isto funcione ?
Obrigado pela ajuda.
Temporizador no MiniGui
Enviado: 02 Mar 2014 19:57
por asimoes
Hasse,
Só para entendimento você está considerando que o INTERVAL DE DEFINE TIMER é:
1000 = 1 SEGUNDO
60000 = 1 MINUTO
300000 = 5 MINUTOS
No seu ON KEY
ON KEY RETURN ACTION { || n_Interv_5 := n_Minutos * 60 * 1000, Baixa_Prescr() }
n_Interv_5 := n_Minutos * 60 * 1000 essa conta é igual a 5 minutos? ou 300000
Temporizador no MiniGui
Enviado: 02 Mar 2014 21:13
por Hasse
São 5 minutos == 30 000 milisegundos. Unidade padrão do DEFINE TIMER.
n_Interv_1 é igual a 1000 (1 minuto)
n_Interv_5 é igual a 30000 (5 minutos)
O Timer_1 do DEFINE TIMER usa o valor de 1 segundo = 1000 milsegundos.
Assim, a cada segundo, o processamento acessa a FUNCTION Temporizador(), reduzindo o valor do n_Interv_5 em 1 segundo.
(n_Interv_5 := n_Interv_5 - n_Interv_1)
Quando o valor de n_Interv_5 é menor que 1000 o processamento deve ir para a Baixa_Prescr(). É isto que ainda não está funcionando no modo automático. Só funciona pressionando a tecla ENTER, via ON Key RETURN ACTION.....
Agora também estou vendo que o cálculo (n_Interv_5 := n_Minutos * 60 * 1000) poderia ser colocado no início da FUNCTION Baixa_Prescr(), sem qualquer problema, retirando ele do ON Key RETURN....
Temporizador no MiniGui
Enviado: 03 Mar 2014 08:05
por Hasse
Bom dia Asimoes.
Devo-te desculpas por ter postado informações, parte incorretas, parte incompletas. O Tico-e-o-Teco já estão "batendo pino". Já fiz tantos testes e tantas re-compilações que já perdi a conta. Acordei de madrugada após sonhar com o código. E me dei conta da mancada.
Ocorre que:
1)-Na parte do Temporizador a contagem decrescente do tempo faltante agora funciona corretamente, mesmo fora de foco, após a inserção do comando DO EVENTS como você orientou acima.
2)-O que não funciona são as informações nas LABEL's da FUNCTION Baixa_Prescr(), que segue abaixo:
Código: Selecionar todos
FUNCTION Baixa_Prescr()
*
n_Interv_5 := n_Minutos * 60 * 1000
*
SetProperty("Principal","label_1","Value", '* = Abrindo conexÆo com o ' + c_NmHospLg + ' = *' )
* Principal.label_1.Value := '* = Abrindo conexÆo com o ' + c_NmHospLg + ' = *'
Principal.label_1.FontColor := RED
* Principal.label_2.Value := ''
SetProperty("Principal","label_1","Value", '' )
...
...
Principal.Title := "Conectado ao TASY do Hospital " + c_NmHospCt
SetProperty("Principal","label_1","Value", 'conexÆo com ' + c_NmHospLg + ' ATIVA' )
* Principal.label_1.Value := 'conexÆo com ' + c_NmHospLg + ' ATIVA'
Principal.label_1.FontColor := BLUE
...
...
SetProperty("Principal","label_1",'Abrindo arquivo de Prescri‡äes do TASY do "' + c_NmHospCT + '"' )
* Principal.label_1.Value := 'Abrindo arquivo de Prescri‡äes do TASY do "' + c_NmHospCT + '"'
Principal.label_1.FontColor := GREEN
...
...
WITH Object oRecSet
SetProperty("Principal","label_2",'Gravando a data/hora do download da Prescri‡Æo' )
* Principal.label_2.Value := 'Gravando a data/hora do download da Prescri‡Æo'
Principal.label_2.FontColor := BLUE
...
...
SetProperty("Principal","label_2",'===================================' )
* Principal.label_2.Value := '==================================='
...
...
END WITH
...
...
SetProperty("Principal","label_1",'ConexÆo ATIVA - Aguardando novo per¡odo para recep‡Æo de dados' )
* Principal.label_1.Value := 'ConexÆo ATIVA - Aguardando novo per¡odo para recep‡Æo de dados'
Principal.label_1.FontColor := BLUE
*
DO EVENTS
...
...
RETURN()
OBSERVE:
1)-Onde temos os três pontinhos, eu eliminei as linhas onde trato da importação dos dados do Banco Oracle. Deixei somente as linhas dos LABEL's. Se você achar que o código completo ajudaria eu insiro;
2)-Observe que testei tanto a forma tradicional, como:
Principal.label_2.Value := 'Abrindo conexão', quanto a forma sugerido pelo Toledo como:
SetProperty("Principal","label_2",'Abrindo conexão' );
3)-Se eu insiro o comando DO EVENTS no meio do código, após cada LABEL, atualiza o LABEL, mas o processamento pula por cima do código restante e vai direto para o fim da função, ou seja, desta forma não serve, já que o processamento fica incompleto;
4)-Inserir o comando DO EVENTS no final já não serve mais para nada, visto que o processamento passa para o Temporizador, onde já está funcionando corretamente;
5)-Possivelmente a solução estaria na possibilidade de inserção do comando DO EVENTS após cada LABEL, mas de tal forma que o processamento continuasse normalmente.
Mas, como se faria isto ?
Temporizador no MiniGui
Enviado: 03 Mar 2014 09:10
por asimoes
Hasse,
Bom dia,
Notei o seguinte o timer está ligado e está sendo chamado a cada x tempo, acontece que se naquele laço WITH Object oRecSet o timer a função for chamada novamente não vai dar erro?
o do events deve ser informado somente uma vez, informe após o último label..
Eu gosto de usar o timer com cuidado veja a função:
O timer foi inciado no ON INIT, ON INIT {||Liga_Timer("INICIAR")};
Código: Selecionar todos
FUNCTION Impressao
Para o timer.
Liga_Timer("PARAR")
Faz alguma coisa....
Reinicia o timer.
Liga_Timer("INICIAR")
RETURN Nil
FUNCTION Liga_Timer(cEvento)
SWITCH cEvento
CASE "INICIAR"
IF !IsControlDefined(Timer_Impressao,Form_Principal)
DEFINE TIMER Timer_Impressao ;
OF Form_Principal ;
INTERVAL 1000 ;
ACTION Impressao()
ELSE
Form_Principal.Timer_Impressao.Enabled:=.T.
ENDIF
EXIT
CASE "PARAR"
IF IsControlDefined(Timer_Impressao,Form_Principal)
Form_Principal.Timer_Impressao.Enabled:=.F.
ENDIF
EXIT
ENDSWITCH
RETURN Nil
Temporizador no MiniGui
Enviado: 03 Mar 2014 09:57
por asimoes
Hasse,
Uma função que simula o enter caso precise:
Código: Selecionar todos
#pragma BEGINDUMP
#include <windows.h>
HB_FUNC( SIMULAENTER )
{
keybd_event(
VK_RETURN,
0,
0,
0
);
}
#pragma ENDDUMP