
Delphi Team Roma - F.A.Q. (Frequently Asked Questions)
In questa pagina vengono presentate alcune soluzioni ai problemi ed ai quesiti che più frequentemente vengono posti nelle aree di discussione. Sono graditi suggerimenti, commenti e segnalazioni, inviando un messaggio a Franco Di Molfetta.
Le FAQ sono state suddivise secondo i seguenti argomenti:
Faq di carattere generale
Installazione
Componenti
Object Pascal
Database
FAQ DI CARATTERE GENERALE
- E' possibile sviluppare con Delphi 2.0 applicazioni a 16 bit?
Con Delphi 2.0 si possono creare soltanto applicazioni a 32 bit. Ad ogni modo, in ogni copia di Delphi 2.0 è presente anche la versione a 16 bit con la quale è possibile sviluppare applicazioni a 16 bit.
- E' incluso, in Delphi, un programma di utilità per l'installazione delle applicazioni sviluppate con Delphi?
In Delphi 1.0 no. Sono comunque disponibili molte utilità di installazione prodotte da terze parti.
Le versioni "Developer"e "Client/Server" di Delphi 2.0 contengono invece un'applicazione apposita, denominata "Install Shield".
- Il codice sorgente delle applicazioni sviluppate con Delphi a 16 bit è compatibile con Delphi 2.0?
In molti casi, è sufficiente ri-compilare il codice sorgente per ottenere un'applicazione a 32 bit completamente funzionante.
Potrebbe essere necessario apportare qualche modifica al codice in caso di chiamate a funzioni API specifiche di Windows 3.x, non supportate dalle API a 32 bit.
In caso di utilizzo di prodotti sviluppati da terze parti, è opportuno contattare i responsabili per ottenere assicurazioni sulla compatibilità del prodotto o sull'esistenza di aggiornamenti.
- Verrà mantenuto il supporto tecnico di Delphi a 16 bit?
Si prevede che i sistemi operativi a 16 bit e a 32 bit coesisteranno per almeno altri 18-24 mesi. Per questo motivo entrambi i prodotti saranno supportati da Borland.
- Quali sono, per un programmatore, i vantaggi che derivano dalle nuove caratteristiche di Windows 95?
Delphi 2.0 include numerosi componenti interamente disegnati per il nuovo sistema operativo a 32 bit. Tali componenti incorporano automaticamente le novità di Windows 95 come i nomi di file lunghi, i nuovi controlli, le rinnovate finestre di dialogo.
Delphi 2.0 supporta gli OLE controls (OCX); inoltre si ha accesso diretto alla API con pieno supporto di caratteristiche come il "plug and play", il "multithreading", etc.
- Utilizzando uno o più VBX, quali files bisogna accludere per un corretto funzionamento della mia applicazione?
E' indispensabile accludere il file "BIVBX11.DLL" (ovviamente qualificato da Borland come "redistribuibile"). Tale file si trova nella directory "..\windows\system". Bisogna accludere, naturalmente, anche il o i VBX stessi ed eventuali file associati.
INSTALLAZIONE
- Perché non riesco ad installare certi VBX o, in alcuni casi, Delphi va in crash al momento del loro utilizzo?
Probabilmente si sta cercando di utilizzare controlli VBX disegnati per le versioni 2 o 3 di Visual Basic. Delphi 1.0 supporta soltanto VBX disegnati per Visual Basic 1.0. Delphi 2.0 supporta gli OCX.
- Perché, da quando ho installato Delphi, alcune applicazioni sviluppate con Visual Basic mostrano malfunzionamenti?
L'installazione di Delphi può comportare la sovrascrittura di alcuni VBX, per la precisione: GAUGE.VBX, SWITCH.VBX,PICT.VBX e CHART2FX.VBX. Tutto ciò è ampiamente documentato nel file "install.txt" contenuto nel cd di Delphi.
- Dopo avere installato il BDE mediante l'apposito programma di installazione incluso in Delphi (nella directory "..\redinst\bdeinst"), l'utente finale, tentando di utilizzare la mia applicazione, ottiene il messaggio "Could not find language driver".
Se l'installazione viene effettuata su di un'unità di rete, non viene creata la subdirectory "langdrv". In questo caso è necessario creare manualmente tale subdirectory e decomprimervi, utilizzando "unpaq.exe", il file "langdrv.pak".
COMPONENTI
- Sto sviluppando un'applicazione MDI in Delphi; riducendo a icona una finestra "child" ottengo un messaggio di GPF (General Protection Fault).
E' un malfunzionamento noto. E' disponibile presso il sito Borland una patch che risolve il problema. Il file si chiama "delpatch.zip".
- All'avvio di Delphi, compare il seguente messaggio: "can't open c:\delphi\bin\complib.dcl".
Le cause possono essere diverse.
1) "Share" o "vshare" non installati.
2) I parametri di "share" non corretti (dovrebbero essere "F: 4096 L: 40).
3) Potrebbe essere errata o inesistente la sezione "[IDAPI]" nel file "win.ini" che dovrebbe essere simile alla seguente:
- [IDAPI]
CONFIGFIL01=C:\IDAPI\IDAPI.CFG
DLLPATH=C:\IDAPI
4) Il file "complib.dcl" potrebbe essere danneggiato. Copiarlo dal cd (si trova nella directory "..\runimage\delphi\bin\complib.dcl").
- Come ottenere una "scroll-bar" orizzontale in una list box?
Con il seguente codice:
-
SendMessage(Listbox1.Handle, LB_SetHorizontalExtent, 1000, Longint(0));
inserito, per esempio, nell'evento "OnCreate" della form.
- Aggiungendo un nuovo elemento ad una "list box" (listBoxName.items.add('xxx')), come posso fare per mostrare l'elemento appena aggiunto?
Tale risultato si ottiene con il seguente codice:
-
ListBoxName.Items.Add('xxx');
ListBoxName.ItemIndex := (ListBoxName.Items.Count-1);
- Esiste la possibilità di usare il tasto "Enter" per spostarsi tra i controlli, come avviene per il tasto "Tab"?
Basta intercettare la pressione del tasto "Enter". Ecco un esempio adottato ad un controllo di tipo "Edit". Ovviamente è possibile associare tale evento a tutti gli altri controlli che si desidera abbiano lo stesso comportamento.
- procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
- if Key = #13 then
begin
- SelectNext(Sender as tWinControl, True, True );
Key := #0;
end;
end;
E' anche possibile attuare tale comportamento a livello di form (e quindi ereditato da tutti i controlli della form), previa assegnazione del valore "True" alla proprietà (della form) "KeyPreview":
- procedure TMainForm.FormKeyPress(Sender: TObject; var Key: Char);
begin
- if Key = #13 then
begin
- Key := #0;
PostMessage(Handle, WM_NEXTDLGCTL, 0, 0);
end;
end;
N.B. Questo metodo non funziona con una griglia di database (vedi faq nella sezione "database") poichè il passaggio ad un campo successivo non comporta uno spostamento tra controlli.
- Come fare per centrare una form sullo schermo?
Si può usare il seguente codice nell'evento "OnPaint":
- MyLeft := (Screen.Left - Form1.Left) div 2; {usare l'operatore "div", non usare "/"}
Lo stesso risultato si ottiene assegnando alla proprietà "Position" il valore "poScreenCenter".
- Come posso ottenere uno "splash screen" per la mia applicazione?
Bisogna inserire il codice opportuno nel sorgente del progetto, tra il primo "Application.FormCreate" e "Application.Run". In questo punto viene creata e resa visibile la form contenente lo "splash screen". Ecco il codice:
- program Project1;
uses Forms, Unit1 in 'UNIT1.PAS' {Form1}, Splash;
{$R *.RES}
var
- SplashScreen : TSplashScreen;
begin
- Application.CreateForm(TForm1, Form1);
SplashScreen := TSplashScreen.Create(Application);
try
- SplashScreen.Show;
SplashScreen.Update;
- {permette che ogni "CreateForm" o qualsiasi altro messaggio venga attuato prima che sia avviata l'applicazione. Se le procedure di avvio risultassero troppo lente, il metodo "Application.ProcessMessages" permette a Windows di rispondere periodicamente ai messaggi}
finally
- SplashScreen.Free;
end;
Application.Run;
end.
- In quale ordine vengono processati gli eventi di una finestra durante la sua creazione?
Nell'ordine: OnCreate, OnShow, OnPaint, OnActivate, OnResize e, di nuovo, OnPaint.
- E' possibile eliminare lo "splash screen" di ReportSmith quando si accede ad un "report"?
Aprire il file "RS_RUN.INI" e, nella sezione "[RS_RunTime]", aggiungere la riga: "ShowAboutBox=0".
- Esiste un modo per determinare la posizione del cursore in un oggetto "Memo"?
E' possibile con un paio di chiamate API:
- var
- LineNum: longint;
CharsBeforeLine: longint;
begin
- LineNum := SendMessage(Memo1.Handle, EM_LINEFROMCHAR, Memo1.SelStart,0);
CharsBeforeLine := SendMessage(Memo1.Handle, EM_LINEINDEX, LineNum, 0);
Label1.Caption := 'Line ' + IntToStr(LineNum +1);
Label2.Caption := 'Position ' + IntToStr((Memo1.SelStart - CharsBeforeLine) + 1);
end;
- Vorrei cambiare il font predefinito dei controlli. E' possibile?
Modificando la proprietà "Font" di una form, tutti i controlli di quella form erediteranno tale proprietà. Ovviamente, è possibile aggiungere la form nella "Gallery" e, eventualmente, selezionarla come "default main form" e "default new form".
- Sembra che tutti gli eventi di una form (OnCreate, OnPaint, etc.)avvengano prima che essa sia visibile. Esiste una soluzione per eseguire un blocco di codice dopo che una form sia divenuta visibile?
Nell'evento "OnCreate", aggiungere: "Visible := True;". A questo punto inserire il codice desiderato.
- Come si possono determinare le dimensioni in pixel di una stringa, dopo aver scelto un determinato tipo di carattere?
Altezza e lunghezza in pixel di una stringa si ottengono con i metodi Canvas.TextHeight e Canvas.TextWidth; prima di utilizzare tali metodi è indispensabile assegnare al Canvas il font desiderato.
Tutti i componenti del tipo "visual" posseggono la proprietà "Canvas", ma, generalmente, tale proprietà non è pubblica. In questi casi è possibile ovviare al problema con la seguente funzione:
- function GetTextWidth(CanvasOwner: TForm; Text : String; TextFont : TFont): Integer;
var OldFont : TFont;
begin
- OldFont := TFont.Create;
try
- OldFont.Assign( CanvasOWner.Font );
CanvasOWner.Font.Assign( TextFont );
Result := CanvasOwner.Canvas.TextWidth(Text);
CanvasOWner.Font.Assign( OldFont );
finally
- OldFont.Free;
end;
end;
- Come mai alcuni componenti come TPanel oppure TEdit non hanno una proprietà "Canvas"?
Qualsiasi discendente di TCustomControl possiede la proprietà "Canvas", ma, in molti casi, tale proprietà non è disponibile perché in contrasto con le peculiarità dell'oggetto.
Per questo motivo sarebbe opportuno indirizzarsi su componenti, come il TPaintBox, appositamente creati per rendere disponibile un'area di disegno.
I discendenti di un componente possono comunque avere accesso a proprietà, come la "Canvas", ereditate dal componente stesso, ma protette e quindi non pubbliche:
- type TCanvasPanel = class(TPanel)
public property Canvas;
end;
- Perché la pressione di uno "Speed Button" non sembra in grado di eseguire l'evento OnExit di un componente?
Perchè un componente del tipo TSpeedButton non è in grado di ricevere il "focus", per cui l'evento OnExit dal controllo attivo non avviene. Si può facilmente aggirare l'ostacolo facendo eseguire tale evento all' interno dell' "OnClick" dello SpeedButton:
- procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
- If ActiveControl is TEdit then
- (ActiveControl as TEdit).OnExit(ActiveControl);
end;
- La griglia di database TDBGrid sembra non avere disponibili gli eventi "OnMouseDown", "OnMouseUp" e "OnMouseMove". Come si può ovviare?
Gli eventi esistono ma non sono stati resi "pubblici"; basta creare un discendente dell'oggetto e qualificare come "pubblici" gli eventi che interessano.
- Come si può, nell'ambito di una chiamata alla funzione "MessageDlg", andare a capo forzatamente?
E' sufficiente inserire un carattere di "ritorno carrello" ed uno di "nuova linea". Ad esempio:
- MessageDlg
- ('Non c'è nulla di più inelegante e fastidioso' + #13#10 +
'di una chilometrica finestra di dialogo.',
mtInformation, [mbOK], 0)
Ovviamente questa tecnica è valida anche con le altre funzioni dello stesso tipo (ad esempio, Showmessage, InputBox, InputQuery, etc.).
- E' possibile implementare qualcosa di simile ad un "control array" del Visual Basic?
Un metodo abbastanza semplice è quello di sfruttare la proprietà Tag. Per esempio, assegnando alla Tag di ogni pulsante un numero differente e quindi creare un OnClick comune che controlli il parametro Sender:
- procedure TForm1.Button1Click(Sender: TObject);
var cap: string;
- begin
case TButton(sender).Tag of
- 1: ShowMessage('Primo bottone premuto');
2: ShowMessage('Secondo bottone premuto');
3: ShowMessage('Terzo bottone premuto');
end;
end;
OBJECT PASCAL
- Come creare variabili globali in Delphi?
Bisogna creare una nuova Unit (senza form), dichiarare le variabili nella porzione di "interfaccia" e aggiungere il nome della Unit nella sezione "uses" di tutte le altre Unit.
Nella programmazione ad oggetti le variabili globali sono un po' anomale. In genere, è più elegante definire una classe che contiene tutte le informazioni "generali". Tali informazioni sono incapsulate in campi privati, e per accedervi occorre usare metodi della classe.
Ecco, ad esempio, un progetto con 2 units e una form. Nella form c'è un controllo del tipo TEdit. La seconda unit (General) definisce una classe (TGeneralData) contenente due campi (ex variabili globali), due metodi per accedere ai campi in lettura, e il costruttore dell'oggetto. Inoltre definisce una variabile di tipo TGeneralData.
- unit Main; { Main unit }
interface
uses
- SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls,
General; { Qui avviene l'inclusione della unit General }
type
- TForm1 = class(TForm)
- Edit1: TEdit;
procedure FormCreate(Sender: TObject);
procedure FormActivate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
public
end;
var
- Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin
- GD := TGeneralData.Create('MioProg', 'MeStesso'); { Istanzio l'oggetto; GD e' dichiarata in General. }
end;
procedure TForm1.FormActivate(Sender: TObject);
begin
- Edit1.Text := GD.Author; { Accedo al campo Autore }
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
- GD.Free; { Quando la form viene distrutta, distruggo l'oggetto }
end;
end.
unit General; { Questa e' la seconda unit (senza form associata) }
interface
uses
- Classes;
type
- TGeneralData = class(TObject)
private
- FPrgName: string;
FAuthor: string;
public
- property ProgramName: string read FPrgName;
property Author: string read FAuthor;
constructor Create(thePrgName, theAuthor: string);
end;
var
- GD: TGeneralData;
implementation
constructor TGeneralData.Create(thePrgName, theAuthor: string);
begin
- inherited Create;
FPrgName := thePrgName;
FAuthor := theAuthor;
end;
end.
- Vorrei permettere lo scrolling di una form anche da tastiera, possibilmente utilizzando i tasti "PagSu" e "PagGiù"
Bisogna associare la pressione dei tasti interessati alla proprietà "VertScrollbar.Position" e/o, eventualmente, "HorzScrollbar.Position":
- procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
const
- PageDelta = 10;
begin
- with VertScrollbar do
if Key = vk_Next then
- Position := Position + PageDelta;
else
- if Key = vk_Prior then
- Position := Position - PageDelta;
end;
- Come posso chiamare una funzione da una dll?
Ovviamente è indispensabile conoscere l'esatta sintassi della funzione da chiamare. Per esempio, nell'evento "OnClick" di un pulsante, la funzione "CallMe", da un ipotetico file "MyTest.dll", prevede, come argomenti, due variabili intere e ritorna un valore di tipo "stringa":
- procedure TForm1.Button1Click(Sender: TObject);
type
- TCallMeDll = function(a,b: Integer): string;
var
- CallMeDll: TCallMeDll;
FuncPtr: TFarProc;
hDll: THandle;
result: string;
begin
- hDll:=LoadLibrary('Mytest.dll'); { carica la dll in memoria}
FuncPtr:=GetProcAddress(hDLL,'CallMe'); { ottiene il puntatore alla funzione "esterna"}
@CallMeDll:=FuncPtr;
if @CallMeDll <> nil then {controlla che "GetProcAddress" sia andato a buon fine}
- result:=CallMeDll(4,5);
FuncPtr:=nil;
FreeLibrary(hDll);
end;
- Come fare per conoscere la data di creazione di un file?
- function GetFileDate(TheFileName: string): string;
var
- FHandle: integer;
begin
- FHandle := FileOpen(TheFileName, 0);
try
- Result := DateTimeToStr(FileDateToDateTime(FileGetDate(FHandle)));
finally
- FileClose(FHandle);
end;
end;
- Come si può controllare la presenza di un dischetto nell' unità "A" senza generare un messaggio di errore all' utente?
E' possibile, ad esempio, con la seguente funzione, che vuole come parametro la lettera dell'unità che si desidera controllare:
-
function DiskInDrive(Drive: Char): Boolean;
var
- ErrorMode: word;
begin
{converte in maiuscolo}
- if Drive in ['a'..'z'] then Dec(Drive, $20);
{controlla sia stata passata una lettera}
- if not (Drive in ['A'..'Z']) then
- raise EConvertError.Create('Unitagrave; non valida');
ErrorMode := SetErrorMode(SEM_FailCriticalErrors);
try { drive 1 = a, 2 = b, 3 = c, etc. }
- if DiskSize(Ord(Drive) - $40) = -1 then
- Result := False
else
- Result := True;
finally
- {ripristina il vecchio controllo di errore}
- SetErrorMode(ErrorMode);
end;
end;
- Qual'è il modo più rapido per eliminare una sola riga da una sezione di un file ini?
E' possibile, ad esempio, salvare in una TStringList tutte le chiavi che interessano e, nel rispettivo campo Objects della TStringList, tutti i valori. Poi, con il metodo TIniFile.EraseSection viene cancellata l'intera sezione che sarà ripristinata tramite il metodo "TIniFile.WriteString" ripetuto per ogni elemento della TStringList.
- Come posso controllare se un'altra applicazione è già in esecuzione?
In Delphi 1 è possibile con una semplice chiamata alla funzione API "GetModuleHandle"; tale funzione richiede il nome dell'applicazione come parametro e ritorna l'handle di tale applicazione. Se questa non è in esecuzione, il valore restituito dalla funzione sarà zero.
In Delphi 2 , invece, non è possibile utilizzare la funzione succitata.
- Come eseguire, all'interno di un mio programma, un'altra applicazione?
E' sufficiente una chiamata alla funzione API "WinExec" la cui sintassi è: WinExec(CmdLine: PChar; CmdShow: Word): Word;
Il valore di ritorno della funzione, se chiamata correttamente, non deve essere minore di 32. Il primo parametro è rappresentato dal nome dell'eseguibile, il secondo dalla modalità di esecuzione del programma (ridotto a icona, in finestra massimizzata, etc.). Se nel paramtero CmdLine non è incluso il percorso completo dell'applicazione, la funzione ricercherà, il file eseguibile rispettivamente: nella directory corrente, la directory di Windows, la directory "system" di Windows, la directory che ospita l'eseguibile della applicazione in esecuzione, tutte le altre directory.
DATABASE
- Come creare un campo di auto-incremento in una tabella Paradox?
E' possibile utilizzando una "TQuery" ed il comando SQL "CREATE TABLE". Ad esempio:
- procedure TForm1.Button1Click(Sender: TObject);
begin
- with Query1 do
begin
- DatabaseName := 'DBDemos';
with SQL do
begin
- Clear;
Add('CREATE TABLE "PDoxTbl.db" (ID AUTOINC,');
Add('Name CHAR(255),');
Add('PRIMARY KEY(ID))');
ExecSQL;
Clear;
Add('CREATE INDEX ByName ON "PDoxTbl.db" (Name)');
ExecSQ L;
end;
end;
end;
- Come determinare il record e, eventualmente, il campo corrente in una "TDBGrid"?
La procedura seguente determina i valori di riga e colonna ad ogni aggiornamento della griglia (cioè l'evento "OnDrawDataCell"). Le variabili "Row" e "Col" devono essere esterne alla procedura.
- var
- Col, Row: Integer;
procedure TForm1.MyDBGridDrawDataCell(Sender: TObject; const Rect: TRect; Field: TField; State: TGridDrawState);
var
- RowHeight: Integer;
begin
- if gdFocused in State then
begin
- RowHeight := Rect.Bottom - Rect.Top;
Row := (Rect.Top div RowHeight) - 1;
Col := Field.Index;
end;
end;
- Come mostrare il contenuto di un campo "Memo" in una "TDBGrid"?
Creare un oggetto di tipo "TMemoField" facendo doppio click sul componente "TTable" e aggiungendo il campo "Memo" desiderato. Associare il seguente codice all'evento "OnDrawDataCell" della griglia:
- procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect; Field: TField; State: TGridDrawState);
var
- P : array [0..50] of char; {le dimensioni dell'array devono essere impostate in base alle dimensioni del campo Memo"}
BS : tBlobStream; {dal campo "Memo"}
S : String;
begin
- if Field is TMemoField then
begin
- with (Sender as TDBGrid).Canvas do
begin {Table1Notes is the TMemoField}
- BS := tBlobStream.Create(Table1Notes, bmRead);
FillChar(P,SizeOf(P),#0); {rende la stringa di tipo "null terminated"}
BS.Read(P, 50); {legge 50 caratteri dal "Memo" e li copia in "blobStream"}
BS.Free;
S := StrPas(P);
while Pos(#13, S ) > 0 do {elimina i "Ritorno Carrello"}
- S[Pos(#13, S)] := ' ';
While Pos(#10, S) > 0 do {elimina i "Nuova Linea"}
- S[Pos(#10, S)] := ' ';
FillRect(Rect); {cancella il contenuto della cella}
TextOut(Rect.Left, Rect.Top, S); {riempie la cella con i dati del campo "Memo"}
end;
end;
end;
- Esiste la possibilità di usare il tasto "Enter" per spostarsi tra i campi di una griglia di database, come avviene per il tasto "Tab"?
Bisogna intercettare gli eventi OnKeyDown e OnKeyPress:
- procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
- if Key = VK_RETURN then Key = VK_TAB;
end;
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
- if Key = #13 then Key := #9;
end;
- Come posso effettuare una ricerca in un campo non indicizzato?
Con la seguente funzione:
"Locate(TabName, FieldName, chiave)"; dove TabName è il componente "TTable", FieldName è l'oggetto di tipo TField aggiunto con il "Field Editor" (ottenibile con un doppio click sul componente "TTable") e "chiave" è il valore da cercare.
- function Locate( const NomeTab: TTable; const NomeCampo: TField; const chiave: String): Boolean;
var
- recPos : TBookMark;
trovato : Boolean;
begin
- Locate := False;
trovato := False;
if not NomeTab.Active then Exit;
if NomeTab.FieldDefs.IndexOf( NomeCampo. FieldName ) < 0 then Exit;
recPos := NomeTab.GetBookMark;
With NomeTab do
begin
- DisableControls;
first;
while not EOF do
if NomeCampo.AsString = chiave then
begin
- Locate := True;
trovato := True;
Break;
end
else
- next;
end ;
if (Not trovato) then NomeTab.GotoBookMark(recPos);
NomeTab.FreeBookMark(recPos);
NomeTab.EnableControls;
end;
- E' possibile controllare se un determinato pulsante di un controllo del tipo "TDBNavigator" sia attivato?
Ecco un esempio:
- type TDBNavCracker = class(TDBnavigator);
...
if TDBNavCracker(DBNavigator1).Buttons[nbEdit].Enabled then...;
Torna alla Home Page.
Torna a inizio pagina.
© 1996 Franco Di Molfetta, mc0559@mclink.it - Ultima revisione: 25 luglio 1996.