Mega Code Archive

 
Categories / Delphi / Examples
 

Using WM_COPYDATA

Title: Using WM_COPYDATA Question: How can I use the WM_COPYDATA message to pass information between 16-bit and 32-bit applications? Answer: The following example shows how to use the WM_COPYDATA message to send a record containing data between a 16-bit and 32-bit application. This method can also be used to call 16-bit or 32-bit dll from a 16-bit or 32-bit application (known as thunking). Thunking can be accomplished by creating an invisible window to respond to the WM_COPYDATA message, and call the dll in your behalf. Compile the following unit source code under both 16-bit and 32-bit versions of Delphi. Use separate directories for the two projects. Each project will require a form, a button, and a memo component on it's form. To use the WM_COPYDATA message, you must send the address of a TCopyDataStruct to the receiving window. The dwData parameter of the TCopyDataStruc is a user defined parameter that allows you to store any 32 bit value you wish, for additional information. The cbData member of the TCopyDataStruc contains the size of the data pointed to by the lpData member of the TCopyDataStruc. The lpData parameter of the TCopyDataStruct can point to any data structure you wish. Note that any pointers contained in the structure you send will not be valid from the receiving application since windows has no way to convert them. Note that the data that is passed to the receiving application is only valid during the call. If the receiving application needs to retain the information passed, it should make a copy of the data that is local to the receiving application. The receiving application should not modify the data that is passed during the call. If modifications are necessary, the receiving application should make a local copy of the data, and send a WM_COPYDATA message back to the sending application using the modified copy. It's worth noting that the WM_COPYDATA message will work going to and from any combination of 16/32 bit applications. Finally, be aware that the call to SendMessage will not return untill the message is processed. Also be aware that you should never use PostMessage() with the WM_COPYDATA message. unit Unit1; interface {$IFDEF WIN32} uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; {$ELSE} uses SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; {$ENDIF} const WM_COPYDATA = $004A; type TForm1 = class(TForm) Memo1: TMemo; Button1: TButton; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); private { Private declarations } procedure WMCopyData(var m : TMessage); message WM_COPYDATA; public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} type PCopyDataStruct = ^TCopyDataStruct; TCopyDataStruct = record dwData: LongInt; cbData: LongInt; lpData: Pointer; end; type PRecToPass = ^TRecToPass; TRecToPass = packed record s : string[255]; i : integer; end; procedure TForm1.FormCreate(Sender: TObject); begin {$IFDEF WIN32} Form1.Caption := 'My 32-Bit App' {$ELSE} Form1.Caption := 'My 16-Bit App' {$ENDIF} end; procedure TForm1.WMCopyData(var m : TMessage); begin Memo1.Lines.Add('Sending Window Handle := ' + IntToStr(m.WParam)); Memo1.Lines.Add('Data Size := ' + IntToStr(PCopyDataStruct(m.LParam)^.cbData)); Memo1.Lines.Add('User Defined Data Param := ' + IntToStr(PCopyDataStruct(m.LParam)^.dwData)); Memo1.Lines.Add('TRecToPass.s := ' + PRecToPass(PCopyDataStruct(m.LParam)^.lpData)^.s); Memo1.Lines.Add('TRecToPass.i := ' + IntToStr( PRecToPass(PCopyDataStruct(m.LParam)^.lpData)^.i)); end; procedure TForm1.Button1Click(Sender: TObject); var h : THandle; cd : TCopyDataStruct; rec : TRecToPass; begin {$IFDEF WIN32} h := FindWindow(nil, 'My 16-Bit App'); rec.s := 'Hello World From: My 32-Bit App'; rec.i := 32; cd.dwData := 3232; {$ELSE} h := FindWindow(nil, 'My 32-Bit App'); rec.s := 'Hello World From: My 16-Bit App'; rec.i := 16; cd.dwData := 1616; {$ENDIF} cd.cbData := sizeof(rec); cd.lpData := @rec; if h 0 then SendMessage(h, WM_COPYDATA, Form1.Handle, LongInt(@cd)); end; end.