Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Typumwandlung string -> PAnsiChar (https://www.delphipraxis.net/149392-typumwandlung-string-pansichar.html)

Berni68 20. Mär 2010 10:52


Typumwandlung string -> PAnsiChar
 
Hallo zusammen,

ich hab mit Unicode noch so meine Probleme:

wenn ich einen String h habe und brauche aber einen PAnsiChar
dann kann man ja PAnsiChar(h) machen.
Der Compiler meldet dann:
[DCC Warnung] Allg_win.pas(162): W1044 Bedenkliche Typumwandlung von string in PAnsiChar
die .exe tut dann auch nicht das was sie soll.

Aber ich krieg es einfach nicht 'unbedenklicher hin'
unter W1044 Bedenkliche Typumwandlung von AnsiString in PWideChar gab es zwar sowas änliches aber schlau werd ich da nicht draus.
Kann mir jemand einen Tip geben?

daywalker9 20. Mär 2010 11:01

Re: Typumwandlung string -> PAnsiChar
 
Das liegt daran, das der normale String unter D2010 ein Multibyte String ist. D.h. wenn du einen String auf pAnsiChar castest, geht das eigentlich immer in die Hose. Ein pAnsiChar ( Zeiger auf ein AnsiString) ist kein Multibyte. Du musst es schon auf pWideChar casten oder Utf8Encode und Utf8Decode benutzten um dein String als AnsiString zu nutzten

Berni68 20. Mär 2010 11:36

Re: Typumwandlung string -> PAnsiChar
 
Hört sich gut an, nützen tut es nichts
Der Compiler gibt nur Fehlermeldungen aus.
Umwandlungsroutinen gibt es zuhauf, eventuell mehr als nötig, aber auch
mit 'try by error' Probiermethode find ich keine Lösung.
(Utf8Encode und Utf8Decode liefert auch nur Fehler)

Wäre ein Beispiel möglich?

Es handelt sich um die Unit Mapi
in Delphi 5 hat einwandfrei funktioniert:

Delphi-Quellcode:
Receip.lpszName:= StrNew(Mail.Values['to']);
wobei Mail: mail: TStringList;
und Receip: TMapiRecipDesc; (unit mapi)

in Delphi 10 geht diese Zeile nicht mehr,
es wird ein PAnsiChar erwartet.

WIE GEHT DAS

SirThornberry 20. Mär 2010 11:49

Re: Typumwandlung string -> PAnsiChar
 
Der Fehler liegt, wie bereits angedeutet, in deinem Verständnis. Ein String war in alten Delphiversionen ein Array von Chars mit einigen Zusatzinformationen. In neuen Delphiversionen ist ein String aber kein Array von Chars mehr.
Ein PAnsiChar ist wiederum nur ein Pointer welcher auf einen Char zeigt. Wenn dein String jetzt aber nicht mehr aus Chars besteht kannst du natürlich den Pointer auch nicht mehr auf Chars zeigen lassen. Entsprechend ist das völlig inkompatibel.
Du müsstest also entweder etwas anderes Anstelle des Strings verwenden (was intern ein Array von Chars ist) oder du musst einen anderen Pointertypen verwenden der nicht auf Chars zeigt sondern so typisiert ist, dass er mit dem Zeichen eines neuen Strings kompatibel ist.

Berni68 20. Mär 2010 12:09

Re: Typumwandlung string -> PAnsiChar
 
Also dann probier ich es nochmal anderherum:

es gab mal eine Prozedur (stammt nicht von mir):
Delphi-Quellcode:
// uses MAPI
function SendEMail(Handle:THandle; Mail:TStrings):Cardinal;
type
  TAttachAccessArray= array [0..0] of TMapiFileDesc;
  PAttachAccessArray= ^TAttachAccessArray;
var
  MapiMessage: TMapiMessage;
  Receip: TMapiRecipDesc;
  Attachments: PAttachAccessArray;
  AttachCount: Integer;
  i1: integer;
  FileName: string;
  dwRet: Cardinal;
  MAPI_Session: Cardinal;
  WndList: Pointer;
begin
Result:= MAPI_E_FAILURE;
  dwRet:= MapiLogon(Handle, PAnsiChar(''), PAnsiChar(''), MAPI_LOGON_UI or MAPI_NEW_SESSION, 0, @MAPI_Session);

  if (dwRet<>SUCCESS_SUCCESS) then
    begin
      MessageBox(Handle, PChar('Error while trying to send email'), PChar('Error'), MB_ICONERROR or MB_OK);
    end
  else
    begin
      FillChar(MapiMessage, SizeOf(MapiMessage), #0);
      Attachments:= nil;
      FillChar(Receip, SizeOf(Receip), #0);

      if Mail.Values['to']<>'' then begin
        Receip.ulReserved:= 0;
        Receip.ulRecipClass:= MAPI_TO;
        Receip.lpszName:= StrNew(Mail.Values['to']);
        Receip.lpszAddress:= StrNew('SMTP:' + Mail.Values['to']);

        Receip.ulEIDSize:= 0;
        MapiMessage.nRecipCount:= 1;
        MapiMessage.lpRecips:= @Receip;
      end;

      AttachCount:=0;
 
      for i1:=0 to MaxInt do begin
        if Mail.Values['attachment' + IntToStr(i1)] = '' then break;
        Inc(AttachCount);
      end;
 
      if AttachCount>0 then begin
        GetMem(Attachments, SizeOf(TMapiFileDesc) * AttachCount);

        for i1:=0 to AttachCount-1 do begin
          FileName:= Mail.Values['attachment' + IntToStr(i1)];
          Attachments[i1].ulReserved:= 0;
          Attachments[i1].flFlags:= 0;
          Attachments[i1].nPosition:= ULONG($FFFFFFFF);
          Attachments[i1].lpszPathName:= StrNew(FileName);
          Attachments[i1].lpszFileName:= StrNew(ExtractFileName(FileName));
          Attachments[i1].lpFileType:= nil;
        end;
        MapiMessage.nFileCount := AttachCount;
        MapiMessage.lpFiles := @Attachments^;
      end;

      if Mail.Values['subject']<>'' then MapiMessage.lpszSubject:= StrNew(Mail.Values['subject']);
      if Mail.Values['body']<>'' then MapiMessage.lpszNoteText:= StrNew(Mail.Values['body']);

      WndList := DisableTaskWindows(0);
      try
        Result:= MapiSendMail(MAPI_Session, Handle, MapiMessage, MAPI_DIALOG, 0);
      finally
        EnableTaskWindows(WndList);
      end;

      for i1:=0 to AttachCount-1 do begin
        StrDispose(Attachments[i1].lpszPathName);
        StrDispose(Attachments[i1].lpszFileName);
      end;

      if Assigned(MapiMessage.lpszSubject) then StrDispose(MapiMessage.lpszSubject);
      if Assigned(MapiMessage.lpszNoteText) then StrDispose(MapiMessage.lpszNoteText);
      if Assigned(Receip.lpszAddress) then StrDispose(Receip.lpszAddress);
      if Assigned(Receip.lpszName) then StrDispose(Receip.lpszName);
      MapiLogOff(MAPI_Session, Handle, 0, 0);
    end;
end;
die man problemlos so nutzen konnte:
Delphi-Quellcode:
procedure TTestForm.Mail1Click(Sender: TObject);
var
  mail: TStringList;
begin
  mail:= TStringList.Create;
  try
      mail.values['to']:= 'fifi@xyz.de';
      mail.values['subject']:= 'test';
      mail.values['body']:= 'Text Text Text';
      mail.values['attachment0']:= 'C:\Anhang.txt';
    SendEMail(Self.Handle, mail);
  finally
    mail.Free;
  end;
end;
Das geht jetzt offensichtlich nicht mehr. PAnsiChar hin oder her ist mir eigentlich völlig egal.
Gibt es eine alternative Möglichkeit eine Mail zu versenden ohne die geheimnisvollen Konvertierungen von PAnsiChar offenbaren zu müssen?

sx2008 20. Mär 2010 12:33

Re: Typumwandlung string -> PAnsiChar
 
Ist doch eigentlich ganz einfach; man braucht einen AnsiString als Zwischenspeicher:
Delphi-Quellcode:
var
  to_addr : AnsiString;
begin
  ...
  to_addr := Mail.Values['to']; // UnicodeString auf AnsiString kopieren
  Receip.lpszName:= PAnsiChar(to_addr);

Berni68 20. Mär 2010 13:00

Re: Typumwandlung string -> PAnsiChar
 
Super, DANKE!!!

Jetzt hab ich auch kapiert was eingangs gemeint war. Manchmal braucht's einfach was anschauliches.

MiKaEr 7. Mär 2012 12:56

AW: Typumwandlung string -> PAnsiChar
 
ich versuche gerade mit folgender funktion eine destkopverknüpfung zu speichern. jedoch geht meine pfadangabe bis auf ein simpes "C" komplett verloren.
wie erreiche ich es, dass die verknüpfung erstellt wird und der pfad erhlten bleibt?

Delphi-Quellcode:
function TGenFunctions.createLink(const AFileName, AParameter: string): Boolean;
var
 psl: IShellLink;
 ppf: IPersistFile;
 wsz: PWideChar;
begin
 Result := False;

 if SUCCEEDED(CoCreateInstance(CLSID_ShellLink, nil, CLSCTX_inPROC_SERVER, IID_IShellLinkA, psl)) then
  begin
   psl.SetPath(PWideChar(AFileName));
   psl.SetArguments(PChar(AParameter));
   psl.SetWorkingDirectory(PChar(ExtractFilePath(AFileName)));

   if SUCCEEDED(psl.QueryInterface(IPersistFile, ppf)) then
    begin
     GetMem(wsz, max_path * 2);
     try
      MultiByteToWideChar(CP_ACP, 0, 'C:\Users\testaccount\Desktop\test.lnk'), -1, wsz, max_path); // hier tritt der fehler auf und der hinweis "bedenkliche umwandlung"
      ppf.Save(wsz, True);
      Result := True;
     finally
      FreeMem(wsz, max_path * 2);
     end;
    end;
  end;
end;

RWarnecke 7. Mär 2012 13:03

AW: Typumwandlung string -> PAnsiChar
 
In diesem Beispiel wird gezeigt, wie eine Verknüpfung erstellt werden kann.

Probiere es mal so :
Delphi-Quellcode:
MultiByteToWideChar(CP_ACP, 0, 'C:\Users\testaccount\Desktop\test.lnk', -1, wsz, max_path);

himitsu 7. Mär 2012 13:26

AW: Typumwandlung string -> PAnsiChar
 
Zitat:

Zitat von Berni68 (Beitrag 1008321)
es zwar sowas änliches aber schlau werd ich da nicht draus.

Wenn die Daten nur im Unicodeformat vorliegen, dann kann man davon keinen Zeiger auf Ansi-Daten rausbekommen.

Delphi gibt dir hier zwar einen Zeiger darauf, aber warnnt dich, daß die Daten im "falschen" Format vorliegen.

Also entweder vorher in eine Stringvariable vom richtigen Typen umkopieren, oder

Delphi-Quellcode:
var
  s: UnicodeString;
  P: PAnsiChar;

p := PAnsiChar(AnsiString(s));
Delphi-Quellcode:
AnsiString(s)
ist kein reiner Type-Cast, denn die Compilermgic legt hier eine temporäre AnsiString-Variable an, welche meistens bis zum Ende der Prozedur erhalten bleibt.
Und PAnsiChar zeigt dann in Wirklichkeit auf diese temporäre Varible, welche eine umgewandelte Kopie von S enthält.


Kommt nun darauf an, wie langlebig dieser Pointer sein muß.
Wenn es nur als direkter Parameter für einen einzigen Funktionsaufruf sein soll, dann gibt es absolut keine Probleme, aber wenn man sich z.B. an einer Stelle den Pointer besort und erst mehrere Codezeilen weiter unten diesen Pointer verwendet, dann wäre es sicherer, wenn man sich eine eigene AnsiString-Variable anlegt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:24 Uhr.
Seite 1 von 2  1 2      

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