![]() |
Frage zu MessageDlg
Hi,
Ich habe da eine kleine Frage... In MessageDlg kann man ja mittels [mbYes, mbNo,...] usw. festlegen welche Buttons angezeigt werden. Meine Frage ist nun wenn mein Programm das mit einer deutschen Delphi geschrieben wurde auf einen Englischen Windows ausgeführt wird...werden dann die Button Caption auch in englisch statt in deutsch angezeigt? |
Re: Frage zu MessageDlg
nein, sie bleiben deutsch. genauso umgekehrt.
du kannst aber hier im forum mal nach "mymessagedlg" suchen. diese funktion formatiert den button text. |
Re: Frage zu MessageDlg
Leider nein. Die Captions erscheinen in der Sprache deiner Delphi-Version, weil Delphi Konstanten dafür benutzt. Immerhin sind es resourcestrings, sie können also in der Exe mit einem Ressourceneditor bearbeitet werden. Aber dass sich die Beschriftung automatisch der Sprache des Betriebssystems anpasst, schafft man so nicht.
|
Re: Frage zu MessageDlg
Oha...danke für die Antwort.
Dann werde ich mir diese mymessagedlg Function mal ansehen oder zur Not bastel ich mir halt einen eigenen MsgDlg. |
Re: Frage zu MessageDlg
Oder du probierst mal
![]() |
Re: Frage zu MessageDlg
Auch interessant...werde mir einfach mal beides ansehen.
Wobei MyMessageDlg schon prima Funktioniert. Da ich ja keine "Neuen" Buttons reinmachen, sondern nur die Vorhandenen entsprechend der gewählten Sprache anpassen will. Das Funktioniert recht gut mit MyMessageDlg. |
Re: Frage zu MessageDlg
Hy
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:
GetSelectedUser.User ist natürlich vom Typ String. Mit MessageDlg geht das ja auch, nur MessageBox erwartet da PAnsiChar...
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 Lässt sich aus folgendem Grund nicht kompilieren: Zitat:
Code:
wenn ich das entferne, gehts soweit. Nur ich möchte es trotzdem drin haben. Sollte mit PChar() ja worken normal :roll:
PChar(GetSelectedUser.User)
|
Re: Frage zu MessageDlg
also ich poste mal das, was ich dachte bei diesem thread stand. hier der daraus entstandene code:
Delphi-Quellcode:
function MyMessageDlg(const Msg: String; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; Captions: Array of String): Integer; var aMsgDlg: TForm; I: Integer; DlgButton: TButton; CaptionIndex: Integer; begin aMsgDlg := CreateMessageDialog(Msg, DlgType, Buttons); CaptionIndex := 0; for I := 0 to aMsgDlg.ComponentCount - 1 do begin if (aMsgDlg.Components[i] is TButton) then begin DlgButton := TButton(aMsgDlg.Components[I]); if CaptionIndex > High(Captions) then Break; // Keine weiteren Buttons da DlgButton.Caption := Captions[CaptionIndex]; //<- ändern // Todo: MyMessageDlg: Problem bei zu langen Captions wird die // Buttonbreite nicht geändert. //DlgButton.Width := //DlgButton.Left := Inc(CaptionIndex); end; end; Result := aMsgDlg.ShowModal; end; |
Re: Frage zu MessageDlg
MyMessageDlg ist eine Funktion...weis leider auch nicht mehr genau wo ich sie dann gefunden habe darum poste ich sie einfach mal mit rein.
Die dlg_xxx Variablen enthalten hier in meinem Fall einen String in der entsprechenden Sprache. Das Prinzip der Funktion sollte aber klar sein.
Delphi-Quellcode:
function MyMessageDlg(const Msg: String; AType: TMsgDlgType; AButtons:TMsgDlgButtons; HelpCtx: Longint): Word;
var Comp: TComponent; k: Integer; begin with CreateMessageDialog(Msg, AType, AButtons) do begin for k := 0 to ComponentCount - 1 do begin Comp := Components[k]; if Comp is TButton then with TButton(Comp) do begin if UpperCase(Name) = 'YES' then Caption := dlg_yes; if UpperCase(Name) = 'NO' then Caption := dlg_no; if UpperCase(Name) = 'OK' then Caption := dlg_ok; if UpperCase(Name) = 'CANCEL' then Caption := dlg_cancel; end; end; Result := ShowModal; end; end; {Popov} |
Re: Frage zu MessageDlg
so sollte es mit deinem code gehen:
delphi-code: @('Soll der User ' + PChar('Test') + ' wirklich gelöscht werden?')[1] ... also einfach ein @ vor den string, sowie ein [1] danach. (habe 'test' eingefügt, da ich mit deiner variablen nichts anfangen konnte). ps: gehen delphi tags sowie bold-tags egtl. nicht gleichzeitg? |
Re: Frage zu MessageDlg
Zitat:
Delphi-Quellcode:
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)
MessageBox(self.Handle, PChar('Soll der User ' + GetSelectedUser.User + ' wirklich gelöscht werden?'),'Titel',MB_ICONQUESTION or MB_YESNO)
(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:
ach ja, wo im speicher steht dann überhaupt dieser string? |
Re: Frage zu MessageDlg
@blackjack:
Zitat:
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? |
Re: Frage zu MessageDlg
Zitat:
Wie wäre es mit:
Delphi-Quellcode:
var
sUser: String; begin ... PChar('Soll der User ' + sUser + ' wirklich gelöscht werden?') |
Re: Frage zu MessageDlg
Zitat:
Zitat:
tss tss tss .... |
Re: Frage zu MessageDlg
Liste der Anhänge anzeigen (Anzahl: 1)
Und wie dann? Siehe Anhang.
|
Re: Frage zu MessageDlg
Zitat:
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:
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.
type
StrRec = record allocSiz: Longint; refCnt: Longint; length: Longint; end; 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:
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.
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.
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:
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.
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 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. |
Re: Frage zu MessageDlg
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!! :-D Übrigens guter Vergleich Olli! :) |
Re: Frage zu MessageDlg
@olli: ja, wirklich interessanter vergleich. danke dass du dir solche mühe gemacht hast.
@killer: Zitat:
auszug aus windows.pas
Delphi-Quellcode:
auszug aus delphi hilfe:
function MessageBox; external user32 name 'MessageBoxA';
function MessageBoxA; external user32 name 'MessageBoxA'; function MessageBoxW; external user32 name 'MessageBoxW'; Zitat:
(edit: ich sehe gerade, du hast deinen beitrag editiert und diesen wunsch zurückgenommen). man möge mich korrigieren falls ich falsch liege. |
Re: Frage zu MessageDlg
@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 ![]() PS: es gibt noch eine weitere Möglichkeit, man castet den String einfach auf Pointer, dann wird gar keine Zwischenfunktion aufgerufen.. ;) |
Re: Frage zu MessageDlg
Zitat:
Übrigens wäre das wohl richtiger ;)
Delphi-Quellcode:
Die Rolle des ersten Elementes von StrRec scheint mir durchaus relevant, wenn wir zB Zuweisungen betrachten.
type
PStringInfo = ^TStringInfo; TStringInfo = packed record Rec : StrRec; pStringAddr : Pointer; end; 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. |
Re: Frage zu MessageDlg
Zitat:
Zitat:
Zitat:
Gruß, Motzi |
Re: Frage zu MessageDlg
Zitat:
Zitat:
|
Re: Frage zu MessageDlg
Zitat:
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:10 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz