-1

I have a delphi application loading a delphi dll which will send messages back to it. For testing, I have the dll sending message to another application, but they are not showing up.

dll code

type
  TSampleRecord = packed record
    card : string[50];
  end;

var
  handle: HWND;

procedure PrepareDLL(AppHandle : HWND); stdcall;
begin
  handle := AppHandle;
end;

procedure ConfigccDLL(Variables: PChar); stdcall;
var
  sampleRecord: TSampleRecord;
  copyDataStruct: TCopyDataStruct;
  receiverHandle: HWND;
begin
  sampleRecord.card := 'FakeCard';

  copyDataStruct.dwData := Integer(2);
  copyDataStruct.cbData := SizeOf(sampleRecord);
  copyDataStruct.lpData := @sampleRecord;

  receiverHandle := FindWindow(PChar('TReceiverMainForm'),PChar('ReceiverMainForm'));
  SendMessage(receiverHandle, WM_COPYDATA, Integer(Handle), Integer(@copyDataStruct));
end;

Receiver code

type
  TSampleRecord = packed record
    card : string[50];
  end;

  TReceiverMainForm = class(TForm)
    cdMemo: TMemo;
    procedure FormCreate(Sender: TObject);
  private
    procedure WMCopyData(var Msg : TWMCopyData); message WM_COPYDATA;
    procedure HandleCopyDataRecord(copyDataStruct : PCopyDataStruct);
  end;

var
  ReceiverMainForm: TReceiverMainForm;

implementation

procedure TReceiverMainForm.FormCreate(Sender: TObject);
begin
  cdMemo.Clear;
end;

procedure TReceiverMainForm.HandleCopyDataRecord(
  copyDataStruct: PCopyDataStruct);
var
  CodeRcvd: string;
  sampleRecord : TSampleRecord;
begin
  sampleRecord.card := TSampleRecord(CopyDataStruct.lpData^).card;

  CodeRcvd := '$B';

  cdMemo.Lines.Add(Format('Received record at %s',[DateToStr(Now)]));
  cdMemo.Lines.Add(CodeRcvd);
  cdMemo.Lines.Add(Format('sampleRecord.card = %s',[sampleRecord.card]));
  cdMemo.Lines.Add(Format('sampleRecord size: %d %d',[SizeOf(sampleRecord), copyDataStruct.cbData]));
end;

procedure TReceiverMainForm.WMCopyData(var Msg: TWMCopyData);
begin
  cdMemo.Lines.Add(Format('WM_CopyData from: %d',[msg.From]));

  HandleCopyDataRecord(Msg.CopyDataStruct);

  msg.Result := cdMemo.Lines.Count;
end;

end.

PrepareDLL gets passed the handle of the delphi application which calls the DLL.

The last two functions aren't implemented yet. I can post the receiver code if needed but it is working fine with other delphi applications built to be 'sender's.

The functions themselves get called fine, ShowMessage() function calls work.

I've checked the return code of SendMessage and RaiseLastError and they both state success.

I have a feeling this might have to do with UIPI but I've checked the 'integrity' of both applications with ProcessExplorer and they are both set to Medium.

This is on Windows Vista.

Nils Guillermin
  • 1,867
  • 3
  • 21
  • 51

1 Answers1

0

It does not work for me on Windows 10 only if Receiver is run as administrator. In this case you'll need following to allow it.

type
  TChangeFilterStruct = packed record
    cbSize: DWORD;
    ExtStatus: DWORD;
  end;
  PChangeFilterStruct = ^TChangeFilterStruct;

const
  MSGFLT_ALLOW = 1;
  MSGFLT_DISALLOW = 2;
  MSGFLT_RESET = 0;

{$WARN SYMBOL_PLATFORM OFF}
function ChangeWindowMessageFilterEx(Wnd: HWND; Message: UINT; Action: DWORD;
  ChangeFilterStruct: PChangeFilterStruct): Bool; stdcall; external 'User32.dll' delayed;
{$WARN SYMBOL_PLATFORM ON}


    ChangeWindowMessageFilterEx(ReceiverWindowHandle, WM_COPYDATA, MSGFLT_ALLOW, nil);

Update Actually this function only exists since Windows 7, for Vista you need to use ChangeWindowMessageFilter

EugeneK
  • 2,164
  • 1
  • 16
  • 21