Página 1 de 1

Contar caracteres no Memoedit() do Xharbour 1.2.1

Enviado: 14 Dez 2015 23:28
por Ceb
Boa noite!

Preciso editar um texto do zero ou pegá-lo num campo de algum dbf, porém, preciso saber a quantidade de caracteres assim que chamar o Memoedit() e a medida de vou editando, ele vai atualizando este valor, considerando espaços dentro do texto. Resumindo, preciso limitar X caracteres para estes texto.

Desde já, agradeço pela ajuda.

Att,

Ceb

Contar caracteres no Memoedit() do Xharbour 1.2.1

Enviado: 15 Dez 2015 02:30
por Vander

Contar caracteres no Memoedit() do Xharbour 1.2.1

Enviado: 15 Dez 2015 11:12
por asimoes
A função Len() faz o que você está querendo.

Ex.>

Código: Selecionar todos

cVar:="HELLO WORLD"

nLen:=Len(cVar)

cVar += " ALO MUNDO"

nLen:=Len(cVar)

cVar += TABELA->Campo

nLen:=Len(cVar)

? nLen

If nLen > 100
   Alert("Ops chegou a 100 caracteres")
Endif

Contar caracteres no Memoedit() do Xharbour 1.2.1

Enviado: 15 Dez 2015 13:56
por Jairo Maia
Olá Pessoal,

Creio que isso não é possível.

Mesmo considerando que é possível saber a linha e coluna do cursor no texto, nem mesmo assim daria para fazer esse controle. Por exemplo se tentar controlar pelo número de linhas e número de colunas na UDF (User defined Function), a linha e coluna é a linha e coluna do cursor. Então se após digitar algumas linhas se o usuário voltar o cursor e continuar digitando, o texto ficará maior que o pretendido, bem como ele pode acrescentar conteúdo de uma variável de um campo memo já existente.

Se o limite é realmente necessário usando o MemoEdit(), não há outra forma a não ser colocá-lo dentro de um laço, e checar se excedeu ou não após sair do memo, tratar, e se for o caso emitir a mensagem ao usuário para corrigir e dar um loop. Tentando explicar seria algo como isso:

Código: Selecionar todos

Function Main()
  
 Local nMeuLimite := 100 

 Do While .t.      

  cTexto := MemoEdit( cTexto, 1, 1 , MaxRow()-1, MaxCol()-1, .T., "FuncaoDoUsuario" )

  cTexto := RTrim( cTexto )

  If Len( cTexto ) > nMeuLimite
   Hb_Alert( "Limite Excedido. Máximo permitido: " + Hb_NToS( nMeuLimite ) )
   Loop
  Else
   Replace cCampoMemo With cTexto
  EndiF

  Exit

 EndDo

Return Nil

Contar caracteres no Memoedit() do Xharbour 1.2.1

Enviado: 15 Dez 2015 17:01
por asimoes
Outra opção seria criar Gets considerando o tamanho máximo a ser digitado:

Ex.: Só poderá digitar até o limite de 150 caracteres.

Código: Selecionar todos

cGet1:=Space(50)
cGet2:=Space(50)
cGet3:=Space(50)

@ 10,00 GET cGet1 PICTURE "@!"
@ 11,00 GET cGet2 PICTURE "@!"
@ 12,00 GET cGet3 PICTURE "@!"
READ


Contar caracteres no Memoedit() do Xharbour 1.2.1

Enviado: 15 Dez 2015 17:43
por Eolo
Creio que isso não é possível.
É possível, sim.

Quando vc inclui uma função de usuário, ela passa a controlar a Memoedit, então dá pra checar em tempo real o limite de caracteres. Eu uso isso campos memo.

Um exemplo, simples e incompleto:

(é só um exemplo, não é pra copiar e colar. O exemplo no help do xHarbour tem o que falta)

Código: Selecionar todos

*...
cTexto:=MemoEdit(cTexto,1,1,MaxRow()-1,MaxCol()-1,.T.,"XPTO" )
*...

function xpto
priv tam:=len(cTexto), limite:=100
priv l:=laskey()
if l=… A_Z, 0_9 ou outros caracteres permitidos
  if (tam+1)>limite
    * Mensagem: Limite atingido
    Retu 32 
  else  
    tam:=tam+1
  endi
