AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Typumwandlung string -> PAnsiChar

Ein Thema von Berni68 · begonnen am 20. Mär 2010 · letzter Beitrag vom 7. Mär 2012
Antwort Antwort
Seite 1 von 2  1 2      
Berni68

Registriert seit: 9. Jan 2006
Ort: Villingen
162 Beiträge
 
Delphi XE5 Professional
 
#1

Typumwandlung string -> PAnsiChar

  Alt 20. Mär 2010, 11:52
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?
Bernhard
  Mit Zitat antworten Zitat
daywalker9

Registriert seit: 1. Jan 2010
Ort: Leer
594 Beiträge
 
Delphi XE3 Professional
 
#2

Re: Typumwandlung string -> PAnsiChar

  Alt 20. Mär 2010, 12:01
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
Lars
  Mit Zitat antworten Zitat
Berni68

Registriert seit: 9. Jan 2006
Ort: Villingen
162 Beiträge
 
Delphi XE5 Professional
 
#3

Re: Typumwandlung string -> PAnsiChar

  Alt 20. Mär 2010, 12:36
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:

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
Bernhard
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#4

Re: Typumwandlung string -> PAnsiChar

  Alt 20. Mär 2010, 12:49
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.
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
Berni68

Registriert seit: 9. Jan 2006
Ort: Villingen
162 Beiträge
 
Delphi XE5 Professional
 
#5

Re: Typumwandlung string -> PAnsiChar

  Alt 20. Mär 2010, 13:09
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?
Bernhard
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 16. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#6

Re: Typumwandlung string -> PAnsiChar

  Alt 20. Mär 2010, 13:33
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);
  Mit Zitat antworten Zitat
Berni68

Registriert seit: 9. Jan 2006
Ort: Villingen
162 Beiträge
 
Delphi XE5 Professional
 
#7

Re: Typumwandlung string -> PAnsiChar

  Alt 20. Mär 2010, 14:00
Super, DANKE!!!

Jetzt hab ich auch kapiert was eingangs gemeint war. Manchmal braucht's einfach was anschauliches.
Bernhard
  Mit Zitat antworten Zitat
MiKaEr
(Gast)

n/a Beiträge
 
#8

AW: Typumwandlung string -> PAnsiChar

  Alt 7. Mär 2012, 13:56
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;
  Mit Zitat antworten Zitat
Benutzerbild von RWarnecke
RWarnecke

Registriert seit: 31. Dez 2004
Ort: Stuttgart
4.408 Beiträge
 
Delphi XE8 Enterprise
 
#9

AW: Typumwandlung string -> PAnsiChar

  Alt 7. Mär 2012, 14:03
In diesem Beispiel wird gezeigt, wie eine Verknüpfung erstellt werden kann.

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

Geändert von RWarnecke ( 7. Mär 2012 um 14:13 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#10

AW: Typumwandlung string -> PAnsiChar

  Alt 7. Mär 2012, 14:26
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));
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.
$2B or not $2B
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:07 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