![]() |
[Artikel] Den ExitCode eines Dialogfensters nutzen
Beim Refactoring des Usermanagers bin ich auf ein Problem gestossen, was ich bisher eher unbefriedigend gelöst habe. Dies mal aber habe ich, eine für mich, befriedigende Lösung gefunden, wie ich denke. In diesen Artikel geht es um das Problem und wie ich es dann gelöst habe.
Artikel: ![]() |
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Also ich hatte mir och 'ne variable in der Unit mit dem Dialog erstellt (innerhalb der DialogKlasse) ... nur daß ich dann direkt auf diese Variable Zugriff.
Da man die DialogUnit eh da einbeinden muß, wo man den Dialog aufrufen will, hat man natürlich auch Zugriff auf die darin daklarierte Variable :stupid: |
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Ginge natürlich auch. Aber somit greifst du auf eine globale Variable zu. Hier ist ja nur die Struktur global. Und ich müsste mal ausprobieren, ob es nicht reicht EndDialog aufzurufen, um den Dialig zu beenden oder ob man unbedingt über WM_CLOSE gehen muss. Reicht EndDialog aus, kann man die Variable sogar lokal un der Fensterprozedur deklarieren.
|
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Also ich war der Meinung es sei Lokal, da die Variable nur innerhalb der aufrufenden Prozedur definiert ist. :gruebel:
Außerdem bräuchte man dann keinen zusätzlichen Record, da alles ja direkt in der Klassendefinition enthalten wäre ^^
Delphi-Quellcode:
Var Dialog: TDialog;
Begin Dialog := TDialog.Create; Try If Dialog.Execute Then Begin ... Dialog.MeineVariable ... End; Finally Dialog.Free; End; End; |
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Ja, aber wenn du sie lokal deklarierst und sendest dann WM_CLOSE mit SendMessage, springt er aus der Fensterprozedur raus und wenn er dann bei WM_CLOSE ankommt, ist der Inhalt wieder vergessen, weil sie lokal ist.
Du hast in deinem Beispiel aber einen ganz anderen Ansatz. Und zwar einen objektorieintierten. Die Methode Dialog.Execute wird bei dir wahrscheinlich DialogBox(...) aufrufen. |
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Ich dachte sowas könnte man halt och auf nonVCL ummoscheln (hab ja sozusagen och gerade erst mit dieser Materie angefangen) ... na ja, dann halt nicht :?
|
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Klar kann man das. Motzi hatte für den Usermanager ein komplettes objektorientiertes Framework entworfen. Nur leider mit einem hartnäckigen Bug, der es leider unbrauchbar macht. ;)
|
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Hallo,
Zitat:
Gruß xaromz |
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
So bald man in einem Editfeld etwas eingibt, reagiert das Fenster nicht mehr. Aber den bug kann nur Motzi finden, weil er einen Überblick über seinen Code hat. Desweiteren würde es bedeuten, dass ich alle Quellen weitergeben müsste und das will ich (noch) nicht. ;) Aber das wird hier jetzt offtopic.
|
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Man könnte beim Aufruf von DialogBoxParam() auch den Zeiger auf eine Struktur übergeben (kommt in WM_INITDIALOG an, wenn ich mich recht erinnere).
Diesen Zeiger kann man sich dann im Dialog lokal speichern (SetProp/GetProp). |
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Das klingt interessant. Wie ginge das genau mit SetPorp und GetPorp? Das kenne ich noch nicht.
|
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
|
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Klingt gut. ;)
|
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Nette Idee .... find ich gut.
Zitat:
|
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Zitat:
|
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Zitat:
Delphi-Quellcode:
var
//... SelCmpData: TSelCmpData; //... begin //... Ret := DialogBoxParam(HInstance, MAKEINTRESOURCE(200), hDlg, @ChooseCompDlgFunc, LPARAM(@SelCmpData)); //... hier ist die lokale Struktur durch den Dialog gefüllt worden (oder eben nicht, je nach Exit-Code) |
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Ach so. Und wo kommt da jetzt SetProp und GetProp ins Spiel? Aber wie wird denn dann die Struktur gefüllt? Sie ist doch nur im Hauptprogramm bekannt.
|
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Hi,
nur mal so als Einwurf: Früher habe ich solche Daten immer mit SendMessage oder besser mit PostMessage verschickt. Ist das keine sinnvolle Möglichkeit mehr? Gruß wo |
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Zitat:
(ps: RemoveProp nicht vergessen :)) Ergo, keine globalen Variablen und kein Mißbrauch des Exit-Codes. Zitat:
|
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Ja wer holt sich den Zeiger, aber er kennt doch die Struktur nicht, die dahinterliegt, weil diese Struktur doch nur im Hauptprogramm definiert ist oder wo hast du sie definiert?
|
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Zitat:
Ich glaube es ist einfacher wenn ich ein Beispiel dazu schreibe, aber im Moment fehlt mir die Zeit dazu... |
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Ach so, dann ist alles klar, denn dann kennt auch das Hauptprogramm die Struktur, da man ja die Unit des Dialoges vorher im Hauptprogramm einbinden muss. Ich werde es heute Abend mal probieren.
|
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Also diese Window Properties klingen ja wirklich nicht schlecht.
Derzeit speichere/lese ich meinen Zeiger per SetWindowLong und GetWindowLong im UserBereich ... sollte ich da auch besser umsteigen, oder ist dieses auch OK? Klar, der Vorteil bei den Properties wäre natürlich, daß da über 'nem Namen und nicht mit 'ner "Nummer" auf die Daten zugegriffen werden kann. |
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Hier das angekündigte Beispiel (schnell runtergeschrieben, statt eines Ressourcenskriptes habe ich DialogBoxIndirect verwendet (einfach um das Beispiel auf den Quellcode zu beschränken))
Delphi-Quellcode:
Der Aufruf sieht dann etwa so aus:
unit FooDlg;
interface {$MINENUMSIZE 4} uses Windows; type {$IFDEF UNICODE} TextString = System.WideString; {$ELSE !UNICODE} TextString = System.AnsiString; {$ENDIF UNICODE} type TFooModalResult = ( foomrNone, foomrOk, foomrCancel ); type TFooDialogParam = record Parent: HWND; // in Text : TextString; // in/out end; type TFooDialog = class private FText: TextString; public class function ShowModal(var AParam: TFooDialogParam): TFooModalResult; end; implementation {$EXTENDEDSYNTAX ON} uses Messages; const FooDialogTemplate: packed record Dialog: packed record Header : TDlgTemplate; Menu : array [0..0] of WideChar; WndClass: array [0..0] of WideChar; Title : array [0..3] of WideChar; Points : Word; Weight : Word; Italic : Byte; Charset : Byte; FontFace: array [0..12] of WideChar; end; __align0: Word; Edit: packed record Header : TDlgItemTemplate; WndClass : array [0..1] of WideChar; Title : array [0..0] of WideChar; ExtraCount: Word; end; __align1: Word; ButtonOk: packed record Header : TDlgItemTemplate; WndClass : array [0..1] of WideChar; Title : array [0..3] of WideChar; ExtraCount: Word; end; ButtonCancel: packed record Header : TDlgItemTemplate; WndClass : array [0..1] of WideChar; Title : array [0..7] of WideChar; ExtraCount: Word; end; end = ( Dialog: ( Header: ( style : WS_VISIBLE or WS_POPUP or WS_CAPTION or WS_SYSMENU or DS_MODALFRAME or DS_SETFONT or DS_CENTER; dwExtendedStyle: 0; cdit : 3; x : 0; y : 0; cx : 4 + 100 + 4; cy : 4 + 60 + 2 + 12 + 4 ); Menu : (#0); WndClass: (#0); Title : ('F', 'o', 'o', #0); Points : 8; Weight : FW_NORMAL; Italic : Ord(False); Charset : DEFAULT_CHARSET; FontFace: ('M', 'S', ' ', 'S', 'h', 'e', 'l', 'l', ' ', 'D', 'l', 'g', #0) ); Edit: ( Header: ( style : WS_VISIBLE or WS_CHILD or WS_TABSTOP or ES_MULTILINE or ES_WANTRETURN or WS_VSCROLL or WS_HSCROLL or ES_AUTOVSCROLL or ES_AUTOHSCROLL; dwExtendedStyle: 0; x : 4; y : 4; cx : 100; cy : 60; id : 100 ); WndClass : (#$FFFF, #$0081); Title : (#0); ExtraCount: 0 ); ButtonOk: ( Header: ( style : WS_VISIBLE or WS_CHILD or WS_TABSTOP or BS_DEFPUSHBUTTON; dwExtendedStyle: 0; x : 4 + 100 - 38 - 2 - 38; y : 4 + 60 + 2; cx : 38; cy : 12; id : ID_OK; ); WndClass : (#$FFFF, #$0080); Title : ('&', 'O', 'K', #0); ExtraCount: 0 ); ButtonCancel: ( Header: ( style : WS_VISIBLE or WS_CHILD or WS_TABSTOP or BS_PUSHBUTTON; dwExtendedStyle: 0; x : 4 + 100 - 38; y : 4 + 60 + 2; cx : 38; cy : 12; id : ID_CANCEL; ); WndClass : (#$FFFF, #$0080); Title : ('&', 'C', 'a', 'n', 'c', 'e', 'l', #0); ExtraCount: 0; ) ); function FooDialogProc(ADlg: HWND; AMsg: UINT; WParam: WPARAM; LParam: LPARAM): Integer stdcall; const PropName = 'Instance'; var PropInst: TFooDialog; EditText: HWND; begin Result := Ord(True); case AMsg of WM_INITDIALOG: begin PropInst := TFooDialog(LParam); SetProp(ADlg, PropName, THandle(PropInst)); if Assigned(PropInst) then begin EditText := GetDlgItem(ADlg, FooDialogTemplate.Edit.Header.id); if EditText <> 0 then SetWindowText(EditText, PChar(PropInst.FText)); end; end; WM_NCDESTROY: RemoveProp(ADlg, PropName); WM_CLOSE: EndDialog(ADlg, Integer(foomrNone)); WM_COMMAND: case HiWord(WParam) of BN_CLICKED: begin case LoWord(WParam) of ID_OK: begin PropInst := TFooDialog(GetProp(ADlg, PropName)); if Assigned(PropInst) then begin EditText := GetDlgItem(ADlg, FooDialogTemplate.Edit.Header.id); if EditText <> 0 then begin SetLength(PropInst.FText, GetWindowTextLength(EditText) + 1); SetLength(PropInst.FText, GetWindowText(EditText, PChar(PropInst.FText), Length(PropInst.FText))); end; end; end; end; EndDialog(ADlg, LoWord(WParam)); end; else Result := Ord(False); end; else Result := Ord(False); end; end; class function TFooDialog.ShowModal(var AParam: TFooDialogParam): TFooModalResult; var FooDialog: TFooDialog; begin FooDialog := TFooDialog.Create(); try FooDialog.FText := AParam.Text; Result := TFooModalResult( DialogBoxIndirectParam(HInstance, FooDialogTemplate.Dialog.Header, AParam.Parent, TFNDlgProc(@FooDialogProc), Integer(FooDialog))); AParam.Text := FooDialog.FText; finally FooDialog.Free(); end; end; end.
Delphi-Quellcode:
var
Param: TFooDialogParam; begin Param.Parent := ParentHandle; Param.Text := 'Foo'#13#10'Bar'; case TFooDialog.ShowModal(Param) of foomrOk: MessageBox(Param.Parent, PChar(Param.Text), '[OK]', MB_OK); foomrCancel: MessageBox(Param.Parent, PChar(Param.Text), '[Cancel]', MB_OK); else MessageBox(Param.Parent, PChar(Param.Text), 'Dialog closed', MB_OK); end; end; |
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Ui. Da muss ich erstmal gucken, wo du die Daten ablegst und wie du sie wieder hervorzauberst. ;)
|
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Zitat:
|
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Das mit der Klasse verkompliziert das eigentlich mehr.
|
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Zitat:
|
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
So gerade ausprobiert: Einen Dialog kann man auch einfach mit EndDialog schließen. man muss also kein WM_CLOSE shcicken und dann auf WM_CLOSE reagieren. Somit kommt meine Methode auch ohne eine globale Variable in der Unit für den zweiten Dialog aus. :P Nur die Struktur muss global in der Unit sein.
Ich glaube, dabei bleibe ich auch. Nicos Methode ist mir doch etwas zu kompliziert muss ich ehrlich sagen. :? |
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Zitat:
Ich finde den Missbrauch des Exit-Codes bedenklicher als mein dahingeschludertes Beispiel :) |
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Also nochmal zu meiner winzigen Frage ...
was is nun besser (bzw. was würdet ihr bevorzugen) ... das mit den Properties, oder Set/GetWindowLong? |
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Ich glaube, das nimmt sich nichts. Und ist wohl reine Geschmackssache.
|
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Zitat:
Geschmacksfrage. |
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Da ich eh noch mehr OOP bin, is dat mit der Klasse schon klar :roll:
und beim Speichern, kann ich dann also beim Get/SetWindowLong bleiben ... hab's die beiden Male auch schon so gemacht :stupid: |
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
also die idee währe mir zu umständlich(evlt. habe ich den beitrag auch falsch verstanden) ich gehe immer so vor:
wenn der user auf ok klick wird die Tag variable vom dialog gesetzt und bei abbrechen auch dann kann ich einfach prüfen und beim nächsten aufrufen wird die variable dann wieder auf z.b.-1 gesetzt |
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Ohne VCL hast du aber keine Tag-Eigenschaft. Und wenn dann würde ich im Dialog entsprechende Rückgabewerte für die Schaltflächen vergeben vom Typ mbResult: mkOK, mbCancel, ...
|
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
das geht doch nur wenn ShowModal verwendet wird oder ?
und dann muss du aber das formular manuell deaktiveren oder nicht ? ich verstehe noch nicht so ganz, warum so ein aufwand betrieben wird um so eine "einfache" sache zu lösen... wo liegt das problem bei einer gobalen variable ? die kann doch einmal definiert werden und wenn das forumlar aufgerufen wird, wird sie jedesmaml auf z.b. 0 gesetzt wird nun auf ok klick auf 1 und bei abbrechen auf 2 z.b. wo sind da die fehler qullen ? |
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Zitat:
(könnte ja sein, dass der Dialog nicht modal genutzt wird) |
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
wo ist da das problem ?
wenn ich jedes dialogs als klasse defnire kann ich davon doch soviele Instanzen erzeugen wie ich möchte, oder nicht ? Es gibt viele wege die noch rom führen einige sind schwer andere wieder einfache aber alle haben nur ein zweck: sie erfüllen ihre aufgabe :-D Der eine betreibt mehr aufwand der andre weniger, um das gleiche zu reichen :-D |
Re: [Artikel] Den ExitCode eines Dialogfensters nutzen
Zitat:
Wie willst du die beliebige Anzahl von Objektreferenzen in einer globalen Variable speichern? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:38 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