AGB  ·  Datenschutz  ·  Impressum  







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

Frage zu MessageDlg

Ein Thema von BTeam · begonnen am 24. Jul 2005 · letzter Beitrag vom 3. Aug 2005
Antwort Antwort
Seite 2 von 3     12 3      
Benutzerbild von BlackJack
BlackJack

Registriert seit: 2. Jul 2005
Ort: Coesfeld
246 Beiträge
 
Delphi 2005 Personal
 
#11

Re: Frage zu MessageDlg

  Alt 3. Aug 2005, 01:34
Zitat von Killer:
hab grad auch noch was zu dem Thema. Entweder suche ich falsch oder ich bin zu blöd dafür. Wenn ich nach "mymessagedlg" suche, find ich nur diesen Thread. Hab als Alternative MessageBox probiert, ein Problem von mir is nun folgendes:
Code:
if MessageBox(self.Handle, 'Soll der User ' + PChar(GetSelectedUser.User) + ' wirklich gelöscht werden?','Titel',MB_ICONQUESTION or MB_YESNO) = IDYES then
    // TODO: User löschen
GetSelectedUser.User ist natürlich vom Typ String. Mit MessageDlg geht das ja auch, nur MessageBox erwartet da PAnsiChar...

Lässt sich aus folgendem Grund nicht kompilieren:
Zitat:
[Error] Unit1.pas(243): Incompatible types: 'String' and 'PAnsiChar'
Es liegt an diesem Teil:
Code:
PChar(GetSelectedUser.User)
wenn ich das entferne, gehts soweit. Nur ich möchte es trotzdem drin haben. Sollte mit PChar() ja worken normal
ich würde sagen du musst einfach den PChar-typecast um den gesamten string machen und nicht nur um diesen User-record, also so:
MessageBox(self.Handle, PChar('Soll der User ' + GetSelectedUser.User + ' wirklich gelöscht werden?'),'Titel',MB_ICONQUESTION or MB_YESNO) man kann nicht PChars und strings einfach so mit einem + aneinanderreihen, da es nunmal verschiedene typen sind (im grunde sind PChars nur pointer, allerdings benutzt Delphi da ein bisschen CompilerMagic)

(eventuell muss noch "Titel" auf PChar getypecastet werden, ich weiss jetzt nicht was da für ein parameter erwartet wird und ob delphi gegebenenfalls automatisch typecastet.)

edit:
ich hab mal nachgeschaut, bei meinem Delphi erwartet die Function MessageBox eh keine PChars, sondern direkt strings als parameter, von daher kannst du einfach komplett mit strings arbeiten und dir den typecast auf PChar sparen.

edit2:
Zitat von dahead:
@('Soll der User ' + PChar('Test') + ' wirklich gelöscht werden?')[1] ...
krass, so eine syntax ist mir noch nie untergekommen und ich hätte auch nie erwartet dass das funktioniert (vor allem weil auch strings und PChars gemischt werden)... naja man lehrnt nie aus.
ach ja, wo im speicher steht dann überhaupt dieser string?
See my shadow changing, stretching up and over me.
Soften this old armor. Hoping I can clear the way
By stepping through my shadow, coming out the other side.
Step into the shadow. Forty six and two are just ahead of me.
  Mit Zitat antworten Zitat
Benutzerbild von dahead
dahead

Registriert seit: 16. Mai 2005
620 Beiträge
 
#12

Re: Frage zu MessageDlg

  Alt 3. Aug 2005, 02:06
@blackjack:

Zitat:
krass, so eine syntax ist mir noch nie untergekommen und ich hätte auch nie erwartet dass das funktioniert (vor allem weil auch strings und PChars gemischt werden)... naja man lehrnt nie aus.
nicht dass du denkst ich würde das selbst so lösen. ich wollte nur schnell testen, ob das problem in oder außerhalb der klammer liegt. daher mein vorschlag mit @...[1].

da ich immer noch nicht weiß, welchen typ die besagte variable hat, hab ich sie einfach durch 'test' ersetzt.

edit: ich muss allerdings zu meiner schande gestehen, dass ich das projekt nicht gestartet habe, also nicht weiß wie die message dann dadurch evtl. zerstückelt wurde.

da du schreibst es funktioniert, wird der string korrekt angezeigt?
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#13

Re: Frage zu MessageDlg

  Alt 3. Aug 2005, 02:40
Zitat von dahead:
Code:
[b]@[/b]('Soll der User ' + PChar('Test') + ' wirklich gelöscht werden?')[b][1][/b] ...

Wie wäre es mit:
Delphi-Quellcode:
var
  sUser: String;
begin
...
PChar('Soll der User ' + sUser + ' wirklich gelöscht werden?')
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Olli
(Gast)

n/a Beiträge
 
#14

Re: Frage zu MessageDlg

  Alt 3. Aug 2005, 10:55
