AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

String zu PAnsiChar

Ein Thema von Berni68 · begonnen am 21. Mär 2010 · letzter Beitrag vom 21. Okt 2020
Antwort Antwort
Seite 1 von 2  1 2   
Berni68

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

String zu PAnsiChar

  Alt 21. Mär 2010, 20:05
Hallo, auch auf die Gefahr hin, daß ich langsam nerve,
aber ich hab es noch nicht kapiert,

die folgende einfache Prozedur zeigt mein Problem:

Delphi-Quellcode:
procedure TTestForm.Test2Click(Sender: TObject);
var
  s: TStrings;
  i:integer;
  x: array of PAnsiChar;
begin
  s:= TStringList.Create;
  s.Add('#0#');
  s.Add('#1#');
  s.Add('#2#');

  SetLength(x, 3);

  for i:=0 to 2 do x[i]:= PAnsiChar(AnsiString(s[i]));
  for i:=0 to 2 do showmessage(x[i]); // liefert: #2# #2# #2# WARUM ???????????????????ß

  x[0]:='##0##';
  x[1]:='##1##';
  x[2]:='##2##';
  for i:=0 to 2 do showmessage(x[i]); // -> liefert: ##0## ##1## ##2##

  Finalize(x);
  s.Free;
end;
PAnsiChar(AnsiString(s[i])) war das bisherige Fazit, ist aber offensichtlich nicht richtig oder nicht ausreichend.

Wie bekommt man die Strings von s in das array?
Bernhard
  Mit Zitat antworten Zitat
Benutzerbild von Garfield
Garfield

Registriert seit: 9. Jul 2004
Ort: Aken (Anhalt-Bitterfeld)
1.333 Beiträge
 
Delphi XE5 Professional
 
#2

Re: String zu PAnsiChar

  Alt 21. Mär 2010, 20:13
for i:=0 to 2 do x[i]:= PAnsiChar(AnsiString(s.strings[i])); müsste richtig sein.
Gruss Garfield
W81: Laz1.6/FPC3, D7PE, DXE5Prof - Ubuntu: Laz1.6/FPC3
  Mit Zitat antworten Zitat
Benutzerbild von ghost007
ghost007

Registriert seit: 31. Okt 2005
Ort: München
1.024 Beiträge
 
Delphi 7 Personal
 
#3

Re: String zu PAnsiChar

  Alt 21. Mär 2010, 20:14
Servus, zunächst einmal kann das ja gar nich funktionieren, da ein PAnsiChar auf einen Character zeigt, also nur ein Zeichen.
Hab dein Codeschnipsel mal etwas abgewandelt:

Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var
  s: TStrings;
  i:integer;
  x: array of PAnsiString; //hier
begin
  s:= TStringList.Create;
  s.Add('#0#');
  s.Add('#1#');
  s.Add('#2#');

  SetLength(x, 3);

  for i:=0 to 2 do x[i]:= PAnsiString(s[i]); //hier
  for i:=0 to 2 do showmessage(AnsiString(x[i])); //hier

  Finalize(x);
  s.Free;
end;
Die abgeänderten Stellen sind markiert.
Christian
Es gibt möglich Dinge und unmöglich Dinge.
Für unmögliche braucht man lediglich etwas länger.
  Mit Zitat antworten Zitat
daywalker9

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

Re: String zu PAnsiChar

  Alt 21. Mär 2010, 20:15
So funktioniert es:

x[i]:=StrNew(pAnsiChar(AnsiString(s[i])));
Lars
  Mit Zitat antworten Zitat
Berni68

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

Re: String zu PAnsiChar

  Alt 21. Mär 2010, 20:37
Danke an daywalker9 das ist es!!!
Bernhard
  Mit Zitat antworten Zitat
Berni68

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

Re: String zu PAnsiChar

  Alt 21. Mär 2010, 20:40
Jetzt bleibt nur die Frage:

Reicht da
Finalize(x);
oder muß zuvor noch für jedes
StrDispose[i];
her?
Bernhard
  Mit Zitat antworten Zitat
daywalker9

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

Re: String zu PAnsiChar

  Alt 21. Mär 2010, 20:45
Es reicht eigentlich wenn du für alle Elemente im Array StrDispose() aufrufst.
Lars
  Mit Zitat antworten Zitat
Benutzerbild von Matze
Matze
(Co-Admin)

