Sim o importante é que foi atendido, você também tem razão. Mas o que é muito bom (não ver os colegas serem asperos, achando que a idéia de cada um é melhor). Temos que entender, que isto é um FORUM e que se debatem idéias e podem surgir as mais variadas possibilidades. Claro que é sempre motivada com a necessidade de um colega, mas também temos que dar lugar a novos exemplos, novas idéias. Todas as que você postaram, foram muito válidas. E como eu disse desde um principio deste TÓPICO, eu faria algo mais apurado (mas cabe saber o que o colega precisa). Tal é assim que o colega Eolo, matou direitinho a questão toda. Também não estou tirando razão de cada um, porque as vezes uma demanda simples requer também uma simples solução. Mas a fim de deixar os colegas analisarem o meu GETSYS, vou colocá-lo a seguir:
Código: Selecionar todos
// NOTE: compile with /m /n
#include "Inkey.ch"
#include "Getexit.ch"
/***
* Nation Message Constants
* These constants are used with the NationMsg(<msg>) function.
* The <msg> parameter can range from 1-12 and returns the national
* version of the system message.
*/
#define _GET_INSERT_ON 7 // "Ins"
#define _GET_INSERT_OFF 8 // " "
#define _GET_INVD_DATE 9 // "Invalid Date"
#define _GET_RANGE_FROM 10 // "Range: "
#define _GET_RANGE_TO 11 // " - "
#define K_UNDO K_CTRL_U
// State variables for active READ
STATIC sbFormat
STATIC slUpdated := .F.
STATIC slKillRead
STATIC slBumpTop
STATIC slBumpBot
STATIC snLastExitState
STATIC snLastPos
STATIC soActiveGet
STATIC scReadProcName
STATIC snReadProcLine
//
// Format of array used to preserve state variables
//
#define GSV_KILLREAD 1
#define GSV_BUMPTOP 2
#define GSV_BUMPBOT 3
#define GSV_LASTEXIT 4
#define GSV_LASTPOS 5
#define GSV_ACTIVEGET 6
#define GSV_READVAR 7
#define GSV_READPROCNAME 8
#define GSV_READPROCLINE 9
#define GSV_COUNT 9
/***
*
* ReadModal()
*
* Standard modal READ on an array of GETs
*
*/
FUNCTION ReadModal( GetList, nPos )
LOCAL oGet
LOCAL aSavGetSysVars
IF ( VALTYPE( sbFormat ) == "B" )
EVAL( sbFormat )
ENDIF
IF ( EMPTY( GetList ) )
// S'87 compatibility
SETPOS( MAXROW() - 1, 0 )
RETURN (.F.) // NOTE
ENDIF
// Preserve state variables
aSavGetSysVars := ClearGetSysVars()
// Set these for use in SET KEYs
scReadProcName := PROCNAME( 1 )
snReadProcLine := PROCLINE( 1 )
// Set initial GET to be read
IF !( VALTYPE( nPos ) == "N" .AND. nPos > 0 )
nPos := Settle( Getlist, 0 )
ENDIF
WHILE !( nPos == 0 )
// Get next GET from list and post it as the active GET
PostActiveGet( oGet := GetList[ nPos ] )
// Read the GET
IF ( VALTYPE( oGet:reader ) == "B" )
EVAL( oGet:reader, oGet ) // Use custom reader block
ELSE
GetReader( oGet ) // Use standard reader
ENDIF
// Move to next GET based on exit condition
nPos := Settle( GetList, nPos )
ENDDO
// Restore state variables
RestoreGetSysVars( aSavGetSysVars )
// S'87 compatibility
SETPOS( MAXROW() - 1, 0 )
return ( slUpdated )
/***
*
* GetReader()
*
* Standard modal read of a single GET
*
*/
PROCEDURE GetReader( oGet )
// Read the GET if the WHEN condition is satisfied
IF ( GetPreValidate( oGet ) )
// Activate the GET for reading
oGet:setFocus()
WHILE ( oGet:exitState == GE_NOEXIT )
// Check for initial typeout (no editable positions)
IF ( oGet:typeOut )
oGet:exitState := GE_ENTER
ENDIF
// Apply keystrokes until exit
WHILE ( oGet:exitState == GE_NOEXIT )
if UPPER(READVAR())="CMAIL"
VK:=INKEY(0)
KCLP:=.t. // Permite F10 para clipboard
KLOW:=.t. // Permite caracteres minusculas
KUPP:=.f. // Permite caracteres maiusculas
KNUM:=.t. // Permite caracteres numericos
KOUT:="@._-" // Permite esse caracteres definidos
DO CASE
CASE VK=-9 .AND. KCLP=.T.
VCHR:=CLIP_BOARD()
FOR IC=1 TO LEN(ALLTRIM(VCHR))
GetApplyKey( oGet, ASC(SUBSTR(VCHR,IC,1)) )
NEXT
CASE AT(CHR(VK),KOUT)>0 // Outros caracteres
VCHR:=CHR(VK)
CASE VK=128 .AND. !(KLOW=.F. .AND. KUPP=.F.) // Ç
IF KUPP=.T.
VCHR:=CHR(VK)
ELSE
VCHR:=CHR(135)
ENDIF
CASE VK=135 .AND. !(KLOW=.F. .AND. KUPP=.F.) // ç
IF KLOW=.T.
VCHR:=CHR(VK)
ELSE
VCHR:=CHR(128)
ENDIF
CASE VK>96 .AND. VK<123 .AND. !(KLOW=.F. .AND. KUPP=.F.) // a-z
IF KLOW=.T.
VCHR:=CHR(VK)
ELSE
VCHR:=UPPER(CHR(VK))
ENDIF
CASE VK>64 .AND. VK<91 .AND. !(KLOW=.F. .AND. KUPP=.F.) // A-Z
IF KUPP=.T.
VCHR:=CHR(VK)
ELSE
VCHR:=LOWER(CHR(VK))
ENDIF
CASE VK>47 .AND. VK<58 .AND. KNUM=.T. // 0-9
VCHR:=CHR(VK)
CASE VK=4
VCHR:=CHR(VK)
CASE VK=19
VCHR:=CHR(VK)
CASE VK=1
VCHR:=CHR(VK)
CASE VK=25
VCHR:=CHR(VK)
CASE VK=7
VCHR:=CHR(VK)
CASE VK=6
VCHR:=CHR(VK)
CASE VK=5
VCHR:=CHR(VK)
CASE VK=24
VCHR:=CHR(VK)
CASE VK=8
VCHR:=CHR(VK)
CASE VK=13
VCHR:=CHR(VK)
CASE VK=27
VCHR:=CHR(VK)
OTHERWISE
VCHR:=""
ENDCASE
GetApplyKey( oGet, ASC(VCHR) )
ELSE
GetApplyKey( oGet, INKEY(0) )
ENDIF
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
return
Daqui pra baixo é igual ao original do CLIPPER.
Parece estranho o que fiz, mas foi necessário. Porque nesses GETs eu queria que pudessem navegar entre os outros GETs, deixando de estar activos quando pressionem a tecla de de navegação (seta pra cima, pra baixo). Mesmo eu estando num GET onde digita-se a senha. Funcionou, super legal. Claro, você vão dizer que é trabalhoso, mas no meu caso resolveu porque meu sistema é MODULAR. Isto é, meu sistema é composto por dezenas de EXEcutáveis. E cada executável cumpre uma função e tem um GETSYS1, GETSYS2. Embora seus sistema não fossem MODULARES, também daria para criar uma opção GENÉRICA que atendesse qulquer questão menos a determina em cada CASE.
Não sei, porque gostamos de achar que o nosso é melhor (eu também estou fazendo isso agora), mas de todas formas, tudo isto é sadio. E espero que os colegas não fiquem bravo comigo, as vezes a verdade doi profundamente. Lindo é ver o conhecimento de TODOS vocês.
Se precisarem, alguma explicação do por quê fiz isto, aquilo no meu fonte. Terei o prazer de explicar.
Um clip-abraço pessoal ! :)Pos