Categoria:
Alinhar 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.
