Newsgroup: it.comp.lang.delphi
Titolo: WM_COPYDATA

Ciao ragazzi ..chi può spiegarmi come funziona WM_COPYDATA?
Come si fà a passare dei dati con esso?
Ciao Raf.

 Come si fà a passare dei dati con esso?
... stai intrallazzando con il winamp ?
Ciao
Paolo Zavarise 

 Come si fà a passare dei dati con esso?
Si fa si fa.......eccome se si fa !!!
Ok, lo stavo riusando proprio in questi giorni !!
Tu hai le due applicazioni che devono scambiarsi i dati, quindi si tratta di
una comunicazione interprocesso che risolvi tramite il WM_COPYDATA. ( ad
esempio )
Ora l'applicazione a cui dovrai mandare i dati sarà la ricevente e quella
che manda la chiamante. ( senza usare termini tecnici )
Quindi la ricevente dovrà processare ( filtrare ) il messaggio WM_COPYDATA
tramite un handler di messaggi, mentre la chiamante userà
l' API "SendMessage" per inviare il WM_COPYDATA e i dati.
Per usare questo benedetto WM_COPYDATA, ci sono di mezzo i puntatori.
WParam e LPparam sono due numeri, quindi per contenere dati generici, devono
essere per forza puntatori. A noi interessa LParam che poi nel WM_COPYDATA è
un puntatore alla struttura CopyDataStruct che in Delphi è dichiarata come
TCopyDataStruct ( record ) o PCopyDataStruct ( puntatore a record )
Tutto combacia. WParam è un numero che nell'help indica l'handle a qualcosa,
ma non è rilevante al 100%, mentre  LParam è il puntatore a TCopyDataStruct.
Ok fin quì ?
Bene, non resta che passare al codice. Supponiamo che tu devi inviare una
stringa dall'applicazione X all'applicazione Y con Form "TFormRicevente".
N.B. Io ti faccio l'esempio di una stringa, ma tieni conto che ci puoi
scambiare record e dati generici, l'importante è che ci azzecchi con i
puntatori e non definisci variabili con dimensione ambigua, perchè quando
allochi la memoria ad un puntatore, devi allocargli quella giusta.
Programma chiamante:
var MioMsg                        : String;
       SLen                              : Integer;
       PMsg                             : PChar;
       CopyDataStruct           : TCopyDataStruct;
       HandleFormRicevente : THandle;
begin
  MioMsg:='PROVA WM_COPYDATA';
  SLen:=Length(MioMsg);
  GetMem(PMsg, SLen);
  try
     StrLCopy(PMsg, PChar(MioMsg), SLen - 1);
     HandleFormRicevente:=FindWindow('TFormRicevente', nil); // quì al
limite metti un IF....insomma rivedi tutto tu !!
     CopyDataStruc.cbData:=SLen;
     CopyDataStruct.lpData:=PMsg;
     SendMessage(HandleFormRicevente, WM_COPYDATA, 0,
LParam(@CopyDataStruct));
  finally
    FreeMem(PMsg, SLen);
  end;
end;
Programma ricevente:
dichiari un handler di messaggi del tipo:
procedure WmCopyData(var Msg: TWmCopyData);
e poi lo implementi così:
procedure TFormRicevente.WmCopyData(var Msg: TWmCopyData);
var MioMsg : String;
begin
  SetLength(MioMsg, Msg.CopyDataStruct.cbData + 1);
  StrCopy(PChar(MioMsg), PChar(Msg.CopyDataStruct.lpData));
  ShowMessage(MioMsg);
