* * * *

Privacy Policy

Blog italiano

Clicca qui se vuoi andare al blog italiano su Lazarus e il pascal.

Forum ufficiale

Se non siete riusciti a reperire l'informazione che cercavate nei nostri articoli o sul nostro forum vi consiglio di visitare il
Forum ufficiale di Lazarus in lingua inglese.

Lazarus 1.0

Trascinare un file nel programma
DB concetti fondamentali e ZeosLib
Recuperare codice HTML da pagina web
Mandare mail con Lazarus
Stabilire il sistema operativo
Esempio lista in pascal
File INI
Codice di attivazione
Realizzare programmi multilingua
Lavorare con le directory
Utilizzare Unità esterne
TTreeView
TTreeview e Menu
Generare controlli RUN-TIME
LazReport, PDF ed immagini
Intercettare tasti premuti
Ampliare Lazarus
Lazarus e la crittografia
System Tray con Lazarus
UIB: Unified Interbase
Il file: questo sconosciuto
Conferma di chiusura di un applicazione
Liste e puntatori
Overload di funzioni
Funzioni a parametri variabili
Proprietà
Conversione numerica
TImage su Form e Panel
Indy gestiore server FTP lato Client
PopUpMenu sotto Pulsante (TSpeedButton)
Direttiva $macro
Toolbar
Evidenziare voci TreeView
Visualizzare un file Html esterno
StatusBar - aggirare l'errore variabile duplicata
Da DataSource a Excel
Le permutazioni
Brute force
Indy 10 - Invio email con allegati
La gestione degli errori in Lazarus
Pascal Script
Linux + Zeos + Firebird
Dataset virtuale
Overload di operatori
Lavorare con file in formato JSON con Lazarus
Zeos ... dietro le quinte (prima parte)
Disporre le finestre in un blocco unico (come Delphi)
Aspetto retrò (Cmd Line)
Lazarus 1.0
Come interfacciare periferica twain
Ubuntu - aggiornare free pascal e lazarus
fpcup: installazioni parallele di lazarus e fpc
Free Pascal e Lazarus sul Raspberry Pi
Cifratura: breve guida all'uso dell'algoritmo BlowFish con lazarus e free pascal.
Creare un server multithread
guida all'installazione di fpc trunk da subversion in linux gentoo
Indice
DB concetti fondamentali e connessioni standard
Advanced Record Syntax
DB concetti fondamentali e DBGrid
DB concetti fondamentali e TDBEdit, TDBMemo e TDBText
Advanced Record Syntax: un esempio pratico
Superclasse form base per programmi gestionali (e non)
Superclasse form base per programmi gestionali (e non) #2 - log, exception call stack, application toolbox
Superclasse form base per programmi gestionali (e non) #3 - traduzione delle form
Superclasse form base per programmi gestionali (e non) #4 - wait animation
Un dialog per la connessione al database:TfmSimpleDbConnectionDialog
Installare lazarus su mac osx sierra
immagine docker per lavorare con lazarus e free pascal
TDD o Test-Driven Development
Benvenuto! Effettua l'accesso oppure registrati.
Aprile 26, 2024, 02:43:19 am

Inserisci il nome utente, la password e la durata della sessione.

19 Visitatori, 0 Utenti

Autore Topic: rilevare la posizione di inserimento del carattere in immissione  (Letto 1185 volte)

petrusic

  • Hero Member
  • *****
  • Post: 589
  • Karma: +0/-0
Dovrei assicurare che caratteri particolari come '=', '{', '}' vadano immessi sempre e soltanto in posizioni rigide di una TEdit.
Ho pensato che potrebbe essere decisiva la conoscenza, in digitazione, dell'esatta posizione del cursore all'interno di una Tedit.Text.
L'interrogazione di tale posizione potrebbe avvenire, a mio avviso  nella procedura KeyPress.

Ho cercato una proprietà di tipo TEdit.Text.index. . ., però senza successo.
Come  fare allora?

Mi creo io un pseudo-indice da modificare di volta in volta che arriva un carattere da inserire o un comando di spostamento Avanti, Indietro, in Cima, in Fondo alla TEdit?
ciao ciao

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:rilevare la posizione di inserimento del carattere in immissione
« Risposta #1 il: Ottobre 31, 2021, 08:27:48 pm »
Ci dovrebbe essere un componente TMaskEdit che svolge già la funzione che chiedi. Provalo.

Ciao.
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

petrusic

  • Hero Member
  • *****
  • Post: 589
  • Karma: +0/-0
