Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi WM_CopyData mit Boolschen Variablen (https://www.delphipraxis.net/31022-wm_copydata-mit-boolschen-variablen.html)

Helmi 2. Okt 2004 22:48


WM_CopyData mit Boolschen Variablen
 
Hallo,

ich hab mir von unseren Freunden, den Schweizern den Code zum Kommunizieren zwischen zwei Applicationen mit WM_CopyData angeschaut.

http://www.swissdelphicenter.ch/de/showcode.php?id=810

Nur wird in diesem Code (der funktioniert, habs getestet :-)) aber ein String übertragen.

Wie kann ich dort z. B. Boolsche Variablen (es reicht auch eine) übertragen?

Was muss man in dem Code umbiegen, damit das geht?

Vielleicht kann mir jemand helfen.

mfg
Helmi

Luckie 2. Okt 2004 22:51

Re: WM_CopyData mit Boolschen Variablen
 
schreib dir einen Record, dem du lpData der TCopyDataStruct übergibst.

jfheins 2. Okt 2004 22:52

Re: WM_CopyData mit Boolschen Variablen
 
oder übertrage einfach einen string true oder false ...

Helmi 2. Okt 2004 22:56

Re: WM_CopyData mit Boolschen Variablen
 
an das hab ich auch schon gedacht

ist wahrscheinlich die einfachste Lösung.

Vor allem weil ich schon den Quellcode dafür hab :-)

cu
Helmi

Helmi 3. Okt 2004 00:01

Re: WM_CopyData mit Boolschen Variablen
 
jetzt muss ich trotzdem nochmal nachfragen:

wie kann ich denn einen Record übertragen?

Ich hab mal folgendes im Sender gemacht:

Code:
type
  CustomRec = record
    S: String[50];
    B: Boolean;
  end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Rec: CustomRec;

begin
  //
  with Rec do
    begin
      S := Edit1.Text;
      B := CheckBox1.Checked;
    end;

  with aCopyData do
    begin
      dwData := 0;
      cbData := sizeof(Rec) + 1;
      lpData := Pointer(Rec);
    end;


  // Fenster anhand des Titelzeilentext suchen
  hTargetWnd := FindWindowEx(0, 0, nil, PChar('Empfänger'));

  If hTargetWnd <> 0 then
    SendMessage(hTargetWnd, WM_COPYDATA, Longint(Handle), Longint(@aCopyData))
  else
    ShowMessage('Kein Empfänger gefunden!');
Das problem hierbei ist bei "lbData := Pointer(Rec)".
Wie kann ich den Rec dort reinbekommen? (blöde Frage ich weiss :-))

und beim Empfänger:

Code:
type
  CustomRec = record
    S: String[50];
    B: Boolean;
  end;

procedure TForm1.WMCopyData(var Msg: TWMCopyData);
var
  sText: array[0..99] of Char;
  Rec: CustomRec;

begin
  // anzuzeigenden Text aus den Parametern generieren
  StrLCopy(sText, Msg.CopyDataStruct.lpData, Msg.CopyDataStruct.cbData);

  // Empfangenen Text ausgeben
  label1.Caption := sText;


{
  with Rec do
    begin
      Label1.Caption := S;
      ALed1.Checked  := B;
    end;
}
end;
Wie kann ich beim Empfänger anstatt dem String (sText) den Rec auslesen?

mfg
Helmi

Luckie 3. Okt 2004 00:36

Re: WM_CopyData mit Boolschen Variablen
 
Übergib einen Zeiger auf den Record:
Delphi-Quellcode:
type
  TMyRec = record;
    ...: ...;
  end;
  PMyRec = ^TMyRec;

Luckie 3. Okt 2004 00:57

Re: WM_CopyData mit Boolschen Variablen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Und hier noch mal ein komplettes Beispiel. Gesendet wird zwar an das eigene Fenster, aber du kannst ja das Handle des gewünschten Fensters angeben.
Delphi-Quellcode:
type
  TMyRecord = packed record
    b: Boolean;
    s: string[255];
  end;
  PMyRecord = ^TMyRecord;

