Alinhar GET numérico à DIREITA

Foto de Anderson

Categoria: 

Alinhar GET numérico à DIREITAAlinhar GET numérico à direita deveria "vir de fábrica", um "PICTURE", mas infelizmente é uma falta do xBase que permanece até hoje. Nem o [x]Harbour consertou isso. Só encontrei solução nativa no HWGUI e talvez haja em outras libs gráficas. Todavia, há uma solução  antiga publicada no livro de Rick Spencer de GET CALCULATOR que preenche o campo da direita para a esquerda como numa calculadora. É uma pena que os compiladores recentes não incorporaram essa opção.

Enfim, ela é quase perfeita, o problema é que essa função não considera o padrão numérico britânico, que usamos no Brasil, onde a vírgula é que separa as casas decimais ao invés do ponto, então quando usamos a máscara "@E" essa função dá problema. Achei estranho também ela não mostrar o cursor enquanto tem foco no get, mas sossegue! Eu conseguí corrigir essas duas coisinhas e vou compartilhar aqui com vocês!

Primeiramente, é bom salientar que não considero alterar todo o ambiente GETSYS só por conta disso visto que faz parte do compilador, se você usar um outro GETSYS personalizado vai ficar preso nessa versão sem acompanhar as versões do compilador que usa. Portanto, creio que é melhor usar um READER personalizado que trate apenas desses casos que estamos precisando. Esse comando GET CALCULATOR usa um READer só para ele, ou seja, quando quiser que um campo numérico seja digitado da direita para a esquerda, use um READer só para ele.

Essa função não implementa todas as teclas padrões do GET. Por exemplo, o cursor não passeia pelo GET para editar o campo, ele funciona como uma entrada de calculadora mesmo, digitando da direita para a esquerda e apagando sempre o último número digitado.

O reader baseia-se na função GetReader() padrão com algumas alterações básicas: trabalha com GET:END() para ir pro fim do campo, GET:OVERSTRIKE() para ir digitando à direita e troca a função GetAplyKey() habitual por nossa função personalizada GetCalcApplyKey() para atender nossa necessidade.

Resolvendo campos numéricos sem mudar o GETSYS inteiro

A solução é composta de 2 partes, um header e um READer. Coloque o header na sua pasta INCLUDE. Você pode colocar o comando direto no programa também, apesar de não ser uma "boa prática" de programação, esse comando não teria o que evoluir, então não vejo óbice. 

/***
* Getcalc.ch
*
* Definition of GET CALCULATOR command.
*/

#command @ <row>,  GET <var>                             ;
                        [<clauses,...>]                       ;
                        CALCULATOR                            ;
                        [<moreclauses,...>]                   ;
                                                              ;
      => @ <row>,  GET <var>                             ;
                        [<clauses>]                           ;
                        SEND reader := {|oGet|                ;
                                        GetCalc(oGet) }       ;
                        [<moreclauses>]

Aliás, você pode usar o argumento SEND do comando @...GET para definir um GET:READER() com seu codeblock chamando sua função personalizada, mas se você examinar bem esse comando vai observar que ele estende as funcionalidades do GET sem substituí-lo, ou seja, permite que ele processe as opções que ele já conhece e incrementa o argumento CALCULATOR novo.

Agora vejamos o código principal com o nosso READer personalizado:

#include "Getexit.ch"
#include "Inkey.ch"
#include "Getcalc.ch"

proc GetCalc( oGet )

  nCURSOR := SETCURSOR()
  // read the GET if the WHEN condition is satisfied
  IF ( GetPreValidate(oGet) )
    // activate the GET for reading
    oGet:SetFocus()

    // RS added this
    // Start at last position
    oGet:end()
    // Just to here
	
	// MOSTRA O CURSOR
	SETPOS(oGET:ROW, oGET:COL + oGET:POS - 1)
	SETCURSOR(1) // ATIVA CURSOR MODO SUBLINHADO

    DO WHILE ( oGet:exitState == GE_NOEXIT )
      // check for initial typeout (no editable positions)
      IF ( oGet:typeOut )
        oGet:exitState := GE_ENTER
      ENDIF

      // apply keystrokes until exit
      DO WHILE ( oGet:exitState == GE_NOEXIT )
        GetCalcApplyKey(oGet, HOTInKey(0))
      ENDDO

      // disallow exit if the VALID condition is not satisfied
      IF ( !GetPostValidate(oGet) )
        oGet:exitState := GE_NOEXIT
      ENDIF
    ENDDO
    // de-activate the GET
    oGet:KillFocus()
  ENDIF