Re:rilevare la posizione di inserimento del carattere in immissione
« Risposta #2 il: Novembre 02, 2021, 10:32:28 am »
Ci dovrebbe essere un componente TMaskEdit che svolge già la funzione che chiedi. Provalo.

L'ho già provato, ma non mi ci ci sono trovato.
il Controllo Tedit in questione può ricevere digit numerici, ma anche simboli matematici per immissioni di formule aritmetiche.
In Gambas esisteva la funzione "Eval" che mi permetteva di ricevere anche i suddetti tipi di dati. In ambiente Lazarus FreePascal, non ho trovato niente in merito. Mi sono dovuto perciò organizzare in modo proprio:
Codice: [Seleziona]
procedure TForm2.EImportFormulaKeyPress(Sender: TObject; var Key: char);
var
  decimali, lun, lunSel, p: Integer;

begin
  lun:= Length(EImportFormula.Text);
  case key of
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ',', '.', '=', '{', '}', '(', ')', '+', '-', '*', '/', Char(8):    // Char(8)= VK_Back  (Cancella carattere prima)
    begin
      case key of
        '=':
          begin
            if (Lun > 0) then
            begin
              if (LeftStr(EImportFormula.Text, 1) = '=') then
              begin
                key:= Char(0);
              end;
            end;
          end;
        '{':
          begin
            case lun of
              0:
                begin
                  key:= Char(0);
                end;
            end;
            if (lun >= 1) then
            begin
              if (EImportFormula.Text[1] <> '=') then
              begin
                key:= Char(0);
              end;
              p:= Pos('{', (EImportFormula.Text));
              if (p > 0) then
              begin
                key:= Char(0);
              end;
            end;
          end;
        '}', '(', ')', '+', '-', '*', '/':
          begin
            if (lun < 2) then
            begin
              key:= Char(0);
            end;
            if (LeftStr(EImportFormula.Text, 2) <> '={') then
            begin
              key:= Char(0);
            end;
          end;
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
          begin
            if (lun > 0) then
            begin
              if (LeftStr(EImportFormula.Text, 1) = '=') then
              begin
                if (Copy(EImportFormula.Text, 2, 1) <> '{') then;
                begin
                  key:= Char(0);
                end;
              end;
            end;
          end;
        '.', ',':
          begin
            if (tipoValuta = '£') then
            begin
              key:= Char(0);
            end
            else begin
              p:= Pos(',', EImportFormula.Text);
              if (p > 0) then
              begin
                key:= Char(0);
              end
              else begin
                Key:= ',';
              end;
            end;
          end;
      end;
    end
    else begin
      key:= Char(0);
    end;
  end;
  if (key <> char(0)) then
  begin
    crtUltDig:= key;
  end
  else begin
    crtUltDig:= '';
  end;
end;
In questa procedura  (EImportFormulaKeyPress) mi assicuro che eventuali simboli matematici occupino posizioni obbligate e della possibilità di digitazione di numeri decimali.

Codice: [Seleziona]
procedure TForm2.EImportFormulaChange(Sender: TObject);
var
  i, lun, nuCrtDec, p: Integer;
  conta: Integer = 0;