type
  TForm1 = class(TForm)
    Button1: TButton;
    CheckBox1: TCheckBox;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure WMCOPYDATA(var msg: TWMCOPYDATA); message WM_COPYDATA;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.WMCOPYDATA(var msg: TWMCOPYDATA);
var
  MyRecord: PMyRecord;
begin
  MyRecord := msg.CopyDataStruct.lpData;
  CheckBox1.Checked := MyRecord.b;
  Edit1.Text := MyRecord.s;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  MyRecord: PMyRecord;
  cds: TCopyDataStruct;
begin
  GetMem(MyRecord, sizeof(TMyRecord));
  try
    MyRecord.b := True;
    MyRecord.s := 'Hello world';
    cds.dwData := 0;
    cds.cbData := sizeof(TMyRecord);
    cds.lpData := MyRecord;
    SendMessage(Handle, WM_COPYDATA, Handle, Integer(@cds));
  finally
    FreeMem(MyRecord, sizeof(TMyRecord));
  end;
end;
Im Anhang noch mal komplett mit zwei Fenstern.

Helmi 3. Okt 2004 08:22

Re: WM_CopyData mit Boolschen Variablen
 
Danke Luckie für deine Hilfe :-)
und das noch so spät :hello:

aber eine Frage hätt ich noch:

wieso geht das ned:

Code:
  var
  MyRecord: PMyRecord;
begin
  MyRecord := msg.CopyDataStruct.lpData;
 
  with MyRecord do
    begin
      CheckBox1.Checked := b;
      Edit1.Text := s;
    end;
end;
Ich benutz gerne with xxx do und wollt das dort auch benutzen, geht aber ned.
Kann das mit dem Pointer zusammen hängen?

mfg
Helmi

Luckie 3. Okt 2004 10:02

Re: WM_CopyData mit Boolschen Variablen
 
Ich habe den Empfänger eben noch etwas verbessert:
Delphi-Quellcode:
type
  TMyRecord = packed record
    b: Boolean;
    s: string[255];
  end;
  PMyRecord = ^TMyRecord;

procedure TForm1.WMCOPYDATA(var msg: TWMCopyData);
var
  b: Boolean;
  s: String[255];
begin
  b := PMyRecord(msg.CopyDataStruct.lpData)^.b;
  s := PMyRecord(msg.CopyDataStruct.lpData)^.s;
  CheckBox1.Checked := b;
  Edit1.Text := s;
end;
Und für deine neue Frage, solltest du einen neuen Thread erstellen, das hat nichts mehr mit WM_COPYDATA zu tun.

mirage228 3. Okt 2004 10:25

Re: WM_CopyData mit Boolschen Variablen
 
Zitat:

Zitat von Helmi
Ich benutz gerne with xxx do und wollt das dort auch benutzen, geht aber ned.
Kann das mit dem Pointer zusammen hängen?

mfg
Helmi

Hoi,

das geht, soweit ich weiss, so:

Delphi-Quellcode:
with MyRecord^ do
mfG
mirage228

Luckie 3. Okt 2004 10:27

Re: WM_CopyData mit Boolschen Variablen
 
Argh. Hättest du nicht warten können bis er einen neuen Thread aufmacht? Hier findet das doch keiner. Oder würdest du einen Thread öffnen, wenn du nach with..do suchst, bei dem im Betreff was von WM_COPPYDATA steht? :roll:

Helmi 3. Okt 2004 10:30

Re: WM_CopyData mit Boolschen Variablen
 
grins :-)

danke an euch beide :-)

Nogge 31. Okt 2005 10:54

Re: WM_CopyData mit Boolschen Variablen
 
Zitat:

Zitat von Luckie
Delphi-Quellcode:
  GetMem(MyRecord, sizeof(TMyRecord));