Registriert seit: 7. Jul 2003
Ort: Schwabenländle
14.987 Beiträge
 
Turbo Delphi für Win32
 
#8

Re: String zu PAnsiChar

  Alt 21. Mär 2010, 20:57
Nun habt ihr mich aber neugierig gemacht:
Was sind denn ##0## bzw. ##1## oder ##2##?

Bisher sind mit nur die ASCII-Zeichen wie #10 (= line feed) etc. bekannt. Die genannte Schreibweise ist mir neu.
  Mit Zitat antworten Zitat
Berni68

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

Re: String zu PAnsiChar

  Alt 21. Mär 2010, 21:18
Das hat garnichts mit Steuerzeichen zu tun, das waren lediglich Beispielstrings.
Der Hintergrung ist die Unit Mapi um eMails mit dem Standard eMail-client zu versenden.
Hat in Delphi2010 nicht mehr funktioniert.

Aber jetzt klappt's wieder; wer's gebrauchen kann:
Delphi-Quellcode:
function SendEMail(Handle:THandle; Mail:TStrings):Cardinal;
var
  MapiMessage: TMapiMessage;
  Receip: TMapiRecipDesc;
  Attachments: array of TMapiFileDesc;
  i, AttachCount: Integer;
  FileName: string;
  MAPI_Session: Cardinal;
  WndList: Pointer;
begin
Result:= MAPI_E_FAILURE;
  if (MapiLogon(Handle, PAnsiChar(''), PAnsiChar(''), MAPI_LOGON_UI or MAPI_NEW_SESSION, 0, @MAPI_Session) <> SUCCESS_SUCCESS)
  then
    MessageBox(Handle, PChar('Error while trying to send email'), PChar('Error'), MB_ICONERROR or MB_OK)
  else
    begin
      if Mail.Values['to']<>'then begin
        Receip.ulReserved:= 0;
        Receip.ulRecipClass:= MAPI_TO;
        Receip.lpszName:= PAnsiChar(AnsiString(Mail.Values['to']));
        Receip.lpszAddress:= PAnsiChar(AnsiString('SMTP:' + Mail.Values['to']));
        Receip.ulEIDSize:= 0;
        MapiMessage.nRecipCount:= 1;
        MapiMessage.lpRecips:= @Receip;
      end;
      if Mail.Values['subject']<>'then MapiMessage.lpszSubject:= PAnsiChar(AnsiString(Mail.Values['subject']));
      if Mail.Values['body']<>'then MapiMessage.lpszNoteText:= PAnsiChar(AnsiString(Mail.Values['body']));

      AttachCount:= 0;
      for i:= 0 to MaxInt do begin
        if Mail.Values['attachment' + IntToStr(i)] = 'then break;
        Inc(AttachCount);
      end;
      SetLength(Attachments, AttachCount);

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

      WndList:= DisableTaskWindows(0);
      try
        Result:= MapiSendMail(MAPI_Session, Handle, MapiMessage, MAPI_DIALOG, 0);
      finally
        EnableTaskWindows(WndList);
        for i:=0 to AttachCount-1 do begin
          StrDispose(Attachments[i].lpszPathName);
          StrDispose(Attachments[i].lpszFileName);
        end;
        Finalize(Attachments);
      end;
      MapiLogOff(MAPI_Session, Handle, 0, 0);
    end;
end;
so zu verwenden:
Delphi-Quellcode:
procedure TTestForm.Mail1Click(Sender: TObject);
var
  mail: TStringList;
begin
  mail:= TStringList.Create;
  try
      mail.values['to']:= 'fifi@abc.de';
      mail.values['subject']:= 'subject';
      mail.values['body']:= 'text text text';
      mail.values['attachment0']:= 'C:\Anhang1.txt';
      mail.values['attachment1']:= 'C:\Anhang2.txt';
      mail.values['attachment2']:= 'C:\Anhang3.txt';
    SendEMail(Self.Handle, mail);
  finally
    mail.Free;
  end;
end;
Allerdings gab' hierzu mehrmals die Bemerkung, daß Mapi bereits fast tot ist.
Ich hab auch bei Indy geschaut, aber so wie ich das dort verstanden hab, geht der eMail versand
dann nicht über das Mailprogramm Thundrbird outlook etc. ist also dort nicht drin, was ich aber will.
Ausserdem dar ganze Anmeldekram
Aber wenn das auch mit Indy geht lass ich mich gerne aufklären.
Bernhard
  Mit Zitat antworten Zitat