Zitat von dahead:
Code:
[b]@[/b]('Soll der User ' + PChar('Test') + ' wirklich gelöscht werden?')[b][1][/b] ...
Bitte den PChar-Cast weglassen! -> Nein, den braucht's bei dieser Syntax, wenn der String mehr als ein terminierendes #0 enthält!

Zitat von Luckie:
PChar('Soll der User ' + sUser + ' wirklich gelöscht werden?')
Auch du, Luckie?

tss tss tss ....
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#15

Re: Frage zu MessageDlg

  Alt 3. Aug 2005, 11:03
Und wie dann? Siehe Anhang.
Miniaturansicht angehängter Grafiken
msg_140.png  
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Olli
(Gast)

n/a Beiträge
 
#16

Re: Frage zu MessageDlg

  Alt 3. Aug 2005, 13:03
Zitat von Luckie:
Und wie dann?
So wie dahead es vormacht.

Der Punkt ist folgender. Die Syntax mit dem PChar-Cast mag funktionieren (tut sie ja bekanntlich auch), sie mag sogar schneller sein (zumindest kann sie das unter bestimmten Umständen), aber @String[1] ist eine viel klarere Syntax.
Hier wird mit Compiler-Magic gespielt, ohne daß die meisten Leute wissen, was unter ihren Füßen vorgeht! Obwohl unnötig, entscheidet der Compiler über weitere Checks. Wie wir wissen, besitzen Strings einen Referenz- und einen Längenzähler.
Delphi-Quellcode:
type
      StrRec = record
        allocSiz: Longint;
        refCnt: Longint;
        length: Longint;
      end;
Da soviel am AnsiString und WideString und String "managed" abläuft, kann man fast sagen, daß es sich verhält wie bei einer Klasse in C++. Dort kann man Operatoren auch überladen. In Delphi geht dies nicht, also hat der Compiler eine explizite Unterstützung für Strings eingebaut. Die kann man ihm nehmen, indem man die System-Unit mal ein wenig ausmistet - aber das gehört hier nicht her.

Delphis Strings sind immer nullterminiert, sie sind also schonmal prinzipiell kompatibel mit PAnsiChar/PWideChar. Außerdem ist im Binärcode immer der Zeiger auf den Stringpuffer das Element, auf welches verwiesen wird. Die Offsets des o.g. Records werden also über negative Werte erreicht. Eigentlich ist also ein String in Delphi der Record von oben plus Zeiger auf den Puffer.

Und weil es so schön ist, habe ich mal folgende zwei Codeschnipsel in Delphi und im Disassembler verglichen:
Code:
var
  StringVar: string;
  dwSize: DWORD;
begin
  dwSize := MAX_PATH;
  SetLength(StringVar, MAX_PATH + 1);
  GetComputerName([color=red]@StringVar[1][/color], dwSize);
  Writeln(StringVar);
  Readln;
end.
Code:
var
  StringVar: string;
  dwSize: DWORD;
begin
  dwSize := MAX_PATH;
  SetLength(StringVar, MAX_PATH + 1);
  GetComputerName([color=red]PChar(StringVar)[/color], dwSize);
  Writeln(StringVar);
  Readln;
end.
Wie man im folgenden Code sieht, wird für jeden Typecast eine Funktion reingepappt. Wenn man sich die Funktionen anschaut, ist sogar die vom PChar-Cast (oft) schneller.
Code:
CODE:00408312                 mov    ds:dwSize, 260
CODE:0040831C                mov    eax, offset StringVar
CODE:00408321                 mov    edx, 261
CODE:00408326                 call   SetLength
CODE:0040832B                push   offset dwSize
CODE:00408330                 mov    eax, offset StringVar
[color=red]CODE:00408335                 call   @System@UniqueString$qqrr17System@AnsiString[/color]
CODE:0040833A                push   eax
CODE:0040833B                call   GetComputerNameA
CODE:00408340                 mov    eax, ds:ExceptionHandler
CODE:00408345                 mov    edx, ds:StringVar
CODE:0040834B                call   sub_4034A0
CODE:00408350                 call   _WRITELN
Code:
CODE:004082DE                mov    ds:dwSize, 260
CODE:004082E8                 mov    eax, offset StringVar
CODE:004082ED                mov    edx, 261
CODE:004082F2                 call   SetLength
CODE:004082F7                 push   offset dwSize
CODE:004082FC                mov    eax, ds:StringVar
[color=red]CODE:00408301                 call   @System@@LStrToPChar$qqrv[/color]
CODE:00408306                 push   eax
CODE:00408307                 call   GetComputerNameA
CODE:0040830C                mov    eax, ds:off_4092DC
CODE:00408311                 mov    edx, ds:StringVar
CODE:00408317                 call   sub_40346C
CODE:0040831C                call   _WRITELN
Was mich denn dann doch verwunderte, war daß auch bei der @String[1]-Syntax überhaupt eine extra Funktion aufgerufen wird. Diese wird benutzt um dem String, so er denn auf den Puffer eines anderen zugewiesenen Strings zeigt, eine eigene Kopie des eigentlichen Strings (i.e. Inhalt) zu verschaffen. Man muß sich also dazu klarmachen, daß ein String auch auf den Puffer eines ursprünglich anderen Strings zeigen kann. Bei einer Zuweisung wird dann der Zeiger zugewiesen, aber nicht der Puffer selbst kopiert. Das macht die Delphistrings natürlich äußerst effizient. Aber in unserem Fall verschafft es der klareren Syntax einen kleinen Nachteil, weil nämlich dieser Check erst dazwischengeschoben wird. Dieser Check wird offenbar forciert, wenn ich keinen Cast mache, sondern einen Pointer auf meinen String übergebe.

