Página 1 de 5

Cancelar Operação

Enviado: 27 Jan 2009 13:35
por Netavin
Bom dia pessoal !
Gostaria de um parecer/opinião.
Em minhas rotinas, para cancelar uma operação, tenho empregado o seguinte:
@ 10,10 Say "Informe o código: " get nvar Valid ....
read
If lastkey() = 27
... aviso
use
exit
endif
Porém eu uso isto tambem após os demais Get´s ( de uma inclusão por exemplo ou alteração ).
Haveria a necessidade disto ? ... ou bastaria apenas após o primeiro Read ?

Obrigado !!

[]´s
Netavin

Re: CANCELAR OPERAÇÃO

Enviado: 27 Jan 2009 14:16
por Maligno
Não entendi muito bem. Haveria necessidade de que? Você fala do teste da tecla ESC? Se for, eu uso sempre. E coloco o READ dentro de um WHILE, pois se a resposta for não para cancelar, o comando volta ao topo dos GETs. Mas os GETs ficam fora da malha.

Re: CANCELAR OPERAÇÃO

Enviado: 27 Jan 2009 14:41
por Eolo
Se você tem diversos GETs e o READ, quando vc tecla ESC de qualquer GET, o READ é terminado e o programa continua depois dele.

Uma função que ajuda é a UPDATED(), que retorna .T. se algum GET sofreu alteração e .F. ao contrário. Então, se o usuário saiu com ESC e UPDATED()=.T., é sinal que ele alterou alguma coisa em algum GET e está saindo sem gravar a alteração. Neste caso, eu apresento uma mensagem pedindo que ele confirme se quer mesmo abandonar as alterações.

Um exemplo:

Código: Selecionar todos

set key -9 to F_GRAVA
set confirm on
vcampo1:=campo1
vcampo2:=campo2
do whil .t.
  @10,10 get vcampo1
  @12,10 get vcampo2
  read
  altera=updated()
  lk:=lastkey()
  if lk=-9 .and. altera=.t. // GRAVAR
        repl campo1 with vcampo1
        repl campo2 with vcampo2
        exit
     endi
   elseif lk=27 .and. altera=.f.
      exit
   elseif lk=27 .and. altera=.t.
      do whil .t.
          * mensagem: Sai sem gravar ALTERAÇÕES?
          inkey(0)
          lk2:=upper(chr(lastkey()))
          if lk2$"SN"
              exit
          endi
      endd
      if lk2="S"
          exit
      endi
  endi
endd

function F_GRAVA
clea gets

Re: CANCELAR OPERAÇÃO

Enviado: 27 Jan 2009 14:58
por Eolo
Esqueci de uma coisa: não sei porque, mas a função UPDATED() só é atualizada se vc sair do GET com ENTER. Se vc por ex alterar algo em VCAMPO1 e teclar ESC, a função UPDATED() não é atualizada.

A saída que eu encontrei (não sei se a melhor...) foi vincular a tecla ESC a uma função. Veja o mesmo código acima, complementado com isso.

Código: Selecionar todos

set key -9 to F10
public altera:=.f.
set confirm on
vcampo1:=campo1
vcampo2:=campo2
set key 27 to EXCAPE
do whil .t.
  @10,10 get vcampo1
  @12,10 get vcampo2
  read
  altera=updated()
  lk:=lastkey()
  if lk=-9 .and. altera=.t. // GRAVAR
        repl campo1 with vcampo1
        repl campo2 with vcampo2
        exit
     endi
   elseif lk=27 .and. altera=.f.
      exit
   elseif lk=27 .and. altera=.t.
      do whil .t.
          * mensagem: Sai sem gravar ALTERAÇÕES?
          inkey(0)
          lk2:=upper(chr(lastkey()))
          if lk2$"SN"
              exit
          endi
      endd
      if lk2="S"
          exit
      endi
  endi
endd
altera:=.f.
set key 27 to

function F10
clea gets

function EXCAPE
if updated()
  altera=.t.
endi
clea gets

Cancelar Operação

Enviado: 19 Dez 2015 18:51
por microvolution
olá pessoal, no meu caso, eu tô querendo quase a mesma coisa...
só que no lugar de voltar ao topo da lista de gets, tem como voltar no mesmo get?
exemplo:
-----
CLIENTE COD:
NOME:
ENDEREÇO:
----
neste momento é pressionado a tecla ESC, aí vem a pergunta:
"deseja sair sem gravar?"
se sim:
exit
se não: RETORNA AO GET onde foi acionado o ESC.
========

É possível isso em clipper ou agora em harbour com suas libs?
vlw!

Cancelar Operação

