Newsgroup: it.comp.lang.vo-clipper
Titolo: Ottimizzazione della ricerca incrementale

Ottimizzazione della ricerca incrementale.
Tutti conoscono la ricerca incrementale basata sulla definizione del metodo
EditChange.
Ok, il comportamento normale prevede la definizione dell'indice di ricerca
in base al focus e successiva Seek nel DBase per la visualizzazione del
record nel browser.
Mi chiedevo se esistono delle tecniche per ottimizzare i seguenti
comportamenti anomali:
1)Ho un valore nella clipboard di 15-20 caratteri che intendo incollare in
un campo a ricerca incrementale. La funzione mi esegue 15-20 ricerce anzichč
1.
2) Ho un lettore laser di codici a barre che mi inserisce nella tastiera un
codice di 10-25 caratteri seguito da CR-LF. La funzione mi esegue 15-20
ricerce anzichč 1.
Ho provato ad inserire un Dispatch (un ciclo di Exec...) nell'EditChange ma
non mi accelera la situazione in quanto la funzione di "incolla" e' modale
all'applicazione e non prevede il rilascio dell'esecuzione fintanto che non
e' conclusa. Questo l'ho verificato con un semaforo costruito con una
variabile static che si incrementava nel caso di una ricorsione (possibile
se il Dispatch funzionava a dovere). Ha sempre avuto valore 1.
Voi come suggerite di fare?

Per mia esperienza non e' una buona soluzione usare la ricerca incrementale
attraverso il solo metodo Edichange.
Se gli archivi sono particolrmente grandi e si lavora attraverso la rete
l'utente si trova a dovere attendere vari secondi tra una pressione di un
tasto e l'altra.
Io ho risolto introducendo un timer nel controllo SLE in modo da aggiornare
la ricerca solo se non vengono premuti tasti per piu' di X millisecondi.
In pratica l'utente inizia a scrivere la chiave senza interruzioni e appena
si sofferma per X millisecondi (o secondi) viene aggiornato il browser.
In questo modo il sistema del copia/incolla esegue una sola ricerca come
anche una eventuale lettura da scanner per barcode.
Spero che il suggerimento possa esserti utile ....
Ciao
"pimpa" <xxx@xx.x> ha scritto nel messaggio
news:aunh8.9599$5z3.2...@twister2.libero.it...


 la ricerca solo se non vengono premuti tasti per piu' di X millisecondi.
In quale metodo? Potresti inserire un esempio?

E' un dato di fatto che la ricerca incrementale su di un campo non è il
massimo per applicazioni che operano in rete o su grossi archivi.
Io se posso evitarla lo faccio coolocando un pulsante di ricerca al lato del
campo, se proprio devo farla attendo che la stringa inserita abbia la
lunghezza minima richiesta e poi la faccio partire. In genere si sa quanto
dovrebbe essere lunga la stringa.
Nel caso dei codici a barre è sufficiente far partire la ricerca
all'inserimento dei caratteri di fine riga.
Saluti
                                            Francesco Leo

"pimpa" <xxx@xx.x> ha scritto nel messaggio
news:aunh8.9599$5z3.2...@twister2.libero.it...

PROTECT cLastKey AS STRING
NEL POSTINIT
SetTimer(SELF:Handle(), SEEKTIMER,5000,0)
NEL METODO CLOSE
KillTimer(SELF:Handle(),SEEKTIMER)
METHOD Dispatch(oEvent) CLASS TUAWIN
 LOCAL liReturn AS LONGINT
 LOCAL cKey AS STRING
     liReturn :=SUPER:Diaspatch(oEvent)
  IF oEvent:Message = WM_TIMER
       cKey:=SELF:oDCCerca:TextValue
      IF !SELF:cLastKey == cKey
           KillTimer(SELF:Handle(),SEEKTIMER)
           SELF:cLastKey:=cKey
           SELF:oSFTuoBrowser:Server:Seek(cKey)
           SetTimer(SELF:Handle(), SEEKTIMER,5000,0)
       ENDIF
  ENDIF
RETURN liReturn
DEFINE SEEKTIMER:=6000
Questo per farmi perdonare per la Ricostruzione Indici
Ciao Antonio