elseif l=8 // backspace
   if tam>0
     tam=tam-1
   endi
endi
* faltam os outros RETU...
etc.

Contar caracteres no Memoedit() do Xharbour 1.2.1

Enviado: 15 Dez 2015 20:07
por Jairo Maia
Olá Eolo,

Isso cai no que eu disse anteriormente. Mas se houver algum exemplo que eu possa em tempo de execução, ou seja, em tempo de digitação avisar sobre o limite, passarei a usar. Seria muito legal.

Contar caracteres no Memoedit() do Xharbour 1.2.1

Enviado: 15 Dez 2015 20:40
por Eolo
Tá no exemplo que eu postei.

Seguinte: quando vc inclui uma função de usuário, tudo o que for digitado na janela do Memoedit passa pelo controle da função, que aí retorna alguma coisa pro Memoedit.

Então, no meu exemplo, se você digita a letra J, a variável tam assume 1, a Memoedit mostra o J na janela e continua a execução (iddle). Em seguida, vc digita A e tam vira 2. Digita E, indevidamente, e tam vira 3. Mas aí vc corrige, pressiona Backspace, o E é apagado e tam volta pra 2. Etc etc.

Quando vc tecla CRTL W ou alguma outra tecla pra salvar e sair (eu uso F10), a função de usuário avisa a Memoedit que é pra encerrar o jogo.


Então, essa variável tam, controlada pela função do usuário, é quem vai dizer quando o limite (que vc definir) for atingido.

1. No meu exemplo, se tam+1 for maior que o limite, você refuga a entrada e soca um alerta na tela: “limite atingido”. Esse alerta é gerado dentro da função de usuário.

2. Quer ver quantos caracteres são, à medida em que forem digitados, em tempo real? Inclua “@24,0 say tamanho” no final da função de usuário. A cada letra digitada, o número vai mudar.

Não entrei em muitos detalhes, mas a coisa é bem simples.

Contar caracteres no Memoedit() do Xharbour 1.2.1

Enviado: 16 Dez 2015 12:24
por Jairo Maia
Olá Eolo,

Deu certo, estabelecendo alguns critérios:

1 - Neutralizar a tecla INSERT, ficando permanente no modo de INSERÇÃO;
2 - Neutrlaizando a tecla DELETE, ficando a deleção exclusivamente pela BACKSPACE. Isso porque se não neutralizá-la, o usuario pode posicionar-se no final do texto, pressionar DELETE e depois inserir caracteres tantas quantas vezes pressionou DELETE, ficando o texto maior que o desejado.

Abaixo a adaptação do exemplo do manual e funcionando:

Código: Selecionar todos

#include "Inkey.ch"
#include "Memoedit.ch"

STATIC slChanged := .F.