Enviado: 19 Dez 2015 21:05
por JoséQuintas
O READ é pra receber a digitação de informações.
Se durante esta digitação o usuário teclar ESC, significa que abandonou isto.

Um próximo READ será uma nova digitação.
E na nova digitação, o usuário também poderá optar por teclar ESC.

São digitações distintas, em cada uma delas o usuário pode ou não digitar ESC.

O que o seu programa vai fazer quando o usuário teclar ESC, é decisão sua, e vai ter que colocar no fonte.

Cancelar Operação

Enviado: 19 Dez 2015 21:13
por JoséQuintas
Sobre a outra pergunta do ESC.
É difícil, porque ESC já abandona o que for digitado, e reseta a posição dos GETs.

Talvez alterar dentro da GETSYS, aonde analisa o ESC, assim nem sai dos GETs.

Em todo caso, teste com READ SAVE, que não destrói os GETs

Apenas exemplo, vai ter que testar

Código: Selecionar todos

   @ 1, 0 GET ALGUMACOISA
   DO WHILE .T.
         READ SAVE
         IF Lastkey() == K_ESC
             IF .NOT. MsgYesNo( "Abandona"? )
                LOOP
             ENDIF
         ENDIF
       EXIT
   ENDDO
   GetList := {}   

Cancelar Operação

Enviado: 20 Dez 2015 13:22
por microvolution
isso eu já faço há muitos anos, mas, não dá o resultado esperado!
eu descobri (mexendo no harbourdoc.com.br) as seguintes funções/classes que são mais do que um simples comando GET:
menu:UserInterface/GetSys:

Código: Selecionar todos

EraseGetMsg()
Get()
GetActive()
GetApplyKey()
GetClrBack()
GetClrFore()
GetClrPair()
GetDoSetKey()
GetNew()
GetPairLen()
GetPairPos()
GetPostValidate()
GetPreValidate()
GetReader()
e dentro da sub-pasta API:

Código: Selecionar todos

__Get()
__GetA()
__GetListActive()
__GetListLast()
__GetListSetActive()
__GetMessage()
__GetMsgPrf()
Infelizmente no harbourdoc e em nenhum lugar achei alguma referência (user guide) dessas funções, que podem ser a solução não só pra mim, mas, pra todos que sabem dessa limitação antiga do clipper, que talvez no harbour os desenvolvedores já tenham resolvido.

vlw e abraços!

Cancelar Operação

Enviado: 20 Dez 2015 14:26
por JoséQuintas
Talvez alterar dentro da GETSYS, aonde analisa o ESC, assim nem sai dos GETs.

A GETSYS é a rotina que processa os GETS.
Desde os tempos do Clipper, pode ser substituída.
Lá tem todo funcionamento dos GETS, inclusive o que está perguntando.

Fazendo sua própria getsys, talvez baste alterar esta parte:

Código: Selecionar todos

   CASE ( nKey == K_ESC )
      IF ( SET( _SET_ESCAPE ) )

	 oGet:undo()
	 oGet:EXITState := GE_ESCAPE

      ENDIF

Usar INKEYFILTER também poderia ser uma opção, mas vai ter uso mais limitado.

Cancelar Operação

Enviado: 20 Dez 2015 16:32
por microvolution
falou tudo grego ... rsrs

Cancelar Operação

Enviado: 20 Dez 2015 16:59
por JoséQuintas
No Clipper ou no Harbour existe um fonte com o nome GETSYS.PRG
Tem todo funcionamento do GET.
O fonte é disponível justamente pra poder alterar do jeito que quiser, fazendo os GETs funcionarem do jeito que quiser.

Cancelar Operação

Enviado: 21 Dez 2015 14:28
por Jairo Maia
Olá Pessoal,

Veja também uma opção usando BEGIN/END SEQUENCE e permutando a tecla ESC na seção do READ onde isso se faz necessário:

Código: Selecionar todos

#include "inkey.ch"

//Function Main()  // descomente se for compilar em Harbour
  Local cTeste := Space(10)
  Local k_esc := SetKey( K_ESC, { || PodeSair() } )

  Clear Screen
  
  Begin Sequence

   @ 12, 20 Say "Digite algo ou ESC para sair " GET cTeste Pict "@!"
   READ
   
  End Sequence

  SetKey( K_ESC, k_esc )  // restaura ESC antes de sair

Return Nil

Function PodeSair()
 If Hb_Alert( "Deseja Sair?", { "Nao", "Sim" } ) = 2
  Break
 EndIf
Return Nil  // tem que ser Nil

Cancelar Operação

Enviado: 21 Dez 2015 19:26
por alxsts
Olá!

