Ciao a tutti, attulamente sto utilizzando un software di automatismi, e mi è nata l'esigenza di realizzare una Dll con SaveDialog ma non so come applicarla qualcuno può aiutarmi.
Allego una dll che ho creato come esempio per fare la somma, moltiplicazione.
library Somma;
uses
SysUtils, Windows, Classes;
// -------------------------------------------------------------------------------
Const Inputs = 2; // quantita entrata
Outputs = 2; // quantita uscita
{INPUTS} // nome per numero di entrata
I0 = 0; // valore I0 = PInput[I0] ossia PInput[0]
I1 = 1; // valore I1 = PInput[I1] ossia PInput[1]
// I2 = 2;
// I3 = 3;
// ... I99 = 99;
{OUTPUTS} // nome per numero di uscita
Q0 = 0; // valore Q0 = POutput[Q0] ossia POutput[0]
Q1 = 1; // valore Q1 = POutput[Q1] ossia POutput[1]
// Q2 = 2;
// Q3 = 3;
// ... Q99 = 99;
{USER} // nome per numero di variabile, I valori vengono memorizzati
U0 = 0; // valore U0 = PUser[U0] ossia PUser[0]
// U1 = 1;
// U2 = 2;
// U3 = 3;
// ... U99 = 99;
// I0,I1,I2,I3,Q0,Q1,Q2,Q3,U0,U1,U2,U3
// I nomi possono essere qualsiasi, sono case-insensitive
Type TDLLParams = array[0..100] of extended; // ProfiLab DLL parametro Type
PDLLParams = ^TDLLParams; // ProfiLab DLL parametro Pointer
// -------------------------------------------------------------------------------
function NumInputs: Byte;
begin
result := Inputs; // trasferire quantita entrata
end;
// -------------------------------------------------------------------------------
function NumOutputs: Byte;
begin
result := Outputs; // trasferire quantita uscita
end;
// -------------------------------------------------------------------------------
function InputName(Channel: Byte): ShortString; // trasferire nome di entrata
begin
case Channel of
I0 : result := 'I0'; // nome di pin I0
I1 : result := 'I1'; // nome di pin I1
end;
end;
// -------------------------------------------------------------------------------
Function OutputName(Channel: Byte): ShortString; // trasferire nome di uscita
begin
case Channel of
Q0 : result := 'Q0'; // nome di pin Q0
Q1 : result := 'Q1'; // nome di pin Q1
end;
end;
// -------------------------------------------------------------------------------
Procedure SimStart(PInput,POutput,PUser: PDLLParams); // Routine viene eseguita solo al primo avvio
begin
// solo per inizializzare
end;
// -------------------------------------------------------------------------------
Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine e permanente
begin
// Calcola somma di due numeri
POutput^[Q0] := PInput^[I0] + PInput^[I1];
// Prodotto di due numeri per il calcolo
POutput^[Q1] := PInput^[I0] * PInput^[I1];
// Differenza tra due valori
PUser^[U0] := PInput^[I0] - PInput^[I1];
// piu funzioni
end;
// -------------------------------------------------------------------------------
Procedure SimStop(PInput,POutput,PUser: PDLLParams); // Routine viene eseguita solo in fase di chiusura
begin
// solo in chiusura
end;
// -------------------------------------------------------------------------------
//export methods for ProfiLab
exports SimStart,
SimStop,
NumInputs,
NumOutputs,
Calculate,
InputName,
OutputName;
begin
end.
Vorrei sapere come posso inserire una SaveDialog in una DLL con queste caratteristiche?
Ecco il risultato della DLL sopra citata:
(http://i46.tinypic.com/311t1zc.png)
devi istanziare l'oggetto all'interno della funzione, ad esempio:
function SaveToFile: string;
var d: TSaveDialog;
begin
result := '';
d := TSaveDialog.Create(self); // vado a memoria non ricordo i parametri di create...
try
if d.Execute then
begin
result := d.FileName;
end;
finally
d.Free;
end
end;
quando la richiami, se l'utente clicca su [OK], ti ritorna la fullpath dove salvare il tu file
Ciao, ho provato così, ma genera questo errore:
project1.pas(95,20) Hint: Parameter "PInput" not used
project1.pas(95,27) Hint: Parameter "POutput" not used
project1.pas(95,35) Hint: Parameter "PUser" not used
project1.pas(109,20) Error: Wrong number of parameters specified for call to "ApriOpenDialog"project1.pas(50,11) Hint: Found declaration: ApriOpenDialog(TForm);
project1.pas(142) Fatal: There were 1 errors compiling module, stopping
Allego il sorgente con relativa modifica:
library Project1;
{$mode objfpc}{$H+}
uses
Interfaces, Classes, SysUtils, Windows, FileUtil, Forms, Controls,
Graphics, Dialogs;
{ you can add units after this }
// questa direttiva l'ho tolta perchè non mi creava la dll, mi sono documentato sul forum lazarus {$R *.RES}
Const Inputs = 2; // quantita entrata
Outputs = 2; // quantita uscita
{INPUTS} // nome per numero di entrata
I0 = 0; // valore I0 = PInput[I0] ossia PInput[0]
I1 = 1; // valore I1 = PInput[I1] ossia PInput[1]
// I2 = 2;
// I3 = 3;
// ... I99 = 99;
{OUTPUTS} // nome per numero di uscita
Q0 = 0; // valore Q0 = POutput[Q0] ossia POutput[0]
Q1 = 1; // valore Q1 = POutput[Q1] ossia POutput[1]
// Q2 = 2;
// Q3 = 3;
// ... Q99 = 99;
{USER} // nome per numero di variabile, I valori vengono memorizzati
U0 = 0; // valore U0 = PUser[U0] ossia PUser[0]
// U1 = 1;
// U2 = 2;
// U3 = 3;
// ... U99 = 99;
// I0,I1,I2,I3,Q0,Q1,Q2,Q3,U0,U1,U2,U3
// I nomi possono essere qualsiasi, sono case-insensitive
Type TDLLParams = array[0..100] of extended; // ProfiLab DLL parametro Type
PDLLParams = ^TDLLParams; // ProfiLab DLL parametro Pointer
Procedure ApriOpenDialog(finestra: TForm);
var pannello: TOpenDialog;
begin
pannello := TOpenDialog.Create(finestra);
pannello.Execute();
end;
function NumInputs: Byte;
begin
result := Inputs; // trasferire quantita entrata
end;
function NumOutputs: Byte;
begin
result := Outputs; // trasferire quantita uscita
end;
function InputName(Channel: Byte): ShortString; // trasferire nome di entrata
begin
case Channel of
I0 : result := 'I0'; // nome di pin I0
I1 : result := 'I1'; // nome di pin I1
end;
end;
Function OutputName(Channel: Byte): ShortString; // trasferire nome di uscita
begin
case Channel of
Q0 : result := 'Q0'; // nome di pin Q0
Q1 : result := 'Q1'; // nome di pin Q1
end;
end;
Procedure SimStart(PInput,POutput,PUser: PDLLParams); // Routine viene eseguita solo al primo avvio
begin
// solo per inizializzare
end;
Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine è permanente
begin
// Apri la finestra di dialogo TOpendialog
POutput^[Q0] :=ApriOpenDialog ;
// Prodotto di due numeri per il calcolo
POutput^[Q1] := PInput^[I0] * PInput^[I1];
// Differenza tra due valori
PUser^[U0] := PInput^[I0] - PInput^[I1];
// piu funzioni
end;
Procedure SimStop(PInput,POutput,PUser: PDLLParams); // Routine viene eseguita solo in fase di chiusura
begin
// solo in chiusura
end;
//export methods for ProfiLab
exports SimStart,
SimStop,
NumInputs,
NumOutputs,
Calculate,
InputName,
OutputName,
ApriOpenDialog;
begin
end.
se dichiari
Procedure ApriOpenDialog(finestra: TForm);
non ci sono valori di ritorno e quindi nella chiamata
POutput^[Q0] :=ApriOpenDialog ;
ci sono 2 errori:
- ApriOpenDialog non ritorna alcun valore in quanto è una procedura
- ApriOpenDialog ha un parametro che non gli stai passando nella chiamata
prova dichiararla così:
function ApriOpenDialog: ShortString;
var pannello: TOpenDialog;
begin
pannello := TOpenDialog.Create(nil);
if pannello.Execute then
result := pannello.FileName
else
result := '';
end;
poi quando è ora di chiamarla:
Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine è permanente
var s: ShortString;
begin
// Apri la finestra di dialogo TOpendialog
s :=ApriOpenDialog ;
// poi valorizzi
POutput^[Q0] := ...
end;
Ciao nomorelogic,
Ecco il sorgente ma ho ancora questo errore:
project1.pas(99,20) Hint: Parameter "PInput" not used
project1.pas(99,27) Hint: Parameter "POutput" not used
project1.pas(99,35) Hint: Parameter "PUser" not used
project1.pas(109,4) Error: Illegal expression
project1.pas(109,8) Fatal: Syntax error, ";" expected but "identifier S" found
library Project1;
{$mode objfpc}{$H+}
uses
Interfaces, Classes, SysUtils, Windows, FileUtil, Forms, Controls,
Graphics, Dialogs;
{ you can add units after this }
// questa direttiva l'ho tolta perchè non mi creava la dll, mi sono documentato sul forum lazarus {$R *.RES}
Const Inputs = 2; // quantita entrata
Outputs = 2; // quantita uscita
{INPUTS} // nome per numero di entrata
I0 = 0; // valore I0 = PInput[I0] ossia PInput[0]
I1 = 1; // valore I1 = PInput[I1] ossia PInput[1]
// I2 = 2;
// I3 = 3;
// ... I99 = 99;
{OUTPUTS} // nome per numero di uscita
Q0 = 0; // valore Q0 = POutput[Q0] ossia POutput[0]
Q1 = 1; // valore Q1 = POutput[Q1] ossia POutput[1]
// Q2 = 2;
// Q3 = 3;
// ... Q99 = 99;
{USER} // nome per numero di variabile, I valori vengono memorizzati
U0 = 0; // valore U0 = PUser[U0] ossia PUser[0]
// U1 = 1;
// U2 = 2;
// U3 = 3;
// ... U99 = 99;
// I0,I1,I2,I3,Q0,Q1,Q2,Q3,U0,U1,U2,U3
// I nomi possono essere qualsiasi, sono case-insensitive
Type TDLLParams = array[0..100] of extended; // ProfiLab DLL parametro Type
PDLLParams = ^TDLLParams; // ProfiLab DLL parametro Pointer
function ApriOpenDialog: ShortString;
var pannello: TOpenDialog;
begin
pannello := TOpenDialog.Create(nil);
if pannello.Execute then
result := pannello.FileName
else
result := '';
end;
function NumInputs: Byte;
begin
result := Inputs; // trasferire quantita entrata
end;
function NumOutputs: Byte;
begin
result := Outputs; // trasferire quantita uscita
end;
function InputName(Channel: Byte): ShortString; // trasferire nome di entrata
begin
case Channel of
I0 : result := 'I0'; // nome di pin I0
I1 : result := 'I1'; // nome di pin I1
end;
end;
Function OutputName(Channel: Byte): ShortString; // trasferire nome di uscita
begin
case Channel of
Q0 : result := 'Q0'; // nome di pin Q0
Q1 : result := 'Q1'; // nome di pin Q1
end;
end;
Procedure SimStart(PInput,POutput,PUser: PDLLParams); // Routine viene eseguita solo al primo avvio
begin
// solo per inizializzare
end;
Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine è permanente
begin
var s: ShortString;
begin
// Apri la finestra di dialogo TOpendialog
s :=ApriOpenDialog ;
// poi valorizzi
POutput^[Q0] :=ApriOpenDialog ;
// piu funzioni
end;
Procedure SimStop(PInput,POutput,PUser: PDLLParams); // Routine viene eseguita solo in fase di chiusura
begin
// solo in chiusura
end;
//export methods for ProfiLab
exports SimStart,
SimStop,
NumInputs,
NumOutputs,
Calculate,
InputName,
OutputName,
ApriOpenDialog;
begin
end.
begin
var s: ShortString;
begin
Il copia e incolla va bene, ma togli le cose che non centrano ... hai 2 begin e in mezzo un var ...
Altra considerazione ...
POutput^[Q0] :=ApriOpenDialog ;
Ma come hai dichiarato questo parametro?
Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine è permanente
Credo che il compilatore possa anche farela passare liscia (se si incasina con i puntatori o imposti che non deve fare il controllo di tipo sui puntatori stessi). Ma credo che poi non ti vadano a buon fine le chiamate.
PDLLParams non è dichiarato come array di numeri in virgola mobile?
Tu assegni una stringa ... (Short per giunta).
Fammi sapere ...
Stilgar
Si che stupido grazie :)
ma non ci sono ancora:
project1.pas(116,23) Error: Incompatible types: got "ShortString" expected "Extended"
Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine è permanente
var s: ShortString;
begin
// Apri la finestra di dialogo TOpendialog
s :=ApriOpenDialog;
// poi valorizzi
POutput^[Q0] :=ApriOpenDialog ;
// piu funzioni
end;
Mi da l'errore qui : // poi valorizzi
POutput^[Q0] :=ApriOpenDialog ;
Simulatore dici il programma di automatismi che uso?
Come faccio a dichiararli generici i puntatori?
riferito a questo?
Type TDLLParams = array[0..100] of extended; // ProfiLab DLL parametro Type
PDLLParams = ^TDLLParams; // ProfiLab DLL parametro Pointer
Type TDLLParams = array[0..100] of extended; // ProfiLab DLL parametro Type
PDLLParams = ^TDLLParams; // ProfiLab DLL parametro Pointer
Type TDLLParams = array[0..100] of Pointer; // ProfiLab DLL parametro Type
PDLLParams = ^TDLLParams ; // ProfiLab DLL parametro Pointer
Sì il programma che deve caricare questa DLL.
Stilgar
Ciao nomorelogic, grazie per avermi risposto potresti indicarmi dove inserire nella mia dll quella funzione?
Naturalmente cancellando quello che non serve poichè è una dll somma e altro.
Sono vincolato a seguire delle regole per fare il componente dll ti allego le regole che mi chiede il software:
DLL-Import
Included in version:
DMM-ProfiLab: No
Digital-ProfiLab: No
ProfiLab-Expert: Yes
This component offers a programming interface, which makes it possible to create your own ProfiLab components, for example to control self-made hardware devices, etc.
For that purpose you need a programming language, that allows you to compile DLL-files
(Dynamic Link Libraries), and you need some programming experience, as well.
Programming your own component, you have to meet some requirements of ProfiLab.
For example your DLL must export certain functions, that define the numbers of component inputs and outputs, the pin names and the internal function of the component.
The following function are necessary for a component. The modified C++ versions use DOUBLE instead of EXTENDED and PCHAR instead of STRING.
Delphi: function NumInputs: Byte;
C++: unsigned char _stdcall NumInputs()
alternative:
Delphi: function NumInputsEx(PUser: PDLLParams): Byte;
C++: unsigned char _stdcall CNumInputsEx(double *PUser)
The result of this function must return a byte value that defines the number of inputs of your component. The extended function type NumInputsEx is useful, if the number of inputs depends on configuration data stored in PUser.
Delphi: function NumOutputs: Byte;
C++: unsigned char _stdcall NumOutputs()
alternative:
Delphi: function NumOutputsEx(PUser: PDLLParams): Byte;
C++: unsigned char _stdcall CNumOutputsEx(double *PUser)
The result of this function must return a byte value that defines the number of outputs of your component. The extended function type NumOutputsEx is useful, if the number of outputs depends on configuration data stored in PUser.
Delphi: function InputName(Channel: Byte): ShortString;
void _stdcall GetInputName(unsigned char Channel, unsigned char *Name)
The result of this function must deliver a short text for the pin description for each input pin (channel) of your component. ProfiLab calls this function for each input pin, to request the corresponding description. The parameter CHANNELS identifies the pin and runs from 0 to NumInputs-1.
Delphi: function OutputName(Channel: Byte): ShortString;
C++: void _stdcall GetOutputName(unsigned char Channel, unsigned char *Name)
The result of this function must deliver a short text for the pin description for each output pin (channel) of your component. ProfiLab calls this function for each output pin, to request the corresponding description. The parameter CHANNELS identifies the pin and runs from 0 to NumOutputs-1.
Delphi: Procedure Calculate(PInput,POutput,PUser: PDLLParams);
C++: void _stdcall CCalculate(double *PInput, double *POutput, double *PUser)
This is the main calculation procedure of your component, which defines how your component works. The procedure parameters PINPUT, POUTPUT and PUSER offer three pointer variables with the following function:
The pointer PINPUT points to a memory area, in which input values are stored, so that the DLL can access the input values of the component.
The pointer POUTPUT points to a memory area, in which output values are stored, so that the DLL can set the output values of the component.
The pointer PUSER points to a memory area, where the DLL can store its own (local) values. Background: Variables defined in the DLL are global variables. Values stored to global variables will overwrite each other, if a DLL component is used more than once in a ProfiLab project. To have local variables available, ProfiLab hands out the pointer PUSER to the DLL, so that the DLL can store local data in the memory area that PUSER points to.
If you don´t want to use PUSER, but you need to declare variables in the DLL that are meant to be local (for components that are used more than once in a ProfiLab project), you can rename the DLL file and import it in ProfiLab with different filenames, as well.
Each of the three pointers PINPUT, POUTPUT and PUSER points to an array of 100 EXTENDED variables. All three pointer are declared as type PDLLParams. The declaration in Delphis is as follows:
type TDLLParams = array[0..100] of extended;
PDLLParams = ^TDLLParams;
C++ function types hand out this kind of memory pointer as (double *PInput) parameter for example.
The array of PINPUT offers the input values of the component. The input values can be accessed as follows:
PInput^[0] contains the numeric value of the first input,
PInput^[1] contains the numeric value of the second input, and so on...
The array of POUTPUT offers the output values of the component. The output values can be set as follows:
POutput^[0] must be set with the numeric value for the first output,
POutput^[1] must be set with the numeric value for the second output, and so on...
PUser^[0] to PUser^[99] can be used to store numeric user values. The values of these variables are saved in the ProfiLab project file, so that values are available agein, when the project is loaded next time. The variable PUser^[100] is set by ProfiLab and contains the number of the DLL component: 1 fo DLL1, 2 for DLL2, and so on.
The procedure CALCULATE is called repeatedly while ProfiLab is in RUN mode, to hand out new input values to the DLL and to request new output values from the DLL. This means that this procedure must be programmed as short as possible, and must not contain any pauses (WAIT loops or SLEEP commands) that waste time. After reading input values and setting new output vaues this routine should be terminated as soon as possible. The time spent in this procedure will directly influence the simulation frequency of ProfiLab.
Delphi: Procedure CalculateEx(PInput,POutput,PUser: PDLLParams; PStrings: PStringParams);
C++: void _stdcall CCalculateEx(double *PInput, double *POutput, double *PUser; StringParam PStrings)
This method was introduced to allow string processing with DLL´s. It may be used as alternative for CALCULATE. Parameter PSTRINGS were added for interfacing string data. Its Delphi delclaration is as follows:
type TStringParams = array[0..100] of PChar;
PStringParams = ^TStringParams;
Each input/output (max. 100) has a null-terminated character pointer (PChar) assigned, which points to a memory space that is provided by ProfiLab. Right before ProfiLab enters the method, data is fetched from the $inputs. After leaving the method data is handed out through the $outputs. It is not distinguished between inputs and outputs. This means that Input 0 and Output 0 for example share the same PChar. To make a pin become a string input or string output its pin name must be declared with a leading '$' character. Examples for string processing with DLL´s and ProfiLab are available.
Delphi: Procedure SimStart(PInput,POutput,PUser: PDLLParams);
C++: void _stdcall CSimStart(double *PInput, double *POutput, double *PUser)
This procedure is called once, when the ProfiLab project enters the RUN mode, and can be used to initialize DLL variables, etc. The parameters have been explained before.
Delphi: Procedure SimStop(PInput,POutput,PUser: PDLLParams);
C++: void _stdcall CSimStop(double *PInput, double *POutput, double *PUser)
This procedure is called once, when RUN mode is terminated, and can be used to close open files, etc. The parameters have been explained before.
Delphi: Procedure Configure(UserValues: PDLLParam);
C++: void _stdcall CConfigure(double *PUser)
As soon as your DLL exports this procedure, the button CONFIGURE... in the property dialogue of the component is enabled. With a click on this button, ProfiLab will jump to your CONFIGURE procedure, where you can add your own setup dialogue for your DLL.
These very few routines make it possible to program any ProfiLab component you have in mind. For example you could program hardware components that control special hardware devices, or create components that execute complex calculations.
If you want to program a component with digital outputs, simply set the numeric output vaules to 5 for HIGH levels, or to 0 for LOW levels. Numeric inputs higher than 2.5 should be interpreted as HIGH levels, numeric inputs lower then 2,5 as LOW leves.
Your compiled DLL file can be loaded in the property dialogue of the component. All imported functions and procedures are listed in the dialogue. The component will then appear in the circuit as it is defined in the DLL. To be conform with C-Compiler conventions, names of functions and procedure may begin with an underline character _ as well. For example _SimStart instead of SimStart.
Compiling your own DLL project make sure that the linker option "Dynamic RTL" is disabled. Otherwise the DLL can not be loaded on systems without installed C++ environment.
Il perchè ho scritto tali parametri è scritto qui poichè non posso far diversamente.
Vorrei inizialmente far aprire una OpenDialog premendo un pulsante che ho già in libreria allego l'esempio:
(http://i50.tinypic.com/2s5z1i8.jpg)
Ho modificato il codice inserendo nell'ingresso I0 l'apertura dell'OpenDialog ma ho sempre problemi con i puntatori come posso fare? Grazie :)
library Project1;
{$mode objfpc}{$H+}
uses
Interfaces, Classes, SysUtils, Windows, FileUtil, Forms, Controls,
Graphics, Dialogs;
{ you can add units after this }
// questa direttiva l'ho tolta perchè non mi creava la dll, mi sono documentato sul forum lazarus {$R *.RES}
Const Inputs = 2; // quantita entrata
Outputs = 2; // quantita uscita
{INPUTS} // nome per numero di entrata
I0 = 0; // valore I0 = PInput[I0] ossia PInput[0]
I1 = 1; // valore I1 = PInput[I1] ossia PInput[1]
// I2 = 2;
// I3 = 3;
// ... I99 = 99;
{OUTPUTS} // nome per numero di uscita
Q0 = 0; // valore Q0 = POutput[Q0] ossia POutput[0]
Q1 = 1; // valore Q1 = POutput[Q1] ossia POutput[1]
// Q2 = 2;
// Q3 = 3;
// ... Q99 = 99;
{USER} // nome per numero di variabile, I valori vengono memorizzati
U0 = 0; // valore U0 = PUser[U0] ossia PUser[0]
// U1 = 1;
// U2 = 2;
// U3 = 3;
// ... U99 = 99;
// I0,I1,I2,I3,Q0,Q1,Q2,Q3,U0,U1,U2,U3
// I nomi possono essere qualsiasi, sono case-insensitive
Type TDLLParams = array[0..100] of extended; // ProfiLab DLL parametro Type
PDLLParams = ^TDLLParams; // ProfiLab DLL parametro Pointer
function ApriOpenDialog: ShortString;
var pannello: TOpenDialog;
begin
pannello := TOpenDialog.Create(nil);
if pannello.Execute then
result := pannello.FileName
else
result := '';
end;
function NumInputs: Byte;
begin
result := Inputs; // trasferire quantita entrata
end;
function NumOutputs: Byte;
begin
result := Outputs; // trasferire quantita uscita
end;
function InputName(Channel: Byte): ShortString; // trasferire nome di entrata
begin
case Channel of
I0 : result := 'I0'; // nome di pin I0
I1 : result := 'I1'; // nome di pin I1
end;
end;
Function OutputName(Channel: Byte): ShortString; // trasferire nome di uscita
begin
case Channel of
Q0 : result := 'Q0'; // nome di pin Q0
Q1 : result := 'Q1'; // nome di pin Q1
end;
end;
Procedure SimStart(PInput,POutput,PUser: PDLLParams); // Routine viene eseguita solo al primo avvio
begin
// solo per inizializzare
end;
Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine è permanente
var s: ShortString;
begin
// Apri la finestra di dialogo TOpendialog
s :=ApriOpenDialog;
// poi valorizzi
PInput^[I0] :=ApriOpenDialog;
// piu funzioni
end;
Procedure SimStop(PInput,POutput,PUser: PDLLParams); // Routine viene eseguita solo in fase di chiusura
begin
// solo in chiusura
end;
//export methods for ProfiLab
exports SimStart,
SimStop,
NumInputs,
NumOutputs,
Calculate,
InputName,
OutputName,
ApriOpenDialog;
begin
end.
Aggiungo un esempio di dll counter creato dalla casa del software che uso:
library Counter;
// Delphi 5 DLL-source (COUNTER.DLL)
// Defines a simple 8-Bit counter component for ProfiLab
uses
SysUtils,Windows,Classes;
{$R *.RES}
Const Inputs = 2; // number of inputs
Outputs = 8; // number of outputs
{INPUTS}
CLK = 0; // index of input variable CLK
RST = 1; // index of input variable RST
{OUTPUTS}
{USER}
CLK_old = 0; // index user variable CLK_old
RST_old = 1; // index user variable RST_old
Count = 2; // index user variable COUNT
Type TDLLParams = array[0..100] of extended; //Type of ProfiLab DLL parameters
PDLLParams = ^TDLLParams; // Pointer to ProfiLab DLL parameters
function NumInputs: Byte;
begin
result:=Inputs; //Define number of component input pins
end;
function NumOutputs: Byte;
begin
result:=Outputs; //Define number of component output pins
end;
Function InputName(Channel: Byte): ShortString; // Return name for each component input pin
begin
case Channel of
CLK: result:='CLK'; // "CLK" (Clock)
RST: result:='/RST'; // "/RST" (NOT RESET)
end;
end;
Function OutputName(Channel: Byte): ShortString; // Return name for each component output pin
begin
result:='Q'+intToStr(Channel); //"Q0".."Q7" (Binary count)
end;
Procedure SimStart(PInput,POutput,PUser: PDLLParams); //called when ProfiLab enters RUN mode
var i: Integer;
begin
PUser^[Count]:=0; //RESET COUNTER
For i:=0 to Outputs do
begin
POutput[i]:=0; //Set binary outputs with COUNT=0
end;
end;
Procedure SimStop(PInput,POutput,PUser: PDLLParams); //called when ProfiLab RUN mode is terminated
begin
// nothing to be done
end;
Procedure Calculate(PInput,POutput,PUser: PDLLParams); //called regularly from ProfiLab
var i: Integer;
begin
if PInput^[RST]<2.5 then //check RST input HIGH or LOW
begin
if (not (PInput^[RST]>=2.5)) and (PUser^[RST_old]>2.5) then //check out falling edge at RST input
begin
PUser^[Count]:=0; //RESET COUNT
For i:=0 to Outputs do
begin
POutput[i]:=0; //Set binary outputs with COUNT=0
end;
end;
exit;
end;
PUser^[RST_old]:=PInput^[RST]; //Remember RST status for next call
if PInput^[CLK]>2.5 then //check CLK input HIGH or LOW
begin
if (PInput^[CLK]>2.5) and not(PUser^[CLK_old]>2.5) then //check out rising edge at CLK input
begin
PUser^[Count]:=PUser^[Count]+1; // increase COUNT
if PUser^[Count]>255 then PUser^[Count]:=0; //check overflow
For i:=0 to Outputs do
begin
if (round(PUser^[Count]) and (1 shl i))>0 then POutput^[i]:=5 else POutput[i]:=0; //Set binary outputs with current COUNT
end;
end;
end;
PUser^[CLK_old]:=PInput^[CLK]; //Remember CLK status for next call
end;
//export methods for ProfiLab
exports SimStart,
SimStop,
NumInputs,
NumOutputs,
Calculate,
InputName,
OutputName;
begin
end.
type TStringParams = array[0..100] of PChar;
PStringParams = ^TStringParams;
Diventa
Type TDLLParams = array[0..100] of PChar; // ProfiLab DLL parametro Type
PDLLParams = ^TDLLParams ; // ProfiLab DLL parametro Pointer
Occhio che devi usare le funzioni stringa per la gestione delle stringhe open via pchar.
Le allochi.
Le azzeri (il puntato, non il puntatore).
Le copi.
Se hai problemi a questo livello, ti consiglio di lasciar perdere il simulatore/emulatore o quel cavolo che è, per una attimino. Fatti una bella lettura della sezione HowTo.
xinyiman saprà indicarti gli howto più adatti.
Se alcuni concetti non ti sono chiari, qui ci sono molte persone disponibili ad aiutarti. Da quello che ho capito hai forti lacune sulla programmazione pascal/object pascal. Spiegarle in un thread specifico non lo trovo molto d'aiuto.
Stilgar
Ciao Stilgar,
Sai dirmi cosa vuol dire questo?
project1.lpr(0,0) Fatal: Can not find unit Interfaces used by project1. Check if package LCL is in the dependencies.
Non riesco a compilare
Dove posso trovare un manuale per principianti?
Ma per far aprire questa benedetta finestra quando clicco sopra ci vuole ancora molto ? :)
possibile che è così lunga?
Ho bisogno di una vostra mano...se possibile
Ringrazio tutti
Ciao ;)
Grazie Stilgar almeno questo sono riuscito a farlo ;)
Ma ora mi genera questo errore:
project1.lpr(100,20) Hint: Parameter "PInput" not used
project1.lpr(100,27) Hint: Parameter "POutput" not used
project1.lpr(100,35) Hint: Parameter "PUser" not used
project1.lpr(117,22) Error: Incompatible types: got "ShortString" expected "PChar"
project1.lpr(145) Fatal: There were 1 errors compiling module, stopping
type l'ho modificato così:
type TDLLParams = array[0..100] of PChar;
PDLLParams = ^TDLLParams;
Grazie
project1.lpr(117,22) Error: Incompatible types: got "ShortString" expected "PChar"
Questo?
Cosa ti ho indicato per
project1.pas(116,23) Error: Incompatible types: got "ShortString" expected "Extended"
Lo ricordi?type TStringParams = array[0..100] of PChar;
PStringParams = ^TStringParams;
Diventa
Type TDLLParams = array[0..100] of PChar; // ProfiLab DLL parametro Type
PDLLParams = ^TDLLParams ; // ProfiLab DLL parametro Pointer
Occhio che devi usare le funzioni stringa per la gestione delle stringhe open via pchar.
Le allochi.
Le azzeri (il puntato, non il puntatore).
Le copi.
Se hai problemi a questo livello, ti consiglio di lasciar perdere il simulatore/emulatore o quel cavolo che è, per una attimino. Fatti una bella lettura della sezione HowTo.
xinyiman saprà indicarti gli howto più adatti.
Se alcuni concetti non ti sono chiari, qui ci sono molte persone disponibili ad aiutarti. Da quello che ho capito hai forti lacune sulla programmazione pascal/object pascal. Spiegarle in un thread specifico non lo trovo molto d'aiuto.
Stilgar
Ciao a tutti e Buon Natale;
Ho risolto con la OpenDialog, appena premo un pulsante dal mio software si apre la OpenDialog, ma ci sono dei problemini: come mai quando la apro poi non riesco più a chiuderla? e perché quando tento di aprire un file txt non lo apre?
Ho il presentimento che devo mdificare la funzione giusto?
vi ringrazio molto
Ciao
function ApriOpenDialog: ShortString;
var pannello: TOpenDialog;
begin
pannello := TOpenDialog.Create(nil);
if pannello.Execute then
result := pannello.FileName
else
result := '';
end;
(http://i46.tinypic.com/2itlyra.png)
Ciao, anche se clicco sulla X si chiude e si riapre velocemente, come la richiamo la destroy? non ho idea.
Stilgard ma puoi spiegarmi come mai non posso cambiare il (nil) e mettere un (self)?
Filter l'ho inserito e funziona ;)
function ApriOpenDialog: ShortString;
var pannello: TOpenDialog;
begin
pannello := TOpenDialog.Create(nil);
pannello.Filter:='*.txt';
if pannello.Execute then
result := pannello.FileName
else
result := '';
end;
Ma una volta che trovo un file txt da aprire lui non lo apre se ci clicco sopra?
Come posso fare?
Allora nelle modifiche che ho fatto ho rimesso Extended quindi non dovrebbero esserci problemi, poi in Procedure Calculate ho risolto così si aprono sia OpenDialog che SaveDialog, ma non si chiudono.
Sui 2 ingressi ho messo i controlli poiché il pulsante della mi libreria nel momento che viene premuto genera un 5V quindi si spiega il perché si apre... ma non si spiega il perché non si chiude...
Ciao
Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine è permanente
begin
if PInput^[I0] > 2.5 then ApriOpenDialog;
if PInput^[I1] > 2.5 then ApriSaveDialog;
// piu funzioni
end;
library dialog;
{$mode objfpc}{$H+}
uses
Interfaces, Classes, SysUtils, Windows, FileUtil, Forms, Controls,
Graphics, Dialogs;
{ you can add units after this }
// questa direttiva l'ho tolta perchè non mi creava la dll, mi sono documentato sul forum lazarus {$R *.RES}
Const Inputs = 2; // quantita entrata
Outputs = 2; // quantita uscita
{INPUTS} // nome per numero di entrata
I0 = 0; // valore I0 = PInput[I0] ossia PInput[0]
I1 = 1; // valore I1 = PInput[I1] ossia PInput[1]
// I2 = 2;
// I3 = 3;
// ... I99 = 99;
{OUTPUTS} // nome per numero di uscita
Q0 = 0; // valore Q0 = POutput[Q0] ossia POutput[0]
Q1 = 1; // valore Q1 = POutput[Q1] ossia POutput[1]
// Q2 = 2;
// Q3 = 3;
// ... Q99 = 99;
{USER} // nome per numero di variabile, I valori vengono memorizzati
U0 = 0; // valore U0 = PUser[U0] ossia PUser[0]
// U1 = 1;
// U2 = 2;
// U3 = 3;
// ... U99 = 99;
// I0,I1,I2,I3,Q0,Q1,Q2,Q3,U0,U1,U2,U3
// I nomi possono essere qualsiasi, sono case-insensitive
type TDLLParams = array[0..100] of Extended; //Type of ProfiLab DLL parameters
PDLLParams = ^TDLLParams; // Pointer to ProfiLab DLL parameters
function ApriSaveDialog: ShortString;
var pannello: TSaveDialog;
begin
pannello :=TSaveDialog.Create(nil);
pannello.Filter:='*.txt';
if pannello.Execute then
result := pannello.FileName
else
result := '';
end;
function ApriOpenDialog: ShortString;
var pannello: TOpenDialog;
begin
pannello := TOpenDialog.Create(nil);
pannello.Filter:='*.txt';
if pannello.Execute then
result := pannello.FileName
else
result := '';
end;
function NumInputs: Byte;
begin
result := Inputs; // trasferire quantita entrata
end;
function NumOutputs: Byte;
begin
result := Outputs; // trasferire quantita uscita
end;
function InputName(Channel: Byte): ShortString; // trasferire nome di entrata
begin
case Channel of
I0 : result := 'I0'; // nome di pin I0
I1 : result := 'I1'; // nome di pin I1
end;
end;
Function OutputName(Channel: Byte): ShortString; // trasferire nome di uscita
begin
case Channel of
Q0 : result := 'Q0'; // nome di pin Q0
Q1 : result := 'Q1'; // nome di pin Q1
end;
end;
Procedure SimStart(PInput,POutput,PUser: PDLLParams); // Routine viene eseguita solo al primo avvio
begin
// solo per inizializzare
end;
Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine è permanente
begin
if PInput^[I0] > 2.5 then ApriOpenDialog;
if PInput^[I1] > 2.5 then ApriSaveDialog;
// piu funzioni
end;
Procedure SimStop(PInput,POutput,PUser: PDLLParams); // Routine viene eseguita solo in fase di chiusura
begin
// solo in chiusura
end;
//export methods for ProfiLab
exports SimStart,
SimStop,
NumInputs,
NumOutputs,
Calculate,
InputName,
OutputName,
ApriOpenDialog,
ApriSaveDialog;
begin
end.
Allora nelle modifiche che ho fatto ho rimesso Extended quindi non dovrebbero esserci problemi, poi in Procedure Calculate ho risolto così si aprono sia OpenDialog che SaveDialog, ma non si chiudono.
Sui 2 ingressi ho messo i controlli poiché il pulsante della mi libreria nel momento che viene premuto genera un 5V quindi si spiega il perché si apre... ma non si spiega il perché non si chiude...
Non so perchè non si chiudono ma c'è un errore abbastanza serio nelle definizioni delle funzioni ApriSaveDialog e ApriOpenDialog.
Nel codice da te postato c'è la creazione dell'istanza ma non c'è la liberazione delle risorse. Questo vuol dire che ogni volta che invochi una di queste funzioni, viene allocata della memoria ma nessuno si preoccupa di restituirla al sistema.
La differenza nella gestione della memoria tra un componente messo su un form a design-time ed uno istanziato a run-time è che:
- i componenti definiti a design-time sono sia istanziati che liberati automaticamente
- i componenti istanziati a run-time *devono* essere liberati a run-time
quindi la tua funzione dovrebbe diventare così:
function ApriOpenDialog: ShortString;
var pannello: TOpenDialog;
begin
pannello := TOpenDialog.Create(nil);
try
pannello.Filter:='*.txt';
if pannello.Execute then
result := pannello.FileName
else
result := '';
finally
pannello.Free;
end;
Appena dopo la creazione, in casi come questi, ti consiglio di inserire sempre un blocco try...finally e di mettere nel finally la liberazione delle risorse.
Questo ti mette al riparo da eventuali crash e/o eccezioni e se la tua applicazione dovesse anche subire un arresto non previsto, avresti sempre la certezza di aver liberato la memoria istanziata a run-time.
Ho anche la sensazione che così i dialog potrebbero chiudersi ;)
Ciao
Ho tolto SaveDialog per una prova più mirata:)
Ma genera questo errore:
project1.lpr(65,1) Error: Illegal expression
project1.lpr(65,10) Fatal: Syntax error, ";" expected but "identifier NUMINPUTS" found
Esattamente su qesta riga e non capisco il perché se prima andava bene:)
function NumInputs: Byte; <--------------questa riga
begin
result := Inputs; // trasferire quantita entrata
end;
library dialog;
{$mode objfpc}{$H+}
uses
Interfaces, Classes, SysUtils, Windows, FileUtil, Forms, Controls,
Graphics, Dialogs;
{ you can add units after this }
Const Inputs = 2; // quantita entrata
Outputs = 2; // quantita uscita
{INPUTS} // nome per numero di entrata
I0 = 0; // valore I0 = PInput[I0] ossia PInput[0]
I1 = 1; // valore I1 = PInput[I1] ossia PInput[1]
// I2 = 2;
// I3 = 3;
// ... I99 = 99;
{OUTPUTS} // nome per numero di uscita
Q0 = 0; // valore Q0 = POutput[Q0] ossia POutput[0]
Q1 = 1; // valore Q1 = POutput[Q1] ossia POutput[1]
// Q2 = 2;
// Q3 = 3;
// ... Q99 = 99;
{USER} // nome per numero di variabile, I valori vengono memorizzati
U0 = 0; // valore U0 = PUser[U0] ossia PUser[0]
// U1 = 1;
// U2 = 2;
// U3 = 3;
// ... U99 = 99;
// I0,I1,I2,I3,Q0,Q1,Q2,Q3,U0,U1,U2,U3
// I nomi possono essere qualsiasi, sono case-insensitive
type TDLLParams = array[0..100] of Extended; //Type of ProfiLab DLL parameters
PDLLParams = ^TDLLParams; // Pointer to ProfiLab DLL parameters
function ApriOpenDialog: ShortString;
var pannello: TOpenDialog;
begin
pannello := TOpenDialog.Create(nil);
try
pannello.Filter:='*.txt';
if pannello.Execute then
result := pannello.FileName
else
result := '';
finally
pannello.Free;
end;
function NumInputs: Byte;
begin
result := Inputs; // trasferire quantita entrata
end;
function NumOutputs: Byte;
begin
result := Outputs; // trasferire quantita uscita
end;
function InputName(Channel: Byte): ShortString; // trasferire nome di entrata
begin
case Channel of
I0 : result := 'I0'; // nome di pin I0
I1 : result := 'I1'; // nome di pin I1
end;
end;
Function OutputName(Channel: Byte): ShortString; // trasferire nome di uscita
begin
case Channel of
Q0 : result := 'Q0'; // nome di pin Q0
Q1 : result := 'Q1'; // nome di pin Q1
end;
end;
Procedure SimStart(PInput,POutput,PUser: PDLLParams); // Routine viene eseguita solo al primo avvio
begin
// solo per inizializzare
end;
Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine è permanente
begin
if PInput^[I0] > 2.5 then ApriOpenDialog;
if PInput^[I1] > 2.5 then ApriSaveDialog;
// piu funzioni
end;
Procedure SimStop(PInput,POutput,PUser: PDLLParams); // Routine viene eseguita solo in fase di chiusura
begin
// solo in chiusura
end;
//export methods for ProfiLab
exports SimStart,
SimStop,
NumInputs,
NumOutputs,
Calculate,
InputName,
OutputName,
ApriOpenDialog,
ApriSaveDialog;
begin
end.
Controlla gli end della funzione prima ...
begin
pannello := TOpenDialog.Create(nil);
try
pannello.Filter:='*.txt';
if pannello.Execute then
result := pannello.FileName
else
result := '';
finally
pannello.Free;
end;
function NumInputs: Byte;
Credo che il compilatore stia cercando di dirti che per lui manca un end per fare quello che vuoi tu ;)
Ogni blocco ha un inizio e una fine.
begin <-inizio blocco
pannello := TOpenDialog.Create(nil);
try <-inizio blocco
pannello.Filter:='*.txt';
if pannello.Execute then
result := pannello.FileName
else
result := '';
finally
pannello.Free;
end;<-fine blocco try finally end
end; <- fine blocco begin end
Ciao
Allora si aprono e si chiudono bene ma a volte rimane premuto il pulsante e quindi non mi fa chiudere la OpenDialog lo stesso capita per la SaveDialog.
Attualmente ho inserito questi controlli in procedure Calculate per garantire la chiusura qundo non lo chiamo.
E poi come prova ho inserito 2 LED sulle ripettive uscite, quindi quando viene premuto il pulsante della OpenDialog si deve accendere un led, se viene premuto il pulsante della SaveDialog si deve accendere l'altro LED.
Ha funzionato ma poi non l'ho visto più accendere.
è giusto come ho scritto?
Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine è permanente
begin
if PInput^[I0] >2.5 then ApriOpenDialog
else PInput^[I0]:=0;
if PInput^[I1] >2.5 then ApriSaveDialog
else PInput^[I1]:=0;
If PInput^[I0] >2.5 then POutput^[Q0]:=5
else POutput^[Q0]:=0;
If PInput^[I1] >2.5 then POutput^[Q1]:=5
else POutput^[Q1]:=0;
// accende il led quando viene premuto PInput^[I0] ovvero OpenDilog
// accende il led quando viene premuto PInput^[I1] ovvero SaveDialog
// piu funzioni
end;
(http://i49.tinypic.com/103da8m.jpg)
Così funziona ho dovuto togliere gli else
quindi:
Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine è permanente
begin
if PInput^[I0] >2.5 then ApriOpenDialog;
if PInput^[I1] >2.5 then ApriSaveDialog;
If PInput^[I0] >2.5 then POutput^[Q0]:=5;
If PInput^[I1] >2.5 then POutput^[Q1]:=5;
// piu funzioni
end;
Ma rimane sempre il problema che a volte si bloccano i pulsanti se clicco veloce si apre e si chiude regolare, basta che lo tengo un po troppo premuto si blocca
Il fatto che si blocchi, può avere varie cause.
1) Il programma si impalla di suo.
2) La dll si incasina con la creazione e distruzione del dialogo.
Metti i vari dialoghi in una variabile "globale".
Controlli se la variabile è già stata istanziate
if not assigned(dialogoxxx) then
begin
dialogoxxx := TDialog.create(...);
...
FreeAndNil(dialogxxx);
end;
In questo modo il codice apre il dialogo solo se non è già stato aperto.
Quindi la variabile del dialogo ti funge da ... "semaforo".
Stilgar
Domanda n 1
Allora quando apro uno dei due dialoghi si accende il led rispettivo al diagolo chiamato, ma quando clicco su annulla o sulla x i led rimangono sempre accesi.
Domanda: come faccio a resettare il controllo ovvero l'uscita POutput^[Q0] quando clicco su annulla o sulla X dei dialoghi?
If PInput^[I0] >2.5 then POutput^[Q0]:=5;
Domanda n2
Ho tolto le variabili locali e le ho messe globali, praticamente solo una poiché è la stessa.
var pannello: TOpenDialog;
type TDLLParams = array[0..100] of Extended; //Type of ProfiLab DLL parameters
PDLLParams = ^TDLLParams; // Pointer to ProfiLab DLL parameters
function ApriSaveDialog: ShortString;
begin
pannello := TSaveDialog.Create(nil);
try
pannello.Filter:='*.txt';
if pannello.Execute then
result := pannello.FileName
else
result := '';
finally
pannello.Free;
end;
end;
function ApriOpenDialog: ShortString;
begin
pannello := TOpenDialog.Create(nil);
try
pannello.Filter:='*.txt';
if pannello.Execute then
result := pannello.FileName
else
result := '';
finally
pannello.Free;
end;
end;
Ora il codice che mi hai indicato lo devo inserire in Calculate?
Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine è permanente
if not assigned (ApriOpenDialog) then
begin
ApriOpenDialog:= TDialog.create(...); qua cosa metto?
... qui cosa metto?
FreeAndNil(ApriOpenDialog);
end;
// piu funzioni
end;
Domanda n 3
Esiste un modo per evitare che la schermata del dialogo vada sotto il programma che sto usando?
Cerco di spiegarmi a volte capita che clicco fuori dalla finestra di dialogo e quindi il dialogo a sua volta finisce sul desktop quindi sotto il programma allora devo chiudere sulla - per riprenderlo e chiuderlo
Ciao
Risposta 1 :
POutput^[Q0]:=0;
If PInput^[I0] >2.5 then POutput^[Q0]:=5;
Risposta 2:
Esattamente la stessa cosa in entrambe le funzioni. Solo che una è chiamata dal primo pulsante e l'altra dal secondo ... ma se fanno la stessa cosa, potrebbe essere il caso di avere una sola funzione... no?
Risposta 3:
Il dialogo, per essere modale ha bisogno di una finestra "padre", mettendo nil, dici che non ha padre ed è autonoma, per cui non può essere modale sull'applicazione chiamante.
Per fare in modo che abbia un "padre", devi avere un'istanza dell'applicazione chimanate (in genere è nella "main dll" che ti viene passato quel parametro, ma in freepascal non conosco la prassi per lavorare con questi parametri, in C++ della Microsoft è una cosa "abbastanza semplice")
Eccomi ecco il codice...
library dialog;
{$mode objfpc}{$H+}
uses
Interfaces, Classes, SysUtils, Windows, FileUtil, Forms, Controls,
Graphics, Dialogs;
{ you can add units after this }
Const Inputs = 2; // quantita entrata
Outputs = 2; // quantita uscita
{INPUTS} // nome per numero di entrata
I0 = 0; // valore I0 = PInput[I0] ossia PInput[0]
I1 = 1; // valore I1 = PInput[I1] ossia PInput[1]
// I3 = 3;
// ... I99 = 99;
{OUTPUTS} // nome per numero di uscita
Q0 = 0; // valore Q0 = POutput[Q0] ossia POutput[0]
Q1 = 1; // valore Q1 = POutput[Q1] ossia POutput[1]
// Q3 = 3;
// ... Q99 = 99;
{USER} // nome per numero di variabile, I valori vengono memorizzati
U0 = 0; // valore U0 = PUser[U0] ossia PUser[0]
// U1 = 1;
// U2 = 2;
// U3 = 3;
// ... U99 = 99;
// I0,I1,I2,I3,Q0,Q1,Q2,Q3,U0,U1,U2,U3
// I nomi possono essere qualsiasi, sono case-insensitive
type TDLLParams = array[0..100] of Extended; //Type of ProfiLab DLL parameters
PDLLParams = ^TDLLParams; // Pointer to ProfiLab DLL parameters
function ApriSaveDialog: ShortString;
var pannello: TOpenDialog;
begin
pannello := TSaveDialog.Create(nil);
try
pannello.Filter:='*.txt';
if pannello.Execute then
result := pannello.FileName
else
result := '';
finally
pannello.Free;
end;
end;
function ApriOpenDialog: ShortString;
var pannello: TOpenDialog;
begin
pannello := TOpenDialog.Create(nil);
try
pannello.Filter:='*.txt';
if pannello.Execute then
result := pannello.FileName
else
result := '';
finally
pannello.Free;
end;
end;
function NumInputs: Byte;
begin
result := Inputs; // trasferire quantita entrata
end;
function NumOutputs: Byte;
begin
result := Outputs; // trasferire quantita uscita
end;
function InputName(Channel: Byte): ShortString; // trasferire nome di entrata
begin
case Channel of
I0 : result := 'I0'; // nome di pin I0
I1 : result := 'I1'; // nome di pin I1
end;
end;
Function OutputName(Channel: Byte): ShortString; // trasferire nome di uscita
begin
case Channel of
Q0 : result := 'Q0'; // nome di pin Q0
Q1 : result := 'Q1'; // nome di pin Q1
end;
end;
Procedure SimStart(PInput,POutput,PUser: PDLLParams); // Routine viene eseguita solo al primo avvio
begin
// solo per inizializzare
end;
Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine è permanente
begin
if PInput^[I0] >2.5 then ApriOpenDialog;
if PInput^[I1] >2.5 then ApriSaveDialog;
If PInput^[I0] >2.5 then POutput^[Q0]:=5;
If PInput^[I1] >2.5 then POutput^[Q1]:=5;
end; // piu funzioni
Procedure SimStop(PInput,POutput,PUser: PDLLParams); // Routine viene es eguita solo in fase di chiusura
begin
// solo in chiusura
end;
//export methods for ProfiLab
exports SimStart,
SimStop,
NumInputs,
NumOutputs,
Calculate,
InputName,
OutputName,
ApriOpenDialog,
ApriSaveDialog;
begin
end.
prova questo
library dialog;
{$mode objfpc}{$H+}
uses
Interfaces,
Classes,
SysUtils,
Windows,
FileUtil,
Forms,
Controls,
Graphics,
Dialogs;
const
Inputs = 2; // quantita entrata
Outputs = 2; // quantita uscita
{INPUTS}// nome per numero di entrata
I0 = 0; // valore I0 = PInput[I0] ossia PInput[0]
I1 = 1; // valore I1 = PInput[I1] ossia PInput[1]
// I3 = 3;
// ... I99 = 99;
{OUTPUTS}// nome per numero di uscita
Q0 = 0; // valore Q0 = POutput[Q0] ossia POutput[0]
Q1 = 1; // valore Q1 = POutput[Q1] ossia POutput[1]
// Q3 = 3;
// ... Q99 = 99;
{USER}// nome per numero di variabile, I valori vengono memorizzati
U0 = 0; // valore U0 = PUser[U0] ossia PUser[0]
// U1 = 1;
// U2 = 2;
// U3 = 3;
// ... U99 = 99;
// I0,I1,I2,I3,Q0,Q1,Q2,Q3,U0,U1,U2,U3
// I nomi possono essere qualsiasi, sono case-insensitive
var
globalDialog: TFileDialog;
type
TDLLParams = array[0..100] of extended; //Type of ProfiLab DLL parameters
PDLLParams = ^TDLLParams; // Pointer to ProfiLab DLL parameters
function ApriSaveDialog: ShortString;
begin
if not assigned(globalDialog) then
begin
globalDialog := TSaveDialog.Create(nil);
try
globalDialog.Filter := '*.txt';
if globalDialog.Execute then
Result := globalDialog.FileName
else
Result := '';
finally
FreeAndNil(globalDialog);
end;
end;
end;
function ApriOpenDialog: ShortString;
begin
if not assigned(globalDialog) then
begin
globalDialog := TOpenDialog.Create(nil);
try
globalDialog.Filter := '*.txt';
if globalDialog.Execute then
Result := globalDialog.FileName
else
Result := '';
finally
FreeAndNil(globalDialog);
end;
end;
end;
function NumInputs: byte;
begin
Result := Inputs; // trasferire quantita entrata
end;
function NumOutputs: byte;
begin
Result := Outputs; // trasferire quantita uscita
end;
function InputName(Channel: byte): ShortString; // trasferire nome di entrata
begin
case Channel of
I0: Result := 'I0'; // nome di pin I0
I1: Result := 'I1'; // nome di pin I1
end;
end;
function OutputName(Channel: byte): ShortString; // trasferire nome di uscita
begin
case Channel of
Q0: Result := 'Q0'; // nome di pin Q0
Q1: Result := 'Q1'; // nome di pin Q1
end;
end;
procedure SimStart(PInput, POutput, PUser: PDLLParams); // Routine viene eseguita solo al primo avvio
begin
POutput^[Q0] := 0;
POutput^[Q1] := 0;
end;
procedure Calculate(PInput, POutput, PUser: PDLLParams); // Routine è permanente
begin
if PInput^[I0] > 2.5 then
begin
ApriOpenDialog;
POutput^[Q0] := 5;
end;
if PInput^[I1] > 2.5 then
begin
ApriSaveDialog;
POutput^[Q1] := 5;
end;
end;
procedure SimStop(PInput, POutput, PUser: PDLLParams); // Routine viene es eguita solo in fase di chiusura
begin
POutput^[Q0] := 0;
POutput^[Q1] := 0;
end;
//export methods for ProfiLab
exports SimStart,
SimStop,
NumInputs,
NumOutputs,
Calculate,
InputName,
OutputName,
ApriOpenDialog,
ApriSaveDialog;
begin
end.
Per legare le due cose si potrebbe fare in questo modo:
library dialog;
{$mode objfpc}{$H+}
uses
Interfaces,
Classes,
SysUtils,
Windows,
FileUtil,
Forms,
Controls,
Graphics,
Dialogs;
const
Inputs = 2; // quantita entrata
Outputs = 2; // quantita uscita
{INPUTS}// nome per numero di entrata
I0 = 0; // valore I0 = PInput[I0] ossia PInput[0]
I1 = 1; // valore I1 = PInput[I1] ossia PInput[1]
// I3 = 3;
// ... I99 = 99;
{OUTPUTS}// nome per numero di uscita
Q0 = 0; // valore Q0 = POutput[Q0] ossia POutput[0]
Q1 = 1; // valore Q1 = POutput[Q1] ossia POutput[1]
// Q3 = 3;
// ... Q99 = 99;
{USER}// nome per numero di variabile, I valori vengono memorizzati
U0 = 0; // valore U0 = PUser[U0] ossia PUser[0]
// U1 = 1;
// U2 = 2;
// U3 = 3;
// ... U99 = 99;
// I0,I1,I2,I3,Q0,Q1,Q2,Q3,U0,U1,U2,U3
// I nomi possono essere qualsiasi, sono case-insensitive
var
globalDialog: TFileDialog;
type
TDLLParams = array[0..100] of extended; //Type of ProfiLab DLL parameters
PDLLParams = ^TDLLParams; // Pointer to ProfiLab DLL parameters
function ApriSaveDialog: ShortString;
begin
result := '';
if not assigned(globalDialog) then
begin
globalDialog := TSaveDialog.Create(nil);
try
globalDialog.Filter := '*.txt';
if globalDialog.Execute then
Result := globalDialog.FileName
else
Result := '';
finally
FreeAndNil(globalDialog);
end;
end;
end;
function ApriOpenDialog: ShortString;
begin
result := '';
if not assigned(globalDialog) then
begin
globalDialog := TOpenDialog.Create(nil);
try
globalDialog.Filter := '*.txt';
if globalDialog.Execute then
Result := globalDialog.FileName
else
Result := '';
finally
FreeAndNil(globalDialog);
end;
end;
end;
function NumInputs: byte;
begin
Result := Inputs; // trasferire quantita entrata
end;
function NumOutputs: byte;
begin
Result := Outputs; // trasferire quantita uscita
end;
function InputName(Channel: byte): ShortString; // trasferire nome di entrata
begin
case Channel of
I0: Result := 'I0'; // nome di pin I0
I1: Result := 'I1'; // nome di pin I1
end;
end;
function OutputName(Channel: byte): ShortString; // trasferire nome di uscita
begin
case Channel of
Q0: Result := 'Q0'; // nome di pin Q0
Q1: Result := 'Q1'; // nome di pin Q1
end;
end;
procedure SimStart(PInput, POutput, PUser: PDLLParams); // Routine viene eseguita solo al primo avvio
begin
POutput^[Q0] := 0;
POutput^[Q1] := 0;
end;
procedure Calculate(PInput, POutput, PUser: PDLLParams); // Routine è permanente
begin
if PInput^[I0] > 2.5 then
begin
if ('' <> ApriOpenDialog) then
POutput^[Q0] := 5
else
POutput^[Q0] := 0;
end;
if PInput^[I1] > 2.5 then
begin
if ('' <> ApriSaveDialog) then
POutput^[Q1] := 5
else
POutput^[Q1] := 0;
end;
end;
procedure SimStop(PInput, POutput, PUser: PDLLParams); // Routine viene es eguita solo in fase di chiusura
begin
POutput^[Q0] := 0;
POutput^[Q1] := 0;
end;
//export methods for ProfiLab
exports SimStart,
SimStop,
NumInputs,
NumOutputs,
Calculate,
InputName,
OutputName,
ApriOpenDialog,
ApriSaveDialog;
begin
end.