Fazit: Ich bleibe bei meiner klareren Syntax. Ihr dürft weiter PChar-Casts benutzen ... und dank obiger Erkenntnis sage ich auch nix böses mehr darüber ...

BTW: Vielleicht solltet ihr diesen Beitrag in die Codelib oder so schieben? Also splitten.
  Mit Zitat antworten Zitat
Killer

Registriert seit: 11. Nov 2003
152 Beiträge
 
Delphi 6 Enterprise
 
#17

Re: Frage zu MessageDlg

  Alt 3. Aug 2005, 13:31
Hy

Also funktionieren tun ja beide Varianten, über den PChar Cast und über dieses @(String)[1].
Nur komisch, warum die Funktion MessageBox da ein PAnsiChar erwartet und nicht etwa einen String.

Danke für eure Hilfe!!

Übrigens guter Vergleich Olli!
  Mit Zitat antworten Zitat
Benutzerbild von dahead
dahead

Registriert seit: 16. Mai 2005
620 Beiträge
 
#18

Re: Frage zu MessageDlg

  Alt 3. Aug 2005, 13:49
@olli: ja, wirklich interessanter vergleich. danke dass du dir solche mühe gemacht hast.

@killer:

Zitat:
Nur komisch, warum die Funktion MessageBox da ein PAnsiChar erwartet und nicht etwa einen String.
messagebox ist ein api befehl. die erwarten immer pchars oder pansichars.

auszug aus windows.pas
Delphi-Quellcode:
function MessageBox; external user32 name 'MessageBoxA';
function MessageBoxA; external user32 name 'MessageBoxA';
function MessageBoxW; external user32 name 'MessageBoxW';
auszug aus delphi hilfe:
Zitat:
public function MessageBox(const Text: PAnsiChar, const Caption: PAnsiChar, Flags: Integer): Integer;
d.h. du musst keine funktion schreiben. deine funktionen sind PChar sowie @String[1].
(edit: ich sehe gerade, du hast deinen beitrag editiert und diesen wunsch zurückgenommen).

man möge mich korrigieren falls ich falsch liege.
  Mit Zitat antworten Zitat
Benutzerbild von Motzi
Motzi

Registriert seit: 6. Aug 2002
Ort: Wien
598 Beiträge
 
Delphi XE2 Professional
 
#19

Re: Frage zu MessageDlg

  Alt 3. Aug 2005, 14:10
@Olli: ich weiß, dass du weißt, dass ich ein String-Tutorial geschrieben hab (du hast ja schon öfters darauf verwiesen), aber hast du auch selbst schonmal reingeguckt? Das was du da oben geschrieben hast steht nämlich eigentlich schon alles drinnen..

@rest: wen es interessiert, das Tutorial findet man auf www.manuel-poeter.de

PS: es gibt noch eine weitere Möglichkeit, man castet den String einfach auf Pointer, dann wird gar keine Zwischenfunktion aufgerufen..
Manuel Pöter
  Mit Zitat antworten Zitat
Olli
(Gast)

n/a Beiträge
 
#20

Re: Frage zu MessageDlg

  Alt 3. Aug 2005, 15:03
Zitat von Motzi:
@Olli: ich weiß, dass du weißt, dass ich ein String-Tutorial geschrieben hab (du hast ja schon öfters darauf verwiesen), aber hast du auch selbst schonmal reingeguckt? Das was du da oben geschrieben hast steht nämlich eigentlich schon alles drinnen..
Nun gut, du weißt ich bin Pedant. Aber du hast recht, es ist ja schon enthalten.

Übrigens wäre das wohl richtiger
Delphi-Quellcode:
type
  PStringInfo = ^TStringInfo;
  TStringInfo = packed record
    Rec : StrRec;
    pStringAddr : Pointer;
  end;
Die Rolle des ersten Elementes von StrRec scheint mir durchaus relevant, wenn wir zB Zuweisungen betrachten.

Im Tut steht ja ganz am Ende:
Womit auch klar sein sollte, mit welcher Typecast-Methode man einen String an eine API Funktion (die Daten in diesen String schreibt) übergeben sollte, wenn man sich nicht sicher ist, dass dieser String ein „Unikat“ (mit einem Referenzzähler von 1) ist.
Darf man fragen, welche Methode dies denn nach Ansicht des großen Meisters ist?!
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


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 00:55 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