Segue outra sugestão:

Código: Selecionar todos

#include "inkey.ch"

FUNCTION Main()

   LOCAL aGets
   LOCAL GetList := {}
   LOCAL oGet
   LOCAL nPos
   LOCAL nLen
   LOCAL lLastExit := READEXIT(.T.)
   
   RELEASE GetList
   
   SetMode( 25,80)

   CLS

   aGets := AFill( Array( 5 ), Space(20) )
   
   @ 10,10 Say "Campo 1" Get aGets[ 1 ]
   @ 12,10 Say "Campo 2" Get aGets[ 2 ]
   @ 14,10 Say "Campo 3" Get aGets[ 3 ]
   @ 16,10 Say "Campo 4" Get aGets[ 4 ]
   @ 18,10 Say "Campo 5" Get aGets[ 5 ]

   nLen := Len( GetList )
   
   nPos := 1
   
   WHILE ( nPos <= nLen )
      oGet := GetList[ nPos ]
      
      ReadModal( { oGet } )

      nKey := Lastkey()
      
      DO CASE
         CASE nKey == K_ESC
            IF Alert( " Cancelar ? ", {" Nao ", " Sim " }, "W+/B" ) == 2
               EXIT
            ELSE
               LOOP
            ENDIF
         CASE nKey == K_DOWN .OR. nKey == K_TAB .OR. nKey == K_ENTER
            nPos++
         CASE nKey == K_UP
            nPos := Max( --nPos, 1 )         
      END CASE
   ENDDO

   GetList := {}
   
   READEXIT(lLastExit)
   
   RETURN NIL
//------------------------------------------------------------------------------

Cancelar Operação

Enviado: 22 Dez 2015 20:51
por microvolution
olá pessoal!
Diante de todos os comentários aqui (testes e exemplos) e durante vários dias de pesquisas...
juntei tudo e comecei a fazer o meu CANCELAR ESC dessa forma:

Código: Selecionar todos

Local escape
...
sequencia de @say GETs
...
escape := hb_SetKey( K_ESC, {|| escapar_ou_continuar () } )
readexit (.t.)
read
readexit (.f.)
hb_SetKey( K_ESC, escape )

Código: Selecionar todos

FUNC escapar_ou_continuar ()
   LOCAL lRetorna := .f.
   if .not. CONFIRMA ('Deseja realmente cancelar sem concluir', 6 ,'SiCCA v3.6 - Tecla <ESC> foi pressionada ???') == 1
      lRetorna := .t.
   endif
RETU lRetorna
Espero que funcione pra todos!
pra mim já está funcionado...
só tem um desconforto:
por exemplo no meu ACHOICE, já existia uma rotina que pra confirmar todos os produtos cadastrados, eu usava o LastKey() ESC... agora ele não mais funciona, pois cai é na mensagem de CONFIRMA (acima mencionada).
Então, estou tendo que adaptar para uma tecla de FUNÇÃO QUALQUER...
vlw!

Cancelar Operação

Enviado: 24 Dez 2015 21:52
por JoséQuintas
Não entendi como o lRetorna faz sair dos gets.

Em todo caso, testei isto e funciona.
Bastaria trocar READ por MyRead()

Código: Selecionar todos

#include "inkey.ch"

PROCEDURE Main

   SetMode( 25, 80 )
   CLS
   mNome := Space(10)
   @ 5, 5 GET mNome
   MyRead()
   RETURN

FUNCTION MyRead()
   SET ESCAPE OFF
   SET KEY K_ESC TO ExitFromRead
   READ
   SET KEY K_ESC TO
   SET ESCAPE ON
   RETURN NIL

FUNCTION ExitFromRead()

   LOCAL nKey
   
   @ 22, 0 SAY "Sair?"
   nKey := 0
   DO WHILE .NOT. Upper( Chr( nKey ) ) $ "SN"
      nKey := Inkey(0)
   ENDDO
   @ 22, 0 SAY "     "
   IF Upper( Chr( nKey ) ) == "S"
      SET ESCAPE ON
      SET KEY K_ESC TO
      KEYBOARD Chr( K_ESC )
   ENDIF
   RETURN NIL
Explicando o funcionamento:

MyRead) chama uma rotina que mexe com a configuração do ESC, faz o READ, e retorna à configuração original.
Com SET ESCAPE OFF, o ESC não sai do GET
Com SET KEY K_ESC, teclar o ESC chama a função
A função chamada por K_ESC reativa a saída com ESC e simula teclar ESC caso responda sim.

Na rotina de GETs normal, só testar se a última tecla pressionada foi ESC.
Pelo menos nessa parte fica igual todo mundo.