Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   FindWindow und WM_COPYDATA (https://www.delphipraxis.net/201045-findwindow-und-wm_copydata.html)

Gler 18. Jun 2019 16:06

FindWindow und WM_COPYDATA
 
Da ich nicht sicher war in welches UnterForum mein Problem gehört:
Ich würde gerne mit SendMessage und WW_COPYDATA einen einfachen String zwischen einem Delphi-3 Programm und einem Delphi-10-Programm senden.
In D3 zu arbeiten ist hier leider nicht optional, aber auch (hoffentlich) nicht das Problem.

Um das nicht in den Hauptprogrammen zu testen habe ich mit dazu flott zwei neue Programme erstellt, mit folgendem Code:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  aCopyData: TCopyDataStruct;
  hTargetWnd: HWND;
  s:string;
begin
  s:='test';
  with aCopyData do
  begin
    dwData := 0;
    cbData := StrLen(PChar(s)) + 1;
    lpData := PChar(s)
  end;

 hTargetWnd:=FindWindow(nil,'test');
 htargetWnd:=strtoint(Edit1.Text);       //weil findwindow nicht das richtige liefert
 if hTargetWnd <> 0 then
    SendMessage(hTargetWnd, WM_COPYDATA, Longint(Handle), Longint(@aCopyData))
  else
    ShowMessage('No Recipient found!');
end;
Zum Ersten gibt mir FindWindow ein falsches Handle.
Zwar wird hier scheinbar irgendwas vom anderen Programm gefunden, wenn denn das zweite Programm nicht gestartet ist kriege ich hier 0, aber was gefunden wird ist grundsätzlich verschieden vom Handle dass ich zum testen am zweiten Programm direkt ausgebe - und wenn ich das dann von Hand ins Edit-Feld eingebe funktioniert das senden auch.

Zum Zweiten scheint sich mir beim Auslesen irgendwo ein Fehler eingeschlichen zu haben - erst hatte ich einfach label1.Caption := Stext, allerdings hat mir das immer nur den ersten Buchstaben ausgegeben, dann habe ich versucht das Array auszulesen, aber das hat noch weniger geklappt (wobei hier sicher nur ein saublöder Struddelfehler drinne ist)

Delphi-Quellcode:
procedure TForm1.WMCopyData(var Msg: TWmCopyData);
var
  sText: array[0..99] of Char;
    i: Integer;
  s: string;
begin

  StrLCopy(sText, Msg.CopyDataStruct.lpData, Msg.CopyDataStruct.cbData);

  s := '';
  for i:=1 to length(Stext) do
    begin
      s := s + sText[i];
    end;
  label1.Caption := s;
end;

Danke im Vorraus

peterbelow 18. Jun 2019 17:15

AW: FindWindow und WM_COPYDATA
 
Zitat:

Zitat von Gler (Beitrag 1434963)
Da ich nicht sicher war in welches UnterForum mein Problem gehört:
Ich würde gerne mit SendMessage und WW_COPYDATA einen einfachen String zwischen einem Delphi-3 Programm und einem Delphi-10-Programm senden.
In D3 zu arbeiten ist hier leider nicht optional, aber auch (hoffentlich) nicht das Problem.

Um das nicht in den Hauptprogrammen zu testen habe ich mit dazu flott zwei neue Programme erstellt, mit folgendem Code:

Siehe Änderungen im Code:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  aCopyData: TCopyDataStruct;
  hTargetWnd: HWND;
  s:string;
begin
  s:='test';
  with aCopyData do
  begin
    // tell receiver the size of a char!
    dwData := sizeof(char);
// Nicht Unicode-kompatibel!!
//    cbData := StrLen(PChar(s)) + 1;
    cbData := (Length(s)+ 1)*Sizeof(char);
    lpData := PChar(s)
  end;

 hTargetWnd:=FindWindow(nil,'test');
 htargetWnd:=strtoint(Edit1.Text);       //weil findwindow nicht das richtige liefert
 if hTargetWnd <> 0 then
    SendMessage(hTargetWnd, WM_COPYDATA, Longint(Handle), Longint(@aCopyData))
  else
    ShowMessage('No Recipient found!');
end;
Delphi-Quellcode:
procedure TForm1.WMCopyData(var Msg: TWmCopyData);
  procedure UnsupportedCharsize;
  begin
    assert(false, 'Unsupported character size');
  end;
var
  s: string;
begin
  case sizeof(char) of
    1: begin
         // target is ansistring
         if msg.dwdata = 1 then
           s:= PChar(msg.lpdata)
         else if msg.dwdata = 2 then
           s:= widecharToString(pwidechar(msg.lpdata))
         else
          UnsupportedCharsize;
       end;
    2: begin
         // target is unicodestring
         if msg.dwdata = 2 then
           s:= PChar(msg.lpdata)
         else if msg.dwdata = 1 then
           s:= String(Ansistring(pansichar(msg.lpdata)))
         else
          UnsupportedCharsize;
       end;
  else
    UnsupportedCharsize;
  end;

  label1.Caption := s;
end;
Ungetestet!

Dein Problem mit FindWindow ist einfach, dass deine Parameter zu unspezifisch sind. Versuch mal,anstelle von nil für den Klassennamen wirklich den Namen der Formklasse zu verwenden. Der sollte dann aber nicht gerade TForm1 sein :wink:, Du brauchst was eindeutiges.

samso 18. Jun 2019 17:31

AW: FindWindow und WM_COPYDATA
 
Problem 1:
FindWindow gibt Dir halt das erste beste Fenster mit dem Text "Test" zurück. Bei Windows ist aber fast alles ein Fenster. Nicht nur das was wir als Fenster kennen. Auch ein Button ist gern mal ein Fenster (jedenfalls für "FindWindow"). Eine erste Lösung (Im Sinne von Quick&Dirty) kann sein, dass Du einen hinreichend eindeutigen Namen für die Fensterklasse vergibst. Also statt "TForm" nennst Du das Dingen "TMeineEmfaengerForm". Dann änderst Du den Aufruf in
Delphi-Quellcode:
hTargetWnd:=FindWindow('TMeineEmfaengerForm', nil);
.

Problem 2:
Wenn Du zwischen Delphi 3 und Delphi 10 Strings austauschen willst, musst Du bedenken, dass bei Delphi 3 ein String ein AnsiString ist. Bei Delphi 10 ist es aber eine UTF16-String. Für den Test kannst Du bei dem Delphi 10-Programm auf AnsiStrings wechseln.

Beim Sender unter Delphi 10
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  aCopyData: TCopyDataStruct;
  hTargetWnd: HWND;
  s:Ansistring;
begin
  s:='test';
  with aCopyData do
  begin
    dwData := 0;
    cbData := Length(s) + 1;
    lpData := PAnsiChar(s);
  end;

 hTargetWnd:=FindWindow('TMeineEmfaengerForm',nil);
 if hTargetWnd <> 0 then
    SendMessage(hTargetWnd, WM_COPYDATA, Longint(Handle), Longint(@aCopyData))
  else
    ShowMessage('No Recipient found!');
end;
Beim Empfänger unter Delphi 10
Delphi-Quellcode:
procedure TMeineEmfaengerForm.WMCopyData(var Msg: TWmCopyData);
var
  s: Ansistring;
begin
  SetString(s, PAnsiChar(Msg.CopyDataStruct.lpData), Msg.CopyDataStruct.cbData);
  label1.Caption := String(s);
end;

Gler 19. Jun 2019 10:24

AW: FindWindow und WM_COPYDATA
 
Super,danke euch, das hat funktioniert.

Das D3 und D10 ein ganz anderes Format benutzen war mir komplett entfallen - vor Urzeiten schonmal extra notiert und dann nie wieder den Zettel gelesen.
Und die Parameter von FindWindow hatte ich scheinbar nicht ganz verstanden.


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:36 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz