DelphiFAQ Home Search:

Pass data from 16bit to 32bit applications with WM_COPYDATA.

 

commentsThis article has not been rated yet. After reading, feel free to leave comments and rate it.

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 { TForm1.FormCreate }
{$IFDEF WIN32}
  Form1.Caption := 'My 32-Bit App'

{$else}
  Form1.Caption := 'My 16-Bit App'
 {$ENDIF}
  end; { TForm1.FormCreate }


procedure TForm1.WMCopyData(var m: TMessage);
begin { TForm1.WMCopyData }
  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; { TForm1.WMCopyData }


procedure TForm1.Button1Click(Sender: TObject);
var
  h: THandle;
  cd: TCopyDataStruct;
  rec: TRecToPass;
begin { TForm1.Button1Click }
{$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; { TForm1.Button1Click }


end.
You don't like the formatting? Check out SourceCoder then!

Comments:

 

 

NEW: Optional: Register   Login
Email address (not necessary):

Rate as
Hide my email when showing my comment.
Please notify me once a day about new comments on this topic.
Please provide a valid email address if you select this option, or post under a registered account.
 

Show city and country
Show country only
Hide my location
You can mark text as 'quoted' by putting [quote] .. [/quote] around it.
Please type in the code:

Please do not post inappropriate pictures. Inappropriate pictures include pictures of minors and nudity.
The owner of this web site reserves the right to delete such material.

photo Add a picture: