Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Stringumwandlung (https://www.delphipraxis.net/145508-stringumwandlung.html)

Berni68 3. Jan 2010 09:28


Stringumwandlung
 
Hallo zusammen,

um Strings zwischen 2 Anwendungen auszutauschen verwende ich (Code aus der DP):
Sender:
Delphi-Quellcode:
WindowsNachrichtAn('Tx', 'x', '#TEXT#');
Empfänger:
Delphi-Quellcode:
procedure Tx.WMCopyData(var Msg:TWMCopyData) ;
var
  h: PChar;
begin
  h:= Msg.CopyDataStruct.lpData;
  Showmessage(h);
end;
wobei:
Delphi-Quellcode:
procedure WindowsNachrichtAn(Fensterklasse, Fenstername, Nachricht:string);
var
  CopyDataStruct: TCopyDataStruct;
  ReceiverHandle: THandle;
begin
  CopyDataStruct.dwData:= 0;
  CopyDataStruct.cbData:= 1 + Length(Nachricht);
  CopyDataStruct.lpData:= PChar(Nachricht);

//  ReceiverHandle:= FindWindow(PChar(Fensterklasse),nil);
  ReceiverHandle:= FindWindow(PChar(Fensterklasse),PChar(Fenstername));
  if ReceiverHandle<>0 then begin
    SendMessage(ReceiverHandle, WM_COPYDATA, Longint(Handle), Longint(@copyDataStruct));
  end;
end;
Hat bisher unter XP und Delphi5 einwandfrei geklappt.

Mit Delphi10 und win7 erhalte ich für das Beispiel '#TEXT#'
im Showmessagefenster:
#TEX(viereck)(chinesisches Zeichen)
die Länge ist in Ordnung, nur die beiden letzten Zeichen kommen falsch an.

Weiss jemand woran das liegen könnte?

turboPASCAL 3. Jan 2010 09:31

Re: Stingumwandlung
 
Nutze mal an Stelle von PChar, was wohl in D10 Unicode ist, PAnsiChar

PS.
Editiere mal den Beitragstitel: Stingumwandlung ;)

Berni68 3. Jan 2010 09:52

Re: Stringumwandlung
 
Wenn ich PAnsiChar verwende (CopyDataStruct.lpData:= PAnsiChar(Nachricht); und h: PAnsiChar;)
kommt nur noch '#' an.

himitsu 3. Jan 2010 10:05

Re: Stringumwandlung
 
Jupp, D7 nutzt Ansi (AnsiString und PAnsiChar) und D2010 Unicode (UnicodeString und PWideChar)



Delphi-Quellcode:
procedure WindowsNachrichtAn(Fensterklasse, Fenstername, Nachricht: WideString);
var
  CopyDataStruct: TCopyDataStruct;
  ReceiverHandle: THandle;
begin
  CopyDataStruct.dwData:= 0;
  CopyDataStruct.cbData:= (Length(Nachricht) + 1) * 2;
  CopyDataStruct.lpData:= PWideChar(Nachricht);



PWideChar(Msg.CopyDataStruct.lpData)
oder
Delphi-Quellcode:
procedure WindowsNachrichtAn(Fensterklasse, Fenstername, Nachricht: AnsiString);
var
  CopyDataStruct: TCopyDataStruct;
  ReceiverHandle: THandle;
begin
  CopyDataStruct.dwData:= 0;
  CopyDataStruct.cbData:= Length(Nachricht) + 1;
  CopyDataStruct.lpData:= PAnsiChar(Nachricht);



PAnsiChar(Msg.CopyDataStruct.lpData)
aus genau diesem Grund nutzt man für programmexternen Datenaustausch und Datenspeicherung nur statische Typen ... kein Integer, Cardinal, String, PChar und wenn Records, dann nur packed.

Berni68 3. Jan 2010 10:55

Re: Stringumwandlung
 
Hallo, erst mal vielen Dank für die Anwort.
Allerdings versteh ich immer weniger:

Mit WideString funktioniert es fast, es kommen allerdings 2 Zeichen zuviel im Showmessagefenster.
Kurioserweise ändert sich nichts, wenn ich (Length(Nachricht) + 1 in (Length(Nachricht) ändere!???

Mit AnsiString funktioniert es fast nicht, es kommt lediglich 1 Zeichen an im Showmessagefenster.

SirThornberry 3. Jan 2010 11:44

Re: Stringumwandlung
 
Diese Zeile hier ist nicht die beste Art:
Delphi-Quellcode:
CopyDataStruct.cbData:= (Length(Nachricht) + 1) * 2;
Wenn man das "*2" fest rein schreibt ist es kein Wunder das man beim Wechsel zwischen Delphiversionen dann wieder Probleme bekommt. Richtiger wäre hier mit sizeof zu arbeiten.
Delphi-Quellcode:
CopyDataStruct.cbData:= (Length(Nachricht) + 1) * sizeof(Nachricht[1]);
Und das "+1" würde ich weg lassen und stattdessen lieber die Länge mit verschicken und diese dann auch beim Auslesen mit beachten.

jbg 3. Jan 2010 12:02

Re: Stringumwandlung
 
Zitat:

sizeof(Nachricht[1])
Hoffen wir mal das Nachricht nicht '' ist, sonst krachts.

Was auch noch zu beachten ist, dass Sender und Empfänger die gleiche String-Sprache sprechen. Denn wenn der Sender Unicode (2 Byte pro Zeichen) und der Empfänger ANSI (1 Byte pro Zeichen) spricht, dann können die beiden sich nicht unterhalten.

SirThornberry 3. Jan 2010 12:06

Re: Stringumwandlung
 
Zitat:

Zitat von jbg
Zitat:

sizeof(Nachricht[1])
Hoffen wir mal das Nachricht nicht '' ist, sonst krachts.

Das sollte nicht so sein. Denn SizeOf wird bereits beim compilieren aufgelöst und nicht erst während der Laufzeit. Man könnte ebenso Nachricht[0] oder Nachricht[5000] nehmen. Ausschlaggebend ist hier einzig und Allein das der Typ zum Zeitpunkt des compilierens fest steht und somit kann die Größe korrekt ermittelt werden.
So kenne ich Beispiele bei denen die Größe eines Record-Members ermittelt werden soll wo keine Instanz des Records vorhanden ist. Dort wird dann einfach nil auf den pointertyp des Records gecastet, dereferenziert und dann die Größe des Members ermittelt. Dies ist gängige Praxis. (Im ersten Moment sieht dies Haarstreubend aus aber es gibt kaum eine bessere Möglichkeit)

thkerkmann 3. Jan 2010 12:47

Re: Stringumwandlung
 
Dann sollte man hier doch den Typen verwenden:

sizeOf(TChar)

und fertig.

himitsu 3. Jan 2010 14:00

Re: Stringumwandlung
 
TChar? Dann sollte man aber auch den Typen nutzen, welcher für die Variable verwendet wurde.


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:23 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