SETCURSOR(nCURSOR)
RETURN


/***
* GetCalcApplyKey()
* Apply a single Inkey() keystroke to a GET.
*
* NOTE: GET must have focus.
* Standard stuff. RS changed only BS and otherwise
*/

#define K_UNDO          K_CTRL_U

proc GetCalcApplyKey(oGet, nKey)

local cKey
local bKeyBlock
local cTemp
local nTemp

  // check for SET KEY first
  IF (bKeyBlock := SetKey(nKey)) <> NIL
    GetDoSetKey(bKeyBlock, oGet)
    RETURN                              // NOTE
  ENDIF

  DO CASE
    CASE nKey == K_UP
      oGet:exitState := GE_UP

    CASE nKey == K_SH_TAB
      oGet:exitState := GE_UP

    CASE nKey == K_DOWN
      oGet:exitState := GE_DOWN

    CASE nKey == K_TAB
      oGet:exitState := GE_DOWN

    CASE nKey == K_ENTER
      oGet:exitState := GE_ENTER

    CASE nKey == K_ESC
      IF Set(_SET_ESCAPE)
        oGet:undo()
        oGet:exitState := GE_ESCAPE
      ENDIF

    CASE nKey == K_PGUP
      oGet:exitState := GE_WRITE

    CASE nKey == K_PGDN
      oGet:exitState := GE_WRITE

    CASE nKey == K_CTRL_HOME
      oGet:exitState := GE_TOP

    // both ^W and ^End terminate the READ (the default)
    CASE nKey == K_CTRL_W
      oGet:exitState := GE_WRITE

    CASE nKey == K_UNDO
      oGet:Undo()

    CASE nKey == K_BS .OR. nKey == K_DEL
      oGet:delete()
      IF oGet:type == "C"
        cTemp := oGet:unTransform()
        cTemp := " " + Substr(cTemp, 1, Len(cTemp) - 1)
        oGet:buffer := Transform(cTemp, oGet:picture)
      ELSE
        nTemp := oGet:unTransform()
		cDEC := "."
		IF AT("@E", UPPER(oGET:picture) ) > 0
			// NESSE CASO É A VÍRGULA PARA CASAS DECIMAIS!
			cDEC := ","
		ENDIF
        IF At(cDEC, oGet:buffer) != 0
          // There is a decimal point
          nTemp := nTemp / 10
        ELSE
          // No decimal point, division already taken place
          // by deleting last character
        ENDIF
        oGet:buffer := Transform(nTemp, oGet:picture)
      ENDIF
      oGet:display()

    OTHERWISE
      IF (nKey >= Asc('0') .AND. nKey <= Asc('9')) .OR. ;
          (nKey == Asc('.') .AND. ;
           oGet:type == "C" .AND. At(".", oGet:buffer) == 0)

        cKey := Chr(nKey)
        IF oGet:type == "C"
          cTemp := oGet:unTransform()
          cTemp := SubStr(cTemp, 2) + " "
          oGet:buffer := Transform(cTemp, oGet:picture)
        ELSE
          nTemp := oGet:unTransform()
          nTemp := nTemp * 10
          oGet:buffer := Transform(nTemp, oGet:picture)
        ENDIF
        // NOTE - important to use OverStrike here to set changed
        // Alternative is to stuff key yourself. However, that does
        // not set changed, therefore var is not updated.
        oGet:overStrike(cKey)
        oGet:end()
        oGet:display()
    ENDIF
  ENDCASE
RETURN

Os comentários em português foi do que eu alterei. O resto é mérito de Rick Spencer!

Veja também: http://www.pctoledo.com.br/forum/viewtopic.php?f=1&t=5559

Gostou? Deixe seus comentários.

Downloads: 

getcalc.ch — Baixado 140 vezes
getcalc.prg — Baixado 306 vezes
Total votes: 0