* * * *

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.
Novembre 25, 2024, 11:31:51 am

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

38 Visitatori, 0 Utenti

Autore Topic: Come faccio a...  (Letto 6549 volte)

mmxngg

  • Newbie
  • *
  • Post: 25
  • Karma: +0/-0
Come faccio a...
« il: Febbraio 20, 2012, 05:20:01 pm »
- Da lontanissimi ricordi del pascal so che era possibile testare il valore di una sottostringa così : Stringa[2:3] = 'ABC'. Mi da errore in fase di compilazione. Esiste in maniera diversa da quella che ricordo o me lo sono inventato per facilitarmi la vita ?  ;D
- Questa è un po più tosta. Ho parecchie form che sostanzialmente contengono gli stessi componenti e anzichè scrivere lo stesso codice di gestione per ognuna ho implementato un sistema generico sugli eventi e fin qui tutto bene. Il problema è che in alcuni casi vorrei che fosse eseguito anche del codice specifico (in sostanza una specie di eredietarietà a runtime). Sono riuscito a farlo sul componente Application e ho visto che c'è qualcosa anche per gli altri componenti su alcune proprietà / eventi ma non su tutti. C'è un sistema ?

Allengo parte del codice (con un minimo di commento) per rendere meglio l'idea :

Codice: [Seleziona]
// Richiamato dall'evento OnCreate di ogni form
procedure TFormMain.GenericCatchSettings(Sender: TObject);
var
  N: Integer;
begin
  with (TForm(Sender)) do
    for N := $0 to Pred(ComponentCount) do
      case (Components[N].ClassName) of
        'TTrackBar': begin
          TTrackBar(Components[N]).OnChange := @GenericTBChange;
        end;
        'TStaticText': begin
          TStaticText(Components[N]).OnMouseDown := @GenericSTMouseDown;
          TStaticText(Components[N]).OnMouseMove := @GenericSTMouseMove;
        end;
      end;
end;

// Per ogni componente static text cerco il rispettivo trackbar
procedure TFormMain.GenericSTMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var
  N, Delta: Integer;
  MNewPos: TPoint;
  TBName: string;
begin
  if (Shift = [ssLeft]) then
  begin
    GetCursorPos(MNewPos);
    Delta := (MNewPos.X - MOldPos.X) + (MNewPos.Y - MOldPos.Y);
    MOldPos := MNewPos;
    TBName := 'TB' + Copy(TStaticText(Sender).Name, $3, Length(TStaticText(Sender).Name) - $2);
    with (TForm(TStaticText(Sender).Owner)) do
      for N := $0 to Pred(ComponentCount) do
        if (Components[N].Name = TBName) then
          TTrackBar(Components[N]).Position := TTrackBar(Components[N]).Position + Delta;
  end;
end;

procedure TFormMain.GenericSTMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  GetCursorPos(MOldPos);
end;

// Qui vorrei che fosse eseguito questo codice + quello eventualmente presente nel componente
procedure TFormMain.GenericTBChange(Sender: TObject);
var
  STName: string;
  N: Integer;
begin
  STName := 'ST' + Copy(TTrackBar(Sender).Name, $3, Length(TTrackBar(Sender).Name) - $2);
  with (TForm(TTrackBar(Sender).Owner)) do
    for N := $0 to Pred(ComponentCount) do
      if (Components[N].Name = STName) then
        TStaticText(Components[N]).Caption := IntToStr(TTrackBar(Sender).Position);
end;

// Il codice da eseguire associato al componente TBProva
procedure TFormMain.TBProvaChange(Sender: TObject);
begin
  ShowMessage('Prova');
end;

In pratica anzichè assegnare l'evento con Evento := @NomeProc non c'è una specie di AddHandleOn qualcosa ?

xinyiman

  • Administrator
  • Hero Member
  • *****
  • Post: 3277
  • Karma: +12/-0
Re:Come faccio a...
« Risposta #1 il: Febbraio 20, 2012, 10:55:46 pm »
Per quanto riguarda il punto 1 puoi usare questo codice:
Codice: [Seleziona]
function EstraiStringa(StringaIn: string; Da: integer; A: integer): string;
var
     i: integer;
     ret: string;