delphifan2004

Registriert seit: 26. Nov 2004
Ort: Dresden
206 Beiträge
 
Delphi 10.3 Rio
 
#10

AW: String zu PAnsiChar

  Alt 21. Okt 2020, 14:13
Ich beschäftige mich auch gerade mit solchen Stringumwandlungen und da erhalte ich eine Accessviolation beim Beenden meines Programmes, obwohl der String zunächst korrekt angezeigt wird, an folgender Stelle in der System Unit, wie mir mein Debugger zeigt (Delphi 10.3.3 Community Edition). Kann der Quellcode aus der System Unit hier so stehen bleiben?


Delphi-Quellcode:
procedure _UStrClr(var S);
{$IFDEF CPUX86}
asm
        { ->    EAX     pointer to str  }
        { <-    EAX     pointer to str  }

        MOV EDX,[EAX] { fetch str                     }
        TEST EDX,EDX { if nil, nothing to do         }
        JE @@done
        MOV dword ptr [EAX],0 { clear str                     }
        MOV ECX,[EDX-skew].StrRec.refCnt { fetch refCnt                  } /// Hier knallt es
        DEC ECX { if < 0: literal str           }
        JL @@done
   LOCK DEC [EDX-skew].StrRec.refCnt { threadsafe dec refCount       }
        JNE @@done
Hier mein Quellcode zu verschiedenen Stringkonvertierungen:

Delphi-Quellcode:
program Strconv;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  Windows;

var
  AnsiStr: AnsiString;
  AnsiChr: PAnsiChar;
  WideStr: WideString;
  WideChr: PWideChar;

procedure AnsiStrToWideStr(aStr: AnsiString; var waStr: WideString);
begin
  waStr := aStr;
end;

procedure AnsiStrToPAnsiChr(aStr: AnsiString; var paChr: LPCSTR);
begin
  paChr := PAnsiChar(aStr);
end;

procedure AnsiStrToPWideChar(aStr: AnsiString; var pwChr: LPCWSTR);
var ws: WideString;
begin
  ws := aStr;
  pwChr := LPCWSTR(ws);
end;

procedure PWideCharToWideString(pwChr: LPCWSTR; var ws: WideString); //Diese Prozedur macht die Probleme
var
  wchr: array of WideChar absolute pwChr;
  i: Integer;
  wch: array of WideChar;
begin
  SetLength(wch,StrLen(pwChr));
  move(wchr,ws,StrLen(pwChr));
  ws := WideString(wchr);
end;
{
procedure PWideCharToPAnsiChar(pwChr: LPCWSTR; var a: LPCSTR);
var
  wchr: array of WideChar absolute pwChr;
  ansiStr: AnsiString;
  wideStr: WideString;
begin

  move(wchr,wideStr,StrLen(pwChr));

  //PWideCharToWideString(pwChr,wideStr);

  ansiStr := WideStr;
  a := @ansiStr;


end;
}

procedure PWideCharToAnsiString(pwChr: LPCWSTR; var s: AnsiString);
var wideStr: WideString;
begin
  PWideCharToWideString(pwChr,wideStr);
  s := AnsiString (WideStr);
end;



begin
  try
    { TODO -oUser -cConsole Main : Code hier einfügen }
    AnsiStr := 'Dieser String';
    //AnsiStrToPAnsiChr(AnsiStr,AnsiChr);
    //AnsiStrToWideStr(AnsiStr,WideStr);
    AnsiStrToPWideChar(AnsiStr,WideChr);
    //PWideCharToPAnsiChar(WideChr,AnsiChr);
    //PWideCharToWideString(WideChr,WideStr);
    //PWideCharToPAnsiChar(WideChr,AnsiChr); funktioniert nicht

    PWideCharToAnsiString(WideChr,AnsiStr);

    writeln(AnsiStr); //wird korrekt angezeigt

    readln; //Nach Drücken der Enter Taste zum Beenden meines Programmes kommt die Exceptioen EAccessviolation.
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
Warum wird da diese Exception geworfen, was muss ich da anders machen?



Ist zwar ein uralter Thread, aber dessen Thema passt so gut zu meinem Problem.

.

Geändert von delphifan2004 (21. Okt 2020 um 14:17 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 16:11 Uhr.
Powered by vBulletin® Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2020 by Daniel R. Wolf