Clipper On Line • Ver Tópico - Help 3 MiniGUI
Página 1 de 1

Help 3 MiniGUI

MensagemEnviado: 22 Mai 2013 13:57
por Hasse
Boa tarde colegas.

No código abaixo:
   DEFINE WINDOW principal AT 30,1230 WIDTH 200 HEIGHT 80 ;
      TITLE "JS600 - COM " + c_Port MAIN ;
      ON INIT Dados_Iniciais( c_Form )
      *
      @ 12, 15 LABEL label_1 WIDTH 160 HEIGHT 16 ;
         VALUE 'COM ' + c_Port + " => INATIVA" ;
         FONT 'Times New Roman' SIZE 14
         principal.label_1.fontcolor := RED
      *
   END WINDOW
   ACTIVATE Window principal

Como posso transferir o processamento da rotina acima para uma Procedure() ou Function() do tipo abaixo ?
WHILE ! EOF()
*
n_Soma += VALOR
DBSkip()
*
ENDDO

Help 3 MiniGUI

MensagemEnviado: 22 Mai 2013 21:08
por Pablo César
Eu não entendi.

Help 3 MiniGUI

MensagemEnviado: 22 Mai 2013 21:54
por Hasse
Seria lago que em modo janela se faria assim:
   DEFINE WINDOW principal AT 30,1230 WIDTH 200 HEIGHT 80 ;
         TITLE "JS600 - COM " + c_Port MAIN ;
         ON INIT Dados_Iniciais( c_Form )
         *
         @ 12, 15 LABEL label_1 WIDTH 160 HEIGHT 16 ;
            VALUE 'COM ' + c_Port + " => INATIVA" ;
            FONT 'Times New Roman' SIZE 14
            principal.label_1.fontcolor := RED
         *
          Leitura()
         *
      END WINDOW
      ACTIVATE Window principal


FUNCTION Leitura()
   ...
   ...
   Rotina de leitura da serial....
   ...
   ...
RETURN NIL

E que esta função Listar() recebesse novamente o foco após decorrido determinado tempo, e assim por diante.

Help 3 MiniGUI

MensagemEnviado: 22 Mai 2013 22:08
por Pablo César
Para que a rotina Leitura() retorne de tempos em tempos, utilize TIMER.

Substitua na linha 10 por:
DEFINE TIMER Timer_1 INTERVAL 2000 ACTION Leitura()

Help 3 MiniGUI

MensagemEnviado: 23 Mai 2013 08:34
por Hasse
Bom dia Pablo.

Eu já havia testado esta Função, tirada de exemplos da pastas SAMPLES, mas na oportunidade descartei em virtude do comportamento dela.

É que ela dispara a Função a cada intervalo de tempo programado, mesmo que o primeiro processamento ainda não tenha terminado e voltado ao Window principal, fato este que dá erro na Porta Serial.

Agora, após a tua sugestão, botei o tico-e-teco prá funcionar, e encontrei uma gambiarra para contornar este problema. Veja:
l_Read := .F.
   DEFINE WINDOW principal AT 30,1230 WIDTH 200 HEIGHT 80 ;
      TITLE "JS600 - COM " + c_Port MAIN ;
      ON INIT Dados_Iniciais( c_Form )
      *
      @ 12, 15 LABEL label_1 WIDTH 160 HEIGHT 16 ;
         VALUE 'COM ' + c_Port + " => INATIVA" ;
         FONT 'Times New Roman' SIZE 14
         principal.label_1.fontcolor := RED
      *
      DEFINE TIMER Timer_1 INTERVAL 2000 ACTION Ctrl_Read()     
      *
   END WINDOW
   ACTIVATE Window principal

FUNCTION Ctrl_Read()
IF l_Read = .T.
    RETURN( NIL )
ENDIF
l_Read := .T.
...
...
Leitura da Serial
...
...
l_Read := .T.
RETURN( .T. )

A variável l_Read controla e retorna o segundo processo caso o primeiro ainda não tenha terminado o seu trabalho.

Ainda não testei a rotina de comunicação serial com este código, mas ela já está testada, com a MiniGUI em *.PRG separado. Agora, imagino juntar os 2 códigos, tratar da integração, e testar.

A não ser que haja uma outra forma de configurar a função DEFINE TIMER, acredito que a gambiarra deverá funcionar.

Uma outra pergunta:

A MiniGui funciona com algo mais ou menos como abaixo ?