Il metodo che suggerisci va benissimo nel caso in cui per eseguire una
ricerca incrementale si apra una finestra ad essa dedicata. Nel caso invece
si voglia eseguire una ricerca incrementale partendo dal testo digitato in
una SLE posta sulla stessa finestra in cui risiedono gli altri normali
controlli con cui si gestiscono i dati di un database le cose si complicano.
Ad ogni evento timer si dovrebbe controllare che il testo contenuto nella
SLE di ricerca non sia cambiato per decidere se eseguire o meno la ricerca e
ci sarebbe comunque sempre un timer attivo finchè non si chiude la finestra.
La soluzione giusta potrebbe essere quella di creare una nuova classe
ereditando dalla SingleLineEdit ed in questa classe gestire i vari eventi in
modo che la ricerca incrementale parta solamente dopo un certo periodo
dall'inserimento dell'ultimo carattere nella SLE. Se non sbaglio questo
sistema era quello suggerito da Marco B.
Il problema è come fare! Io ci ho provato ma non ci sono riuscito. Marco B.
dacce er codice :-)
Ciao a tutti.
Roberto Cordini

Io ho una SLE tutta personalizzata che svolge molte funzioni tra cui anche
quelle per la ricerca incrementale (molte funzioni probabimente neppure ti
servirebbero e sono comunque legate ad un particolare tipo di Window creata
da me). Non posso mandarti tutto il codice ma posso darti le indicazioni su
come procedere per realizzarne una tutta tua ...
1) Prima di tutto devi attivare un timer legato alla sle (NON ALLA FINESTRA
CHE LA CONTIENE). Per fare questo e' sufficiente nell'Init della classe
inserire   SetTimer(SELF:Handle(),1,500,NULL_PTR)
2) Devi riscrivere il metodo DISPATCH della tua classe SLE. Nel metodo
dispatch devi intercettare la pressione dei tasti cuccando l'evento
WM_KEYDOWN e l'evento del timer con l'enveto WM_TIMER.
3) Attraverso una variabile di istanza della tua classe SLE ed il risultato
del GetTickCount() puoi imbastire un sistema di controllo del Timeout dopo
la pressione dell'ultimo tasto. Basta, alla pressione di ciascun tasto,
memorizzare il risultato del GetTickCount() nella varaiabile di istanza e ad
ogni evento timer verificare quanti millisecondi sono trascorsi dall'ultima
pressione.
4) Se i millisecondi trascorsi sono superiore ad una certa soglia, ed il
valore contenuto nella SLE è differente da quello dell'ultimo seek, fai
semplicemente scattare una chiamata ad un metodo CallBack della classe owner
(la finestra che contiene il controllo) semplicemente con il seguiente
codice :
if IsMethod(self:Owner,#MYSEEK)
 send(self:Owner,#MYSEEK)
endif
Naturalemente la classe owner deve avere un metodo di gestione chiamato
MySeek ....
Come fatto notare da Antonio questo sistema utilizza un Timer ma se ci pensi
bene non ci sono vie di uscita, ed e' l'unico sistema praticabile. Una
alternativa, che ho sperimentato ma ho abbandonato, è la gestione della
temporizzazione attraverso un Thread. In questo modo eviti il timer ma
succhi processore all'applicazione (secondo me il gioco non vale la candela
....).
Se sulla maschera di ricerca hai molti controlli di questo tipo, perche'
devi eseguire ricerche con piu' chiavi, puoi ovviare al problema di troppi
timer prevedendo un semplice metodo nella SLE che scateni un evento timer.
In questo modo puoi attivare il timer reale solo sulla finestra che contiene
i controlli e fare in modo che chiami il metodo di ciascuno di essi.
Se sulla finestra hai solo una SLE ed utilizzi una serie di radiobuttons per
selezionare le chiavi di ricerca il gioco e' fatto .....
Ciao, Marco
"Robby" <roberto...@NOXSPAMiol.it> ha scritto nel messaggio
news:a65pda$rmv$1...@zamboni.dsnet.it...



cut cut
Ciao Marco grazie per la dettagliatissima risposta. Nelle mie prove avevo
cercato di utilizzare un sistema simile a quello che Tu mi hai indicato. Ma
poi, all'ennesimo crash e conseguente reboot, leggermente demoralizzato ho
lasciato perdere. Ci riproverò sicuramente, forte anche dei tuoi
suggerimenti.
Grazie ancora.
Un saluto a tutti.
Roberto Cordini

Vai tranquillo .... il sistema puo' funzionare perfettamente (e' piu' di un
anno che lo utilizzo senza problemi).
Ciao
"Robby" <roberto...@NOXSPAMiol.it> ha scritto nel messaggio
news:a67hgn$vrm$1...@zamboni.dsnet.it...


 Ma poi, all'ennesimo crash e conseguente reboot...
non dirmi che lavori in Win 98!


Ebbene si cos'altro potrei desiderare ? .... la Manuela Arcuri?
Ciao.
Roberto Cordini

Sarebbe meglio............
"Robby" <roberto...@NOXSPAMiol.it> ha scritto nel messaggio
news:a67sdr$rs$1...@zamboni.dsnet.it...


 Ebbene si cos'altro potrei desiderare ? .... la Manuela Arcuri?
Guai se cosi' non fosse!