Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to pass a string via a SendMessage?

Status
Not open for further replies.

LucieLastic

Programmer
May 9, 2001
1,694
GB
hi

I'm trying to pass a 13 character string to another app using a PostMessage or SendMessage call. I have the same RegisterWindowMessage in each FormCreate. The receiving code just keeps getting a null terminated string. Can anyone help?

Tried all sorts but can't get it to work:

Code:
//The sending code
procedure TForm1.Button1Click(Sender: TObject);
  var pMsg : array[0..12] of char;
      Msg  : string;
begin
  Msg := edMsg.text;
  pMsg := 'NEED HELP';

  SendMessage(FindWindow('TForm1', 'Recipient'), WMStr, integer(@Msg), 0);
//SendMessage(FindWindow('TForm1', 'Recipient'), WMStr, integer(@pMsg), 0);
end;
Code:
//The receiving code
procedure TForm1.DefaultHandler(var msg);
  var smsg : string;
begin
  inherited DefaultHandler(Msg);
  if (TMessage(msg).msg <> WMStr) then
      EXIT;

  sMsg := String(Pointer(TMessage(Msg).WParam));
//  sMsg := StrPas(Pointer(TMessage(Msg).WParam));
  lbMsg.caption := smsg;
end;

Many thanks in advance
Lou
 
I've got it to work (thanks to an old post by StretchWickster)
Sending code
Code:
procedure TForm1.Button1Click(Sender: TObject);
  var DataStruct : CopyDataStruct;
begin
  DataStruct.dwData := 0;
  DataStruct.cbData := length(edMsg.text)+1;
  DataStruct.lpData := pchar(EdMsg.text);

  SendMessage(FindWindow('TForm1', 'Recipient'),
                          WM_CopyData, Form1.handle, integer(@DataStruct));

end;

Receiving code
Code:
    procedure CopyData(var Msg: TWMCopyData); message wm_CopyData;
:
procedure TForm1.CopyData(var Msg: TWmCopyData);
var sMsg: String;
begin
  if IsIconic(Application.Handle) then
    Application.Restore;
  sMsg := PChar(Msg.CopyDataStruct.lpData);
  lbMsg.Caption := sMsg;
end;
 
You cant pass a pointer directly between processes, they are working in different address spaces.

That is why you need to use WM_COPYDATA, which is marshalling your pointer and making the data accessable in the receiver end.

buho (A).
 
Hi Lou,

I read your first post and was just about to start digging for that old WM_COPYDATA post, but looks like you already found it!

Clive
Runner_1Revised.gif

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"To err is human, but to really foul things up you need a computer." (Paul Ehrlich)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To get the best answers from this forum see: faq102-5096
 

Another way is to "borrow" the technique used by DDE. Take a look at the "atom" functions. In particular:

GlobalAddAtom
GlobalGetAtomName
GlobalDeleteAtom

The first program adds the global atom to the global atom table, then passes the value as wParam or lParam in the message.

The second program processes the message, retrieves the string with GlobalGetAtomName and then deletes the atom. Couldn't be simpler. Also that way you could use PostMessage and close the first application (if appropriate) and the second program will still "get the message."

 
Thanks everyone. We are, in fact, using the GlobalAddAtom in another bit of code too (I've discovered) [smile2].

Lou
 
Direct passing of any variable, but particularly strings, is dicey. It's always better to explicitly create your own memory-buffer, copy the value into it, use the buffer, and ("finally") discard it. Takes a slight bit of work but it's much more robust. It avoids the sort of problems that surface long after an app has been "tested" and shipped to a customer.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top