DEFINE TIMER Timer_1 INTERVAL 2000 ACTION ( Ctrl_Read1() ; Ctrl_Read2() )
ou ainda
DEFINE TIMER Timer_1 INTERVAL 2000 ACTION ( l_Read := .T. ; Ctrl_Read1() )

Onde o Processamento do Ctrl_Read1() é processado primeiro, e no seu retorno, é disparado Ctrl_Read2().

Help 3 MiniGUI

MensagemEnviado: 23 Mai 2013 09:19
por Pablo César
Hasse escreveu:É que ela dispara a Função a cada intervalo de tempo programado, mesmo que o primeiro processamento ainda não tenha terminado
Não deu pra entender direito o que você fez para contornar este caso. Acho que se você optou por fazer o TIMER com condicional, então acertou ! Para isso você disponibiliza uma variável private ou publica (acho que no seu caso você utilizou a variável l_Read), que deve ser do tipo lógica, começando sempre com valor verdadeiro, depois torna-se falso (enquanto está fazendo o processamento) e retorna a ser verdadeiro para que a condição do TIMER funcione na hora certa. Em código seria algo assim:
Function Main
Public l_Read:=.t.
..//..

DEFINE TIMER Timer_1 INTERVAL 2000 ACTION (If(l_Read,Ctrl_Read(),Nil))

Function Ctrl_Read()
If l_Read
    l_Read:=.f.
    ..//.. inicio de
    // Leitura da Serial
    ..//.. fim da leitura (do processamento)
   l_Read:=.t.
Endif
Return Nil


Hasse escreveu:A MiniGui funciona com algo mais ou menos como abaixo ?

DEFINE TIMER Timer_1 INTERVAL 2000 ACTION ( Ctrl_Read1() ; Ctrl_Read2() )
ou ainda
DEFINE TIMER Timer_1 INTERVAL 2000 ACTION ( l_Read := .T. ; Ctrl_Read1() )
Não só a Minigui como em todo que é feito em Harbour ou qualquer outra linguagem. Quando é necessário fazer mais de uma ação, isto é: fazer executar mais de uma função... então você coloca as funções entre parenteses separadas de vírgula. Então como uma operação matemática, irá processar primeiro o que está dentro do parentese em sequência. O ponto e vírgula na linguagem de programação, é utilizada para quebra de linha. Mantendo tudo como se fosse uma linha só. Apenas quebra a linha para efeito visual (para compreensão do código apenas).

Help 3 MiniGUI

MensagemEnviado: 23 Mai 2013 10:04
por asimoes
Você pode controlar a função timer assim:

Liga_Timer("INICIAR")

RotinaX()

FUNCTION ROTINAX
Liga_Timer("PARAR")
... processa... e na saída:
Liga_Timer("INICIAR")
RETURN Nil

FUNCTION Liga_Timer(cEvento)
   SWITCH cEvento
    CASE "INICIAR"
         IF !IsControlDefined(Timer_1,Form_1)
           DEFINE TIMER Timer_1  ;
           OF Form_1      ;
           INTERVAL 500 ;
           ACTION RotinaX()
        ELSE
            Form_1.Timer_1.Enabled:=.T.
        ENDI
        ENDIF
        EXIT
   CASE "PARAR"
     IF IsControlDefined(Timer_1,Form_1)
            //Form_1.Timer_1.Release
           Form_1.Timer_1.Enabled:=.F.
       ENDIF
       EXIT
   ENDSWITCH
RETURN Nil

Help 3 MiniGUI

MensagemEnviado: 23 Mai 2013 10:49
por Hasse
Bom dia colegas.

Muito boas as 2 soluções !!!. A minha percepção da MiniGUI está se expandindo...

1)-Dispara a Função Ctrl_Read condicionalmente:
DEFINE TIMER Timer_1 INTERVAL 2000 ACTION (If(l_Read,Ctrl_Read(),Nil))


2)-Controle das propriedades do Timer:
O colega Asimoes apresentou uma solução técnica mais elaborada, usando as propriedades do TIMER, que eu nem de longe poderia imaginar existirem.

Este aprendizado está sendo muito gratificante.

Pablo e Asimoes, obrigado.

Help 3 MiniGUI

MensagemEnviado: 23 Mai 2013 12:00
por Pablo César
Hasse escreveu:A minha percepção da MiniGUI está se expandindo...
Quê bom ! Mas além disso, você está formando novos conceitos para programação GUI. Essas lógicas que foram apresentadas servem para toda linguagem de programação gráfica é outra forma de programar como vínhamos programando em Clipper... (ou até mesmo em Harbour, console).