begin
  lun:= Length(EImportFormula.Text);
  case crtUltDig of
    ',', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
      begin
        nuCrtDec:= ControlloDecimali(EImportFormula.Text);
        if (nuCrtDec > 2) then
        begin
          EImportFormula.Text:= CancUltCrtDig(EImportFormula.Text, nuCrtDec);
        end;
      end;
    '{':
      begin
        if (LeftStr(EImportFormula.Text, 2) <> '={') then
        begin
          EImportFormula.Text:= RightStr(EImportFormula.Text, Length(EImportFormula.Text) - 1);    // annulla soltanto l'inserimento dell'ultimo carattere digitato
        end;
      end;
    '}':
      begin
        for i:= 1 to lun do
        begin
          case EImportFormula.Text[i] of
            '}':
              begin
                conta:= conta + 1;
              end;
          end;
        end;
        if (conta > 1) then
        begin
          CancUltCrtDig(EImportFormula.Text, 0);
        end
        else begin
          if (LeftStr(EImportFormula.Text, 2) <> '={') then
          begin
            EImportFormula.Text:= CancUltCrtDig(EImportFormula.Text, 0);
          end
          else begin
            if (RightStr(EImportFormula.Text, 1) <> '}') then
            begin
              EImportFormula.Text:= CancUltCrtDig(EImportFormula.Text, 0);
            end;
          end;
        end;
      end;
    '(', ')':   // la sua posizione non è vincolante. Occorre però che ci siano tante ')', quante sono le '('
      begin
        if (LeftStr(EImportFormula.Text, 2) <> '={') then
        begin
          EImportFormula.Text:= CancUltCrtDig(EImportFormula.Text, 0);
        end
        else begin
          for i:= 1 to lun do
          begin
            case EImportFormula.Text[i] of
              ')':
                begin
                  numTondeChiuse:= numTondeChiuse + 1;
                end;
              '(':
                begin
                  numTondeAperte:= numTondeAperte + 1;
                end;
            end;
          end;
          if (numTondeChiuse > numTondeAperte + 1) or (numTondeChiuse < numTondeAperte - 1) then
          begin
            CancUltCrtDig(EImportFormula.Text, 0);
          end;
        end;
      end;
    '+', '-', '*', '/':
      begin
        for i:= 1 to (lun - 1) do
        case EImportFormula.Text[i] of
          '+', '-', '*', '/':
            begin
              if (EImportFormula.Text[i - 1] = '+') or (EImportFormula.Text[i - 1] = '-') or (EImportFormula.Text[i - 1] = '*') or (EImportFormula.Text[i - 1] = '/') then
              begin
                CancUltCrtDig(EImportFormula.Text, 0);
                Break;
              end;
              if (EImportFormula.Text[i + 1] = '+') or (EImportFormula.Text[i + 1] = '-') or (EImportFormula.Text[i + 1] = '*') or (EImportFormula.Text[i + 1] = '/') then
              begin
                CancUltCrtDig(EImportFormula.Text, 0);
                Break;
              end;
            end;
        end;
      end;
  end;
end;
In quest'altra (EImportFormulaChange) controllo le formalità sui simboli matematici e, in caso di anomalia richiamo la funzione "CancUltCrtDig" che si occupa della cancellazione dell'ultimo carattere immesso. Controllo anche che le eventuali cifre decimali siano soltanto due, attraverso il richiamo della funzione "ControlloDecimali":
Codice: [Seleziona]
function CancUltCrtDig(StrIniz: String; nuCrtDec: Integer): String;
var
  incrDecr, lun: Integer;
  conta:Integer = 0;
  i: Integer = 0;

  strFin: String;

begin
  lun:= Length(StrIniz);
  if (nuCrtDec > 2) then
  begin
    i:= lun;
    incrDecr:= (-1);
  end
  else begin
    i:= 1;
    incrDecr:= 1;
  end;
  while (StrIniz[i] <> crtUltDig) do
  begin
    conta:= conta + 1;
    i:= i + incrDecr;
  end;
  strFin:= LeftStr(StrIniz,(i - 1)) + RightStr(StrIniz, conta);
  Result:= strFin
end;
//. . .
function ControlloDecimali(strInput: String): Integer;
var
  lun, p: Integer;
  decimali: Integer = 0;

begin
  lun:= Length(strInput);
  p:= Pos(',', strInput);
  if (p > 0) then
  begin
    decimali:= lun - p;
  end;
  Result:= decimali;
end;
Alla fine della digitazione, la formula, viene ricavata in un campo numerico di tipo Real che va a riempire un altro controllo TEdit (EImporto), delle stesse dimensioni e coordinate di quello della formula, per la visualizzazione del totale. Non modifico così il contenuto della TEdit della formula che posso richiamare  per  la correzione di termini aritmetici, non corretti ai fini del risultato.

Può servire a qualcun altro, oltre che a me?  ;)
« Ultima modifica: Novembre 02, 2021, 03:53:36 pm da petrusic »
ciao ciao

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:rilevare la posizione di inserimento del carattere in immissione
« Risposta #3 il: Novembre 02, 2021, 07:22:24 pm »
Interessante ciò che hai svolto, potrebbe essere utile ritengo.

Rispetto all'argomento, cioè rilevare la posizione del cursore o tracciarlo nella TEdit, sinceramente non l'ho mai provato. Ti posso dire che tracciarlo può essere un problema, perchè ad esempio ci si potrebbe spostare con il mouse, e quindi non è sufficiente tracciare la tastiera.

Sarebbe utile secondo me costruire una TEdit specializzata per le formule (tipo cella Excel) .... lo feci più di trent'anni fà in DOS, misto assembler e C con gli INT10 per un programma per computi metrici.

Bhè vediamo se il tempo avanza ...