begin
          ret:='';
          for i:=Da to A
                ret:=ret + StringaIn[i];
          EstraiStringa:=ret;
end;
Per il secondo problema devo fare delle ricerche!
Ieri è passato, domani è futuro, oggi è un dono...

bonmario

  • Hero Member
  • *****
  • Post: 1360
  • Karma: +11/-1
Re:Come faccio a...
« Risposta #2 il: Febbraio 21, 2012, 07:56:08 am »
Oppure usare la funzione copy http://www.delphibasics.co.uk/RTL.asp?Name=Copy


Ciao, Mario

mmxngg

  • Newbie
  • *
  • Post: 25
  • Karma: +0/-0
Re:Come faccio a...
« Risposta #3 il: Febbraio 21, 2012, 09:46:48 am »
Si alla fine ho usato la funzione Copy mentre non ho ancora trovato niente per risolvere il secondo problema se non ripristinare l'evento di default (quello assegnato in fase di design) e li richiamare anche quello generico.

Microges2000

  • Global Moderator
  • Full Member
  • *****
  • Post: 130
  • Karma: +1/-0
    • Power of Nature
Re:Come faccio a...
« Risposta #4 il: Febbraio 21, 2012, 02:46:08 pm »
Per il secondo problema puoi usare il metodo virtual sulle procedure che ti interessano oppure l'override di metodi se vuoi completamente riscrivere gli eventi.

Facciamo degli esempi....

Metodo 1 - aggiunta di funzionalità:

Definamo una semplice classe...

TPadre = Class
           Procedure Evento1;
         Public
           Procedure FaiEvento1; Virtual;
         End;

ora Evento1 eseguirà una serie di codice e, poi, richiamerà FaiEvento1 che sarà una procedura vuota.
Quindi avremo

Procedure TPadre.Evento1;
Begin
  {
   .....
   Qui' il codice relativo all'evento 1
   .....
  }

  FaiEvento1;  // Qui' è richiamata la procedura che interessa 
End;

Procedure TPadre.FaiEvento1;
Begin
End;

come vedi FaiEvento1 è vuota in quanto il padre si occupa di tutto.

Se vogliamo aggiungere qualche riga di codice in futuro basta derivare l'oggetto padre e riscrivere solamente la funzione che ci interessa:

TFiglio = Class(TPadre)
         Public
           Procedure FaiEvento1; Override;
         End;
         
Procedure TFiglio.FaiEvento1;
Begin
  {
   .....
   Qui' il codice da aggiungere
   .....
  }
End;

Metodo 2 - redifinizione procedure:

La tecnica è simile alla precedente ma sovrascrive tutto il codice

Definamo la solita classse ma, in questo caso, ci serve solo una procedura...

TPadre = Class
         Public
           Procedure FaiEvento1;
         End;

l'oggetto figlio sarà:

TFiglio = Class(TPadre)
         Public
           Procedure FaiEvento1; Override;
         End;

in questo caso abbiamo riscritto totalmente l'evento - possiamo comunque richiamare quello del padre richiamando la procedura con la parola chiave hinerited cosi':

Procedure TFiglio.FaiEvento1;
Begin
  inHerited FaiEvento1;
  {
   .....
   Qui' il codice dell'oggetto figlio
   .....
  }
End;
Il possibile lo abbiamo già fatto, l'impossibile lo stiamo facendo, per i miracoli ci stiamo attrezzando

mmxngg

  • Newbie
  • *
  • Post: 25
  • Karma: +0/-0
Re:Come faccio a...
« Risposta #5 il: Febbraio 21, 2012, 05:02:08 pm »
Ok, questa è l'eredietarietà standard ma se l'applico così son costretto a crearmi un nuova classe per ogni componente che utilizzo, compilarla nell'IDE ecc. ecc.
E' poco pratico perchè mi ritroverei con 2 TTrackBar, 2 TStaticText ecc. ecc. con l'unica differenza che quelli personalizzati eseguono una porzione di codice in più su un determinato evento.  L'oggetto Application ha AddOnUserInputHandler che permette di aggiungere (in stack) del codice rispetto a quello eseguito di default. Mi chiedevo se c'era un metodo generico (e a runtime) senza passare per la ridefinizione delle varie classi.

