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.
Comentários recentes