Ciao
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:rilevare la posizione di inserimento del carattere in immissione
« Risposta #4 il: Novembre 02, 2021, 09:59:33 pm »
Codice: [Seleziona]
program Project1;
{
    Copyright (c) 2011 by Marco van de Voort(marco@freepascal.org)
    member of the Free Pascal development team

    See the file COPYING.FPC, included in this distribution,
    for details about the copyright. (LGPL-with-static-linking-exception)

    Rock bottom example of new evaluator helper function.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
}

//{$mode objfpc}{$H+}
{$mode delphi}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes
  { you can add units after this },
  Symbolic, sysutils;

{$R *.res}

var s : AnsiString;
    a : extended;
    b : integer;

begin
  // quickevaluate('expression',[],[]); evaluates a constant expression to an
  //  extended result

  s:='(5+5+10)*2';
  writeln(s,'=',QuickEvaluate(s,[],[]):10:1);


  // ... but still allows variables:

  a:=2.0;
  b:=3;
  s:='(5+A+10)*B';
  // variable names are case sensitive!
  writeln(s,'=',QuickEvaluate(s,['A','B'],[a,b]):10:1,' with A=',a:0:1,' and B=',b);

 // now let's do that again, but add a symbol (C) that we don't define:

 try
   a:=2.0;
   b:=3;
   s:='(5+A+10)*B+C';
   // variable names are case sensitive!
   writeln(s,'=',QuickEvaluate(s,['A','B'],[a,b]):10:1,' with A=',a:0:1,' and B=',b);
 except
   on E:Exception do
     Writeln('An exception occurred: ',e.message);
   end;
end.

Codice copiato pari pari da una vecchia utility di fpc, presente nella directory:

C:\lazarus\fpc\3.2.0\source\packages\symbolic\examples

(ammettendo che abbiate installato lazarus in c:\Lazarus).

Non è un parser di una TEdit, ma un evaluator .... penso possa esserti utile, e non solo a te.

Ciao
« Ultima modifica: Novembre 02, 2021, 10:02:34 pm da DragoRosso »
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:rilevare la posizione di inserimento del carattere in immissione
« Risposta #5 il: Novembre 02, 2021, 10:13:08 pm »
Un'altra alternativa, ben più vecchia, sarebbe usare le JCL, che però non sono integrate in Lazarus.

Questo fork dovrebbe funzionare con Lazarus: https://github.com/Makhaon/jcl

Nella unit JclExprEval c'è la classe TEvaluator che consente anche lui una valutazione matematica.

Altre classi consentono valutazioni più complesse con variabili  e funzioni (anche ricorsive).

Ciao
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

petrusic

  • Hero Member
  • *****
  • Post: 589
  • Karma: +0/-0
Re:rilevare la posizione di inserimento del carattere in immissione
« Risposta #6 il: Novembre 04, 2021, 07:40:22 pm »
@ DragoRosso

Grazie. Tuttavia, quando riuscirò a far funzionare il mio codice digit con verifica della correttezza formale  della formula, sarò più che soddisfatto.
 