mmxngg

  • Newbie
  • *
  • Post: 25
  • Karma: +0/-0
Re:Come faccio a...
« Risposta #6 il: Febbraio 21, 2012, 06:38:15 pm »
Ho trovato come fare...cercando altro per giunta...vabbè  (fortuna che lazarus è open source e si può spulciare nei sorgenti) :P

Il metodo più semplice è :

Codice: [Seleziona]
var
  ExecShow: procedure of object;

  TMethod(ExecShow).Data := TForm(Sender);
  TMethod(ExecShow).Code := TForm(Sender).MethodAddress('FormShow');
  if not (TMethod(ExecShow).Code = nil) then
    ExecShow;

Questa è il codice da inserire nella parte generica. In questo caso l'evento è l'OnShow e la procedure che contiene il codice specifico si chiama FormShow (e deve chiamarsi allo stesso modo in tutti gli oggetti).  Se non esiste semplicemente ritorna null e va oltre.

P.S.

Aggiungo che funziona solo con le procedure dichiarate published (probabilmente per le altre non viene salvato il nome e quindi ritorna null).
« Ultima modifica: Febbraio 21, 2012, 06:53:44 pm da mmxngg »

xinyiman

  • Administrator
  • Hero Member
  • *****
  • Post: 3277
  • Karma: +12/-0
Re:Come faccio a...
« Risposta #7 il: Febbraio 22, 2012, 07:56:20 am »
Buono a sapersi  ;)
Ieri è passato, domani è futuro, oggi è un dono...

Microges2000

  • Global Moderator
  • Full Member
  • *****
  • Post: 130
  • Karma: +1/-0
    • Power of Nature
Re:Come faccio a...
« Risposta #8 il: Febbraio 22, 2012, 08:16:26 am »
Perfetto (e buono a sapersi) ma conta che è sempre un "truccaccio" e sicuramente non portabile.
Lazarus come Delphi è fortemente orientato agli oggetti e la cosa migliore è usarli nei modi, più o meno, classici in quanto le caratteristiche come quella che hai trovato tu possono essere modificate dagli autori.
Il possibile lo abbiamo già fatto, l'impossibile lo stiamo facendo, per i miracoli ci stiamo attrezzando

mmxngg

  • Newbie
  • *
  • Post: 25
  • Karma: +0/-0
Re:Come faccio a...
« Risposta #9 il: Febbraio 22, 2012, 09:45:21 am »
E' lo stesso metodo che utilizza l'IDE per importare le varie opzioni della schermata dell'ispettore degli oggetti ma dovrebbe anche essere il metodo di base con cui il free pascal richiama gli oggetti dato che è una proprietà della classe TObject (praticamente la prima classe da cui tutti ereditano qualcosa) quindi funziona su qualsiasi piattaforma e difficilmente può subire modifiche (è praticamente un pilastro della struttura). L'unico appunto è dichiarare la variabile con lo stesso prototipo della procedure, quindi nell'esempio ho sbagliato (apparentemente non da errore in realtà si brucia lentamente lo stack).

Codice: [Seleziona]
var
  ExecShow: procedure (Sender: TObject) of object;

Questo è quello corretto e rispecchia l'evento OnShow.

Certo, è un modo a basso livello di utilizzare un linguaggio ad alto livello ma ha i vuoi vantaggi. Io l'ho trovato perchè stavo cercando un sistema per far eseguire il codice contenuto nell'OnShow anche quando la form era già visibile. Utilizzando Show o settando visibile a true non funzionava visto che non cambiava lo stato ed era una bella menata.

 

Recenti

How To

Utenti
  • Utenti in totale: 803
  • Latest: maXim.FI
Stats
  • Post in totale: 19192
  • Topic in totale: 2289
  • Online Today: 54
  • Online Ever: 900
  • (Gennaio 21, 2020, 08:17:49 pm)
Utenti Online
Users: 0
Guests: 38
Total: 38

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.