1.) Sollte ein Pointer nicht eher mit New initialisiert werden?
2.) Ich habe die non-record- und record-Variante für TStringList bzw. TStrings ausprobiert (Dll -> Programm). Jedoch erhalte ich jedesmal eine AV, wenn ich innerhalb der WM_COPYDATA-Proc auf den Pointer der StringList bzw. des record zugreife. Kann mir jemand sagen, wieso dort immer ne Fehlermeldung erscheint? (Liegt es vllt daran, dass in TStrings bzw. TStringList undefinierte Strings enthalten sind? In einem record muss man ja immer eine max. Länge für jeden String angeben...)

Flocke 31. Okt 2005 12:20

Re: WM_CopyData mit Boolschen Variablen
 
@Nogge: Die Daten müssen vollständig in dem Record stehen. Du darfst dort also keine Zeiger benutzen - die sind im Adressraum der anderen Anwendung unbekannt.

Nogge 31. Okt 2005 12:26

Re: WM_CopyData mit Boolschen Variablen
 
Im record selbst stehen ja auch meine vollständigen Daten:
Delphi-Quellcode:
type
  PRecordList = ^TRecordList;
  TRecordList = record
    StringList : TStringList;
  end;
  [...]
  if (MainApp > 0) and (SLData.Count > 0) then
  begin
    New(SLPointer);
    SLPointer^.StringList:=TStringList.Create;
    SLPointer^.StringList.AddStrings(SLData);
    with CDS do
    begin
      dwData:=LoWord(lpici.lpVerb); // MY_PLAY(0) oder MY_ADD(1)
      cbData:=SizeOf(TRecordList);
      lpData:=SLPointer;
    end;
    SendMessage(MainApp,WM_COPYDATA,0,LParam(@CDS));
  end;

SirThornberry 31. Okt 2005 12:41

Re: WM_CopyData mit Boolschen Variablen
 
@Nogge: In deinem Record stehen NICHT die vollständigen Daten. Du hast dort Maximal eine Varible vom Typ TStringlist was wiederum nur ein Pointer ist auf die Instanz.

Nogge 31. Okt 2005 12:47

Re: WM_CopyData mit Boolschen Variablen
 
Ah, verstehe. Kann ich stattdessen ein array of string[255] im record deklarieren? Müsste doch gehen, da es ausgeschrieben ein array of array of Char wäre, oder?

SirThornberry 31. Okt 2005 13:07

Re: WM_CopyData mit Boolschen Variablen
 
ein "Array of String[255]" geht auch nicht da es ja dann ein dynamiches Array ist. Und ein dynamisches Array ist auch ein pointer. ein "Array[von..bis] of string[255]" geht jedoch da es staatich ist und somit nicht dynamisch speicher angefodert wird.

Da es bei einem Dynamischen Array aber wie bei einem String ist (ist ein Zeiger der auf die zusammenhängenden Datein zeigt), kannst du auch einfach den Bereich angeben auf den der ArrayPointer zeigt.

Flocke 31. Okt 2005 13:32

Re: WM_CopyData mit Boolschen Variablen
 
Wenn du eine Stringliste übergeben willst, dann benutze einfach die Eigenschaft Text und übergib den gesamten Inhalt (alle Zeilen) als ein String (also kein Record).

SirThornberry 31. Okt 2005 13:35

Re: WM_CopyData mit Boolschen Variablen
 
@Flocke: In dein meisten fällen mag dies funktionieren, allerdings gibt es auch fälle in denen das Ergebnis auf der Empfängerseite dann verfälscht ist. Hier ein Beispiel wo es nicht funktioniert:
Delphi-Quellcode:
var LStrList: TStringlist;
begin
  LStrList := TStringList.Create;
  LStrList.Add('zeile1-Teil1' + #13#10 + 'zeile1-Teil2');
  LStrList.Add('zeile2');
auf der Empfängerseite wären das dann aber 3 einträge in der Stringlist, auf der Senderseite sind es jedoch nur 2 Einträge.

Nogge 31. Okt 2005 14:16

Re: WM_CopyData mit Boolschen Variablen
 
Zitat:

Zitat von SirThornberry
Da es bei einem Dynamischen Array aber wie bei einem String ist (ist ein Zeiger der auf die zusammenhängenden Datein zeigt), kannst du auch einfach den Bereich angeben auf den der ArrayPointer zeigt.

Die Methode gefällt mir. Allerdings bin ich gerade noch im Hinblick auf cbData rastlos:
Delphi-Quellcode:
type
  PStringArray = ^TStringArray;
  TStringArray = array of String[255];
  [...]
var
  SAPointer : PStringArray;
  [...]
  if (MainApp > 0) and (SLData.Count > 0) then
  begin
    New(SAPointer);
    SetLength(SAPointer^,SLData.Count);
    for i:=0 to SLData.Count-1 do
      SAPointer^[i]:=SLData.Strings[i];
    with CDS do
    begin
      dwData:=LoWord(lpici.lpVerb); // MY_PLAY(0) oder MY_ADD(1)
      cbData:=???;
      lpData:=SAPointer;
    end;
    SendMessage(MainApp,WM_COPYDATA,0,LParam(@CDS));
  end;
Müsste ich die Länge des arrays mit der max. Länge (=256) der Strings multiplizieren?

SirThornberry 31. Okt 2005 16:51

Re: WM_CopyData mit Boolschen Variablen
 
genau so ist es. Wenn ein StringEllement eine größe von 255 Bytes hat so kannst du mit multiplication der Anzahl die gesamtgröße herausfinden. und wie du selbst schon geschrieben hast ist die größe eines Strings bei "[255]" gleich 256 Bytes. Aber sowas sollte man am besten mit "SizeOf" abfragen und nicht festen in den Quellcode tippen.

Olli 31. Okt 2005 19:22

Re: WM_CopyData mit Boolschen Variablen
 
Kann mir jemand von euch verraten, wieso man das über WM_COPYDATA machen würde? Das ist doch totaler Quark wenn ich nur Boolsche Variable übergeben will.

Mit LPARAM und WPARAM habe ich bei einer selbstdefinierten Fensternachricht ganze 64 Boolwerte, die ich auf einfachste Weise und ohne Zeigerfrickeleien übertragen kann.

Habe ich in der Frage was überlesen?

Nogge 1. Nov 2005 21:39

Re: WM_CopyData mit Boolschen Variablen
 
Mmh, leider ist der Versuch fehlgeschlagen ;_;
Delphi-Quellcode:
cbData:=Length(SAPointer^) * SizeOf(ShortString);
Mit dieser Länge erhalte ich nun zwar keine AV mehr, jedoch ist der Inhalt des arrays vollkommen willkürlich gefüllt. Hier mal mein Code vom Empfängerprogramm:
Delphi-Quellcode:
procedure TFMain.WMCopyData(var Msg: TWMCopyData);
type
  PStringArray = ^TStringArray;
  TStringArray = array of ShortString;
const
  MY_PLAY = 0;
  MY_ADD = 1;
var
  SAPointer : PStringArray;
  i : Integer;
  FileName : ShortString;
  [...]
begin
  SAPointer:=PStringArray(Msg.CopyDataStruct.lpData);
  if (SAPointer = nil) then exit;
  [...]
  try
    case Msg.CopyDataStruct.dwData of
      MY_PLAY :
        begin
          for i:=Low(SAPointer^) to High(SAPointer^) do
          begin
            FileName:=SAPointer^[i];
            [...]
          end;
        end;
      MY_ADD :
        begin
          for i:=Low(SAPointer^) to High(SAPointer^) do
          begin
            FileName:=SAPointer^[i];
            [...]
          end;
        end;
      MY_SHOW :
        begin
          [...]
        end;
    end;
  finally
    [...]
    // Einzelelemente freigeben
    for i:=High(SAPointer^) downto Low(SAPointer^) do
      SetLength(SAPointer^[i],0);
    // array freigeben
    SetLength(SAPointer^,0);
    Dispose(SAPointer);
  end;
end;

Olli 1. Nov 2005 21:52

Re: WM_CopyData mit Boolschen Variablen
 
Wie sieht denn dein Code zum Senden aus? Warum benutzt du einen Pointer vor dem Senden? Warum nicht einfach @ und dann dein Array von Shortstrings?

Nogge 4. Nov 2005 21:33

Re: WM_CopyData mit Boolschen Variablen
 
Mein Code zum Senden steht doch bereits weiter oben im Thread. Kannste deine Lösungsmöglichkeit vllt genauer erläutern und etwas Sourcecode hinzufügen?

Olli 4. Nov 2005 22:11

Re: WM_CopyData mit Boolschen Variablen
 
Zitat:

Zitat von Nogge
Mein Code zum Senden steht doch bereits weiter oben im Thread. Kannste deine Lösungsmöglichkeit vllt genauer erläutern und etwas Sourcecode hinzufügen?

Ging das an mich? SendMessage hat 4 Parameter von denen 2 frei definierbar sind, wenn man sich seine eigenen Nachrichten bastelt. Da es sich um "DWORD"s handelt, hat man 2x32bit = 64bit. Jedes Bit hat den Wert 0 oder 1 und kann somit als Boolean dienen. Wenn man also nur Booleans übertragen will, fährt man ohne den Umweg über WM_COPYDATA weit besser und schneller.

Nogge 4. Nov 2005 22:17

Re: WM_CopyData mit Boolschen Variablen
 
Jo, das ging an dich. Allerdings bezog sich meine Frage auf deine letzte Antwort, wo du mir etwas über meine Methoden zum Senden von einem bzw. mehreren Strings sagen wolltest. Deine Methoden mit der eigenen Nachricht habe ich schon verstanden, darum ging es mir ja nicht^^

Olli 4. Nov 2005 22:22

Re: WM_CopyData mit Boolschen Variablen
 
Zitat:

Zitat von Nogge
Allerdings bezog sich meine Frage auf deine letzte Antwort, wo du mir etwas über meine Methoden zum Senden von einem bzw. mehreren Strings sagen wolltest.

Nee, das waren ernsthafte Fragen. In deinem Code mit dem Stringarray zeigst du ja nur die Empfangsseite, oder stehe ich auf dem Schlauch?

Nogge 4. Nov 2005 22:38

Re: WM_CopyData mit Boolschen Variablen
 
Ne, weiter oben (#21) steht mein Sende-Code ;-)

Olli 4. Nov 2005 22:48

Re: WM_CopyData mit Boolschen Variablen
 
Warum hast du einmal String[255] und einmal ShortString für die Array-Elemente?

Nogge 4. Nov 2005 22:51

Re: WM_CopyData mit Boolschen Variablen
 
Macht das einen Unterschied? ShortString ist doch definiert als String[255], oder etwa nicht?

Olli 4. Nov 2005 22:54

Re: WM_CopyData mit Boolschen Variablen
 
Zitat:

Zitat von Nogge
Macht das einen Unterschied? ShortString ist doch definiert als String[255], oder etwa nicht?

Ähem, ich bin mir da nicht so ganz sicher, ob das die exakte Definition ist (habe aber auch kein Delphi zur Hand). Im Regelfall sollte man auf beiden Seiten identische Typen verwenden.

Selbst wenn es jetzt noch keinen Unterschied macht, so kann sich dies theoretisch jederzeit ändern.

Außerdem wundere ich mich soeben, ob man dynamische Arrays überhaupt so übergeben kann. Denn eigentlich verhalten sich doch dynamische Arrays für Pointertypen auf die Elementtypen (des Arrays), oder?


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:10 Uhr.

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