end;
ehi......non so se è giusto a livello sintattico. Forse è giusto come
ragionamento logico. In ogni modo questo codice te l'ho scritto per come ti
sto scrivento questo messaggio, quindi non l'ho provato. Non mi andava di
postarti qualche spezzone di codice di qualche mio programma perchè il più
delle volte passo intere strutture e quindi non volevo che i puntatori ti
complicassero la vita. Credo che un esempio simile ( se funzionante ) sia
certamente meglio di qualcosa di più complesso a cui puoi arrivare con un
poì di pazienza. Anche a me all'inizio a fatto un po' impazzire il
WM_COPYDATA.....ricordo che sbagliavo una caxxata tremenda riguardante
sempre i puntatori e ci ho messo un giorno per capirla !! :-))))
Il bello è che in quei casi Delphi non protesta, il programma viene eseguito
ma non funziona nulla !!!!
Vabbò, ora ti saluto. In caso di problemi atroci con il WM_COPYDATA scrivimi
pure in privato. Cmq la base dovrebbe essere quella che ti ho scritto.
Ciao ciao....
Anrtonio Tarolla

Come si fą a passare dei dati con esso?
E' molto semplice.
Per semplicita', anziche' considerare due applicazioni distinte,
consideriamo due finestre della stessa applicazione.
Supponi di avere il form principale della tua applicazione
(Form1) che riceve dati da un form secondario (Form2).
Form1 ha solo un campo Edit e un bottone che visualizza Form2 e
Form2 invece possiede un campo Edit e un bottone per mandare il
contenuto di questo campo a Form1.
Form1 ha il seguente codice :
type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    procedure WMCopyData(var Msg: TMessage) ;
                        message WM_COPYDATA ;
  public
    { Public declarations }
  end;
var
  Form1: TForm1;
implementation
uses Unit2 ;
{$R *.DFM}
var Stringa : array [0..255] of Char ;
procedure TForm1.WMCopyData(var Msg: TMessage) ;
begin
  StrCopy( Stringa, PCopyDataStruct( Msg.LParam )^.lpData ) ;
  Edit1.Text := Stringa ;
end ;
procedure TForm1.Button1Click(Sender: TObject);
begin
  Form2.Show ;
end;
Form2 invece ha il seguente codice :
type
  TForm2 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  Form2: TForm2;
implementation
uses Unit1;
{$R *.DFM}
var Stringa : array [0..255] of Char ;
procedure TForm2.Button1Click(Sender: TObject);
var pcds : PCopyDataStruct ;
begin
  StrPCopy( Stringa, Edit1.Text ) ;
  pcds := New( PCopyDataStruct );
  pcds^.cbData := SizeOf( Stringa ) ;
  pcds^.lpData := @Stringa ;
  SendMessage( Form1.Handle, WM_COPYDATA, 0, LParam( pcds ) ) ;
end;
Come puoi vedere, l'uso di WM_COPYDATA e' molto semplice.
In ogni caso, se vuoi approfondire questi aspetti della
programmazione per Windows, puoi consultare MSDN
(
msdn.microsoft.com
) alla voce relativa all'IPC (Interprocess
Communications).
--
Andrea Laforgia - walkietalkie(at)
libero.it
#exclude <windows.h>

 wrote in message
9g5kkh$kcr$1...@lacerta.tiscalinet.it...


qualcosa?
Stop.  Che intendi con passare una classe ?
Passeresti dall'altra parte solo i dati (e l'altra applicazione
deve sapere bene in che modo accedere a questi dati).


 qualcosa?
credo che il procedimento non esiste.
Non capisco come si possa passare del codice da un programma all'altro.
Tu mi stai dicendo che un'altro programma dovrebbe utilizzare un oggetto che
sta in un programma totalmente differente.
Boh.....non riesco a capire come sia possibile se i puntatori non li puoi
utilizzare direttamente. Cioč il WM_COPYDATA č un messaggio che tra
applicazioni diverse,
ti permette di COPIARE qualcosa, non di RIFERIRTI a qualcosa !!
E' proprio quģ il problema. Se tu riesci a riferirti ad un'oggetto allora
quando richiami un suo metodo, chiami quello dell'oggetto stesso ( a cui ti
riferisci ). La copia č ben diversa e credo non possa funzionare !!
In pratica se il tuo sistema funziona, in teoria potresti copiare un
pulsante da una form all'altra tramite il semplice WM_COPYDATA. Perchč il
pulsante č essenzialmente un oggetto.
Cioč ho una form con un button ed una form vuota.
La prima invia un WM_COPYDATA alla seconda, dicendo di copiare l'oggetto
TButton1. A questo punto, sulla seconda form dovrebbe comparire un pulsante
identico a quello nella prima.
Per copiare i metodi, significa che deve copiare il codice binario che li
rappresenta nell'eseguibile. E poi nell'altro programma come glielo inietti
?
La cosa forse sarebbe fattibile se il primo programma ed il secondo
condividono una zona di memoria a cui possono riferirsi entrambi e l'oggetto
TMyClass sta in questa zona di memoria condivisa !!
Se invece ti riferisci a form dello stesso programma, allora il WM_COPYDATA
( se "copia" un oggetto ), ti copia un puntatore e usando questo puntatore
puoi condividere l'oggetto da varie parti del programma, ma a questo punto
meglio una variabile globale !!
Ad esempio, nella prima form ho un pulsante e nella seconda non ho nulla.
Entrambe le form conoscono il tipo TButton.
Se tu invii il button della prima form alla seconda, invii in realtą il suo
puntatore. Ora se questo puntatore lo assegni ad una variabile TButton, da
questa seconda form vedrai che usando i suoi metodi e proprietą, in realtą
andrai sempre a lavorare nel button che sta nella prima !!! Questo perchč
c'č un puntatore di mezzo.
Tu fai una cosa.
L'oggetto TMyClass, dichiaralo in entrambi i programmi perchč la copia dei
metodi te la puoi anche sognare.
In pratica, entrambi i programmi dovranno conoscere ed implementare il
TMyClass.
Ora per sincronizzare le proprietą del TMyClass nel primo programma e quello
nel secondo, puoi anche usare il WM_COPYDATA che passa i dati necessari per
far si che entrambi gli oggetti hanno gli stessi valori nelle loro
proprietą.
In ogni caso, se ci dici cosa vuoi fare di preciso, forse troviamo una
soluzione migliore !!
Ti saluto.....facci sapere !!
Antonio Tarolla

La copia è ben diversa e credo non possa funzionare !!
Non e' possibile trasferire i metodi, per il semplice motivo che
i metodi esistono *al di fuori* delle classi.
Vengono trattati dal compilatore come normali funzioni che hanno
il nome decorato in modo tale da ricondursi alla classe
d'appartenenza.  Non essendo dati della classe, non possono
neanche essere trasferiti.


 >tutti i suoi metodi e le sue proprietà..il procedimento è lo stesso o


 così leggendo alcuni mess del NG ho pensato al WM_COPYDATA
l'idea sarebbe anche utilizzabile, però non come dici tu !!
Ma questo oggetto TMyClass quante proprietà public e published ( se ci
sono ) possiede ?
Io te l'avevo già accennato come avrei fatto.
Se tu definisci un record che ti permette di individuare tutte le proprietà
da settare nell'oggetto TMyClass, ti basta solo inviare questo record ( con
il WM_COPYDATA ) nell'eseguibile. Questo ha già il suo oggetto TMyClass
creato, quindi appena riceve il messaggio WM_COPYDATA, tramite una
procedura, il record risetta le proprietà dell'oggetto. E tutto funziona
!!!!
Perchè non ti piace la soluzione ?
Me ne sta venendo in mente un'altra.
Se fino alla DLL funziona tutto, potresti iniettare la DLL nello spazio di
indirizzamento dell'eseguibile, e questo lo puoi fare benissimo con
un' hook, però sto pensando che c'è un problemino che puoi aggirare, ma a
questo punto ti conviene utilizzare quanto ti ho detto sopra !!
Ok, ti saluto. Se c'è un modo semplice per far quanto dici tu direttamente,
non lo conosco !!
Ciao ciao....
Antonio Tarolla