Sto provando ora le mie istruzioni e ... il problema è che, con enorme sorpresa, ho incontrato un errore che, secondo la mia logica, non c'è.  ???
Il passo di programma "anomalo" è il seguente
Codice: [Seleziona]
procedure TForm2.EImportFormulaKeyPress(Sender: TObject; var Key: char);     
. . .
 case key of
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ',', '.', '=', '{', '}', '(', ')', '+', '-', '*', '/', Char(8):    // Char(8)= VK_Back  (Cancella carattere prima)
    begin
 case key of
        '=':
          begin                   
              . . .    // funziona
         end;
        {':
          begin     
               . . .    // funziona
         end;
       '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
          begin
            if (lun > 0) then
            begin
              WriteLn('LeftStr(EImportFormula.Text, 2)= "' + LeftStr(EImportFormula.Text, 2) + '"');  // contenuto: '={'    (corretto)
              if (LeftStr(EImportFormula.Text, 1) = '=') then
              begin
//                if ((Copy(EImportFormula.Text, 2, 1)) <> '{') then;       istruzione modificata con le due successive, per capire l'errore
                striMia:= Copy(EImportFormula.Text, 2, 1);
                if (striMia <> Char(123)) then;   // a questo punto sono sicuro che striMia contiene '{'
                begin
                  key:= Char(0);       //  eppure, inspiegabilmente, viene eseguita questa istruzione ed il numero immesso viene annullato
                end;
              end;
            end;
          end;                                                                           
Il problema nasce con la digitazione del primo carattere numerico, dopo "={" di inizio formula. Infatti, per capire se il numero digitato è interno ad una formula, verifico che i primi 2 caratteri immessi siano proprio "={", altrimenti possono essere accettati solo numeri.

Se la digitazione comprende solo numeri, il codice scritto funziona, se vengono digitati caratteri diversi dai numeri e diversi da "={" come primo e secondo digit, funziona, ma quando dovrei cominciare a vedere comparire i numeri, a partire dal 3° digit, ecco che NON funziona.
ciao ciao

petrusic

  • Hero Member
  • *****
  • Post: 589
  • Karma: +0/-0
Re:rilevare la posizione di inserimento del carattere in immissione
« Risposta #7 il: Novembre 04, 2021, 07:52:26 pm »
Ho risolto subito dopo il mio messaggio, interrogando la posizione di '{' :
Codice: [Seleziona]
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
          begin
            if (lun > 0) then
            begin
              if (LeftStr(EImportFormula.Text, 1) = '=') then
              begin
                p:= pos('{', EImportFormula.Text);
                if (p <> 2) then
                begin
                  key:= Char(0);
                end;
              end;
            end;
          end;                                                                                   

Ora il riconoscimento dei primi due digit ("={") è corretto ed i numeri  immessi dopo vengono presi in carico e mostrati nella Tedit.
 :D
ciao ciao

petrusic

  • Hero Member
  • *****
  • Post: 589
  • Karma: +0/-0
Re:rilevare la posizione di inserimento del carattere in immissione
« Risposta #8 il: Novembre 04, 2021, 10:20:08 pm »
Bene. Ora ho capito, anzi ho trovato l'errore.
Ritornando al gruppo di istruzioni che provocavano l'errore:
Codice: [Seleziona]
procedure TForm2.EImportFormulaKeyPress(Sender: TObject; var Key: char);
. . .
 case key of
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ',', '.', '=', '{', '}', '(', ')', '+', '-', '*', '/', Char(8):    // Char(8)= VK_Back  (Cancella carattere prima)
    begin
      case key of     
        . . .
      '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
          begin
            if (lun > 0) then
            begin
              if (LeftStr(EImportFormula.Text, 1) = '=') then
              begin
//                if ((Copy(EImportFormula.Text, 2, 1)) <> '{') then;       // è il ";" dopo then che ha provocato l'errore
                if ((Copy(EImportFormula.Text, 2, 1)) <> '{') then     // ora l'uscita dalla if è corretta.
                begin
                  key:= Char(0);
                end;
              end;
            end;
          end;

Il ";" dopo then costituiva l'uscita dalla if per "diverso" e, quindi , l'uscita per "uguale" portava alla "key:= Char(0);", annullando così il numero digitato.
Una svista purtroppo dannosa, ma pur sempre una svista. Me ne sono accorto rileggendo il codice, dopo avere interrogato la posizione della "{", perchè non mi spiegavo come mai l'uscita funzionasse così e non come avevo fatto prima. Alla fine l'ho visto ed ho ripristinato il codice iniziale, eliminando il ";".

Vi ho fatto perdere altro tempo nel leggere anche questo messaggio di riflessione, ma era necessario chiarire e spiegare a chi cerca soluzioni cosa può provocare una semplice svista.
 ;)
ciao ciao

SB

  • Scrittore
  • Sr. Member
  • *****
  • Post: 283
  • Karma: +1/-0
Re:rilevare la posizione di inserimento del carattere in immissione
« Risposta #9 il: Novembre 07, 2021, 11:53:55 am »
posizione del cursore all'interno di una Tedit.Text.

TEdit.SelStart

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:rilevare la posizione di inserimento del carattere in immissione
« Risposta #10 il: Novembre 07, 2021, 12:46:07 pm »
Hai ragione, la funzione "SelStart" imposta la posizione del cursore all'interno della TEdit. E pensare che l'ho usato in diversi progetti, ma per selezionare parte del testo di una TEdit (mix di SelStart e SelLength).

In lettura ritorna la posizione del cursore, se non c'è nessuna selezione.

Stò invecchiando  :o
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

 

Recenti

How To

Utenti
Stats
  • Post in totale: 18772
  • Topic in totale: 2233
  • Online Today: 384
  • Online Ever: 900
  • (Gennaio 21, 2020, 08:17:49 pm)
Utenti Online
Users: 0
Guests: 19
Total: 19

Disclaimer:

Questo blog non rappresenta una testata giornalistica poiché viene aggiornato senza alcuna periodicità. Non può pertanto considerarsi un prodotto editoriale ai sensi della legge n. 62/2001.