PROCEDURE Main( cFileName )
      Local cText, lInsert, nk_Ins, nk_del
      Private nLenText, nMaxLen := 45  // limitando a 45 caracteres...
      
      nk_Ins := SetKey( K_INS, { || Nil } )  // neutraliza INSERT
      nk_del := SetKey( K_DEL, { || Nil } )  // neutraliza DELETE
      
      lInsert := Set( _SET_INSERT, .T. )  // tem que ser permanente, nao pode permitir sobreposicao...

      Clear Screen
      
      cText := "Teste de limitacao de texto no MemoEdit."
      nLenText := Len( cText )

      @ 0, 0 TO MaxRow(), MaxCol() DOUBLE

      cText := MemoEdit( cText, 1, 1 , MaxRow()-1, MaxCol()-1, .T., "USERFUNC" )

      Hb_Alert( cText )
      //Replace cCampoMemo With cText

      Set( _SET_INSERT, lInsert )  // retorna estado de INSERT
      SetKey( K_INS, nk_Ins )      // restaura tecla INSERT
      SetKey( K_DEL, nk_del )      // restaura tecla DELETE

      Clear Screen

   RETURN


   FUNCTION UserFunc( nMode, nRow, nCol )
      LOCAL nKey  := LastKey()
      LOCAL nRet  := ME_DEFAULT
      LOCAL cInfo := ""

      DO CASE
      //CASE nMode == ME_INIT
         //Set( _SET_INSERT, .F. )  // start in overstrike mode

      CASE nMode == ME_IDLE

         If nKey = K_BS           // se pressionou BACKSPACE,
           nLenText--             // decrementa nLenText...
         ElseIf nKey > 31 .AND. nKey < 256
           nLenText++
           If nLenText > nMaxLen  // seatingiu limite, bloqueia...
             Hb_Alert( "Limite excedido. Maximo permitido: " + Hb_NToS( nMaxLen ) )
             Clear Typeahead      //limpa teclado
             Hb_KeyPut( K_BS )    // remove ultimo caractere digitado
             Return 0             // volta ao texto 
           EndIf
         EndIf

          slChanged := .T.

         cInfo := "[row: " + LTrim(Str(nRow))
         cInfo += " col: " + LTrim(Str(nCol))+"]"
         cInfo += Chr(205)+Chr(205)

         cInfo += "[Ins]"

         IF slChanged
            cInfo += Chr(205)+Chr(205)+"[Chg]"
         ENDIF

         @ MaxRow(), 2 SAY cInfo + Replicate(Chr(205),6)

      CASE nMode == ME_UNKEY .OR. nMode == ME_UNKEYX
         // buffer is changed
         slChanged := ( nMode == ME_UNKEYX )

         DO CASE
         //CASE nKey IN { K_ALT_W, K_CTRL_W, K_ESC }
         CASE AScan( nKey, { K_ALT_W, K_CTRL_W, K_ESC } ) > 0
            nRet := ME_IGNORE     // ignore default termination keys

         CASE nKey == K_ALT_S
            nRet := K_ALT_W       // Save with Alt+S

         CASE nKey == K_ALT_C
            nRet      := K_ESC    // Cancel with Alt+C
            slChanged := .F.
         ENDCASE

      ENDCASE

   RETURN nRet

Contar caracteres no Memoedit() do Xharbour 1.2.1

Enviado: 16 Dez 2015 16:52
por asimoes
Se o que for digitado aceitar somentes letras e números:

IsAscii( "ABC123" )

ElseIf nKey > 31 .AND. nKey < 256

Por

ElseIf IsAscii(Chr(nKey))

Contar caracteres no Memoedit() do Xharbour 1.2.1

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

Questão interessante a apresentada neste tópico, que mostra como é difícil trabalhar com uma "caixa preta", sem ter acesso ao buffer de edição da função.

Outra opção, alem da apresentada pelo Jairo, seria criar uma MemoEdit() customizada, utilizando o fonte disponível no Github (Copyright 2000 Maurilio Longo <maurilio.longo@libero.it>).

Contar caracteres no Memoedit() do Xharbour 1.2.1

Enviado: 16 Dez 2015 19:56
por asimoes
O autor do tópico ainda não se manifestou em relação as soluções apresentadas, inclusive será que ele quer a solução para o xharbour 1.2.1?

Contar caracteres no Memoedit() do Xharbour 1.2.1

Enviado: 16 Dez 2015 23:25
por Ceb
Boa noite!

Primeiramente quero deixar aqui o meu muito obrigado ao Vander, Asimoes, Jairo, Eolo e Alxsts. Quero que saibam também, que apreciei cada palavra que vocês postaram aqui e que todas, sem exceção foram de grande valia para que eu chegasse a uma decisão.

Das sugestões apresentadas, a do Eolo era a mais provável, mas, conforme o Jairo relatou, haveria necessidade de estabelecer alguns critérios para que o controle funcionasse corretamente. Porém, a edição sem usar DELETE e BACKSPACE iria obrigar o(s) usuário(s) a se adaptar(em) e surgiriam vários pedidos para habilitar tais teclas.

Então, considerando o tempo que tenho para disponibilizar tal recurso, segui o que me parecia se encaixar mais dentro de minhas limitações, ou seja: conforme o Jairo sugeriu acima, eu coloquei o memoedit() dentro de um loop e aviso que XX caracteres ultrapassaram o limite de XX caracteres e volta a edição até que o usuário ajuste o texto.

Obs: antes de contar/avisar que o texto excedeu o limite de caracteres, eu substituo alguns do texto ex: chr(13)+chr(10) por " ", chr(32)+chr(32) por " " e chr(141)+chr(10) por "", fazendo uso do StrTran.

Antes que eu esqueça, a finalidade do uso do Memoedit() é para editar/criar uma mensagem curta para envio de SMS por Http.

Att,

Ceb