-1

I use this example to send a string between two applications.

When I press the Send button for the first time, the string is sent to the Receiver, but only a part of the string is received.

When I press the Send button for the second time, I get "Window not found!". The window is right there on screen. Why it works when I press the button the first time, but not the second time?


This is the sender:

procedure TfrmSender.SendString;
var
 stringToSend : string;
 copyDataStruct : TCopyDataStruct;
begin
 Caption:= 'Sending';
 stringToSend := 'About - Delphi - Programming';

 copyDataStruct.dwData := 12821676; //use it to identify the message contents
 copyDataStruct.cbData := 1 + Length(stringToSend) ;
 copyDataStruct.lpData := PChar(stringToSend);

 SendData(copyDataStruct) ;
end;



procedure TfrmSender.SendData(CONST copyDataStruct: TCopyDataStruct);
VAR
   receiverHandle : THandle;
   res : integer;
begin
 receiverHandle := FindWindow(PChar('TfrmReceiver'), PChar('frmReceiver')) ;
 if receiverHandle = 0 then
  begin
   Caption:= 'Receiver window NOT found!';
   EXIT;
  end;

 res:= SendMessage(receiverHandle, WM_COPYDATA, Integer(Handle), Integer(@copyDataStruct));
 if res= 0 then Caption:= 'Receiver window found but msg not hand';
end;

And this is the receiver:

procedure TfrmReceiver.WMCopyData(var Msg: TWMCopyData);
VAR
   s : string;
begin
 if Msg.CopyDataStruct.dwData = 12821676 then
  begin
   s := PChar(Msg.CopyDataStruct.lpData);
   msg.Result := 2006;  //Send something back

   Winapi.Windows.Beep(800, 300);
   Caption:= s;
  end
end;
Gabriel
  • 20,797
  • 27
  • 159
  • 293
  • project: https://ufile.io/1pyr5 – Gabriel Nov 14 '17 at 14:40
  • or here: https://files.fm/u/m8xxeegg – Gabriel Nov 14 '17 at 14:41
  • 1
    @RBA - nope. unrelated. that uses Pipes. I use WM_COPYDATA – Gabriel Nov 14 '17 at 14:42
  • 3
    The reason why your second attempt results in failure is because you are changing the windows caption. The second parameter of FindWindiow is the caption. – Dsm Nov 14 '17 at 14:48
  • @Dsm - the second parameters in FindWindow is the from's name, not the window caption. Or.... is it? – Gabriel Nov 14 '17 at 14:50
  • They are the same thing - see the MSDN documentation. https://msdn.microsoft.com/en-us/library/windows/desktop/ms633499(v=vs.85).aspx – Dsm Nov 14 '17 at 14:51
  • 1
    Is this 64 Bit? `Integer(@copyDataStruct)` is a common trap then. – nil Nov 14 '17 at 14:51
  • 1
    `cbData` is the size in bytes. You are setting it to length of string. Delphi 2009 and later uses `WideChar` characters. – Tom Brunberg Nov 14 '17 at 14:52
  • @Dsm - you are right. I thought there is a difference between form's name and form's caption. – Gabriel Nov 14 '17 at 14:52
  • @nil - It is 32bit app, but I changed to LPARAM. Thanks! – Gabriel Nov 14 '17 at 15:03
  • Possible duplicate of [Delphi - Message pump in thread not receiving WM\_COPYDATA messages](https://stackoverflow.com/questions/25432761/delphi-message-pump-in-thread-not-receiving-wm-copydata-messages) – Tom Brunberg Nov 14 '17 at 15:03

1 Answers1

2

To summarize the comments there are two errors

1) (See @Tom Brunberg) is that the length is set incorrectly which is why you only get part (about half? of the string)

It should be

copyDataStruct.cbData := sizeof( Char )*(Length(stringToSend) + 1 );

2) The forms caption is being changed which invalidates the expression

FindWindow(PChar('TfrmReceiver'), PChar('frmReceiver'))

because the second parameter is the form's caption (in Delphi terminology)

Dsm
  • 5,870
  • 20
  • 24
  • Thanks. PS: I used stringToSend := pchar('About - Delphi - Programming') in order to avoid hard-codding of the null char (2+). – Gabriel Nov 14 '17 at 15:08
  • 1
    I would prefer: `copyDataStruct.cbData := SizeOf(Char)*(Length(stringToSend) + 1));`. – Rudy Velthuis Nov 14 '17 at 23:07
  • @RudyVelthuis I agree - I will change. We are allowing for null, which is SizeOf( Char ) long, regardless of what size char is. – Dsm Nov 15 '17 at 08:41