Autor |
Beitrag |
Spaceguide
      
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: Mo 23.01.06 20:56
Ich möchte beim Schließen eines modalen Fensters per X-Knopf ein anderes ModalResult als mrCancel zurückgeben. Dafür fange ich SC_CLOSE ab:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| procedure WMSysCommand(var Msg: TMessage); message WM_SYSCOMMAND; ... ... ... procedure TForm.WMSysCommand(var Msg: TMessage); begin if Msg.WPARAM = SC_CLOSE then begin if MessageDlg('OK or Cancel?', mtConfirmation, [mbOK, mbCancel], 0) = mrOK then modalresult := mrOK else modalresult := mrCancel; end;
inherited; end; |
Dummerweise wird mein ModalResult dann wieder auf mrCancel gesetzt. Wie löse ich das Problem am besten?
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mo 23.01.06 21:27
Und warum nutzt du nicht das OnClose Ereignis der Form?
|
|
Spaceguide 
      
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: Di 24.01.06 00:13
Ich hab noch einen OK und Cancel-Knopf auf dem Form, das OnClose-Ereignis wird auch gefeuert, wenn ich diese drücke.
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Di 24.01.06 00:20
Aber dann ist das ModalResult ja schon gesetzt. Darüber kannst Du dann entscheiden, ob es in OnClose noch gesetzt werden muss oder nicht.
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
Spaceguide 
      
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: Di 24.01.06 00:30
Wenn man den X-Knopf drückt, wird Modalresult auf mrCancel gesetzt, also kann man es nicht entscheiden.
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Di 24.01.06 00:36
Ich bezog mich auf diesen Einwand:
Spaceguide hat folgendes geschrieben: | Ich hab noch einen OK und Cancel-Knopf auf dem Form, das OnClose-Ereignis wird auch gefeuert, wenn ich diese drücke. |
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
Spaceguide 
      
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: Di 24.01.06 00:53
Dann erklär ich es dir nochmal:
Es gibt drei Möglichkeiten das Fenster zu schließen:
1) OK-Knopf => ModalResult=mrOK
2) Cancel-Knof => ModalResult=mrCancel
3) X-Knopf,Systemmenü-Close,ALT-F4 => ModalResult=mrCancel
im OnClose-Ereignis ist ModalResult bereits gesetzt, man kann also nicht mehr herausbekommen, ob jetzt der Cancel-Knopf oder der X-Knopf gedrückt wurde. Probiers doch mal aus.
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Di 24.01.06 00:59
Ach sop, jetzt verstehe ich.
Dann setze doch das ModalResult des Buttons auf einen sonst nicht verwendeten Wert, den Du im OnClose zur Unterscheidung nutzt und dann auf mrCancel setzt. Das ist nicht schön, gebe ich zu, aber es sollte gehen.
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
Spaceguide 
      
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: Di 24.01.06 01:16
Diese Lösung habe ich in den Google Groups auch schon gefunden, gefällt mir aber auch nicht so. Da würde ich lieber das was der X-Knopf zurückliefert auf mrAbort oder so setzen.
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Di 24.01.06 01:22
Ich habe mir die Sourcen der VCL angesehen. Das mrCancel ist leider hardcoded.
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
Spaceguide 
      
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: Di 24.01.06 01:28
Ja, leider. Vielleicht könnte man etwas basteln: Eine nicht-visuelle Komponente, die man auf das Form klatscht.
Diese Komponente sollte sich in WM_SYSCOMMAND des Forms einklinken, und bei SC_CLOSE (wird vom X-Knopf gesendet) ein Feld auf True setzen. Dann müsste sie sich noch ins OnClose-Ereignis des Forms hineinklinken und den MessageDlg anzeigen, wenn der X-Knopf gedrückt wurde und entsprechend modalresult setzen. Mal schauen, wie sich das realisieren lässt.
|
|
Spaceguide 
      
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: Mi 25.01.06 17:10
Hab mir mal wieder selbst geholfen und diese Komponente zusammengefrickelt. Wenn man Sie auf den Form klatscht hat man folgende Eigenschaften:
-Minimiert man ein modales Fenster, so wird die ganze Applikation minimiert (finde ich sehr nützlich)
-Beim Schließen per X-Knopf wird ein MessageDlg angezeigt mit variabler Nachricht und den Knöpfen Ja/Nein. Damit kann man sowas wie z.B. "Einstellungen übernehmen" fragen. Wird "Ja" gedrückt, wird Modalresult Fensters auf mrOK gesetzt, ansonsten auf mrCancel.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128:
| unit uModalModifier;
interface
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
type TModalModifier = class(TComponent) private FForm: TForm; FOldModalWndProc: Pointer; FInstanceModalWndProc: Pointer; FOnMinimize: TNotifyEvent; FAskForOKCancel : boolean; FOKCancelMsg : string; FModalResult : TModalResult; FMinimizeAll : boolean; protected procedure ModalWndProc(var Message: TMessage); virtual; function DoAskForOKCancel : TModalResult;
public constructor Create(AOwner: TComponent); override; destructor Destroy; override; published property OnMinimize: TNotifyEvent read FOnMinimize write FOnMinimize default NIL; property AskForOKCancel : boolean read FAskForOKCancel write FAskForOKCancel default false; property MinimizeAll : boolean read FMinimizeAll write FMinimizeAll default false; property OKCancelMsg : string read FOKCancelMsg write FOKCancelMsg; end;
procedure Register;
implementation
constructor TModalModifier.Create; begin inherited Create(AOwner);
FForm := AOwner as TForm;
FInstanceModalWndProc := MakeObjectInstance(ModalWndProc); FOldModalWndProc := Pointer(GetWindowLong(FForm.Handle, GWL_WNDPROC)); SetWindowLong(FForm.Handle, GWL_WNDPROC, Longint(FInstanceModalWndProc));
FModalResult := mrNone; end;
destructor TModalModifier.Destroy; begin if Assigned(FInstanceModalWndProc) then begin SetWindowLong(FForm.Handle, GWL_WNDPROC, integer(FOldModalWndProc)); FreeObjectInstance(FInstanceModalWndProc); FInstanceModalWndProc := nil; end;
inherited Destroy; end;
function TModalModifier.DoAskForOKCancel : TModalResult; begin if MessageDlg(FOKCancelMsg,mtConfirmation, [mbYes, mbNo], 0) = mrYes then Result := mrOK else Result := mrCancel; end;
procedure TModalModifier.ModalWndProc(var Message: TMessage); begin case Message.Msg of
WM_SYSCOMMAND: begin if Message.WParam = SC_CLOSE then begin if FAskForOKCancel then FModalResult := DoAskForOKCancel; end;
if Message.WParam = SC_MINIMIZE then begin if Assigned(FOnMinimize) then FOnMinimize(Self); if FMinimizeAll then ShowWindow(Application.Handle, SW_SHOWMINNOACTIVE) else ShowWindow(FForm.Handle, SW_SHOWMINNOACTIVE); Exit; end; end;
WM_DESTROY: begin if Assigned(FInstanceModalWndProc) then begin SetWindowLong(FForm.Handle, GWL_WNDPROC, Longint(FOldModalWndProc)); FreeObjectInstance(FInstanceModalWndProc); FInstanceModalWndProc := nil; end; end;
WM_ACTIVATE: begin if Message.WParamLo<>WA_INACTIVE then begin if FMinimizeAll then ShowWindow(Application.Handle, SW_SHOWNORMAL) else ShowWindow(FForm.Handle, SW_SHOWNORMAL) end; end; end;
Message.Result:= CallWindowProc(FOldModalWndProc, FForm.Handle, Message.Msg, Message.WParam, Message.LParam);
if Message.Msg = WM_CLOSE then begin if FModalResult<>mrNone then FForm.ModalResult := FModalResult; end; end;
procedure Register; begin RegisterComponents('Installed', [TModalModifier]); end;
end. |
|
|
aim65
      
Beiträge: 312
Win 9x, Win XP
Delphi 3pro, 7PE
|
Verfasst: Mi 25.01.06 20:22
Hallo, bin neu hier.
Warum nehmt Ihr nicht "Form.Close.Query" mit "CanClose"?
Hab so etwas in einem meiner Progrämmchen benutzt, wobei das Programm sowohl über "X" als auch mit einem Button verlassen werden kann. Hier mal der herauskopierte Source (hoffe, daß ich das mit den Tags hinkriege):
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); var rply: Byte; begin rply := Application.MessageBox(Pchar(text5),'Exit Program', mb_IconQuestion + mb_YesNoCancel + mb_DefButton3); if rply = mrYes then SaveSettings else if rply = mrCancel then CanClose := false; end; . . procedure TForm1.Button2Click(Sender: TObject); begin Form1.Close; end; |
Vielleicht hilft's. T'schuldigung für's Englisch.
|
|
Spaceguide 
      
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: Mi 25.01.06 23:04
Das hatten wir schon. OnCloseQuery wird auf gefeuert, wenn z.b. der OK-Knopf gedrückt. Das soll aber gerade NICHT der Fall sein.
|
|
Böser Borstel
      
Beiträge: 154
|
Verfasst: Fr 27.01.06 08:54
Setze doch einen Standardwert in FormShow (mrCancel) und nur auf den Ok-Button etwas anderes (mrOk)
|
|
Spaceguide 
      
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: Fr 27.01.06 20:09
Ja genau, ich setze in FormShow modalresult auf mrCancel ... mann, mann, noch so ein Vorschlag?
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Fr 27.01.06 20:11
Spaceguide hat folgendes geschrieben: | mann, mann, noch so ein Vorschlag? |
Bitte achte auf Deinen Tonfall! 
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
alias5000
      
Beiträge: 2145
WinXP Prof SP2, Ubuntu 9.04
C/C++(Code::Blocks, VS.NET),A51(Keil),Object Pascal(D2005PE, Turbo Delphi Explorer) C# (VS 2008 Express)
|
Verfasst: Fr 27.01.06 20:16
Ja noch einer, man kann die Sache auch andersherum und viel weniger Schreibaufwändig machen:
einfach eine Globale Boolean Variable deklarieren, die bei OnFormShow auf false gesetzt wird.
Wird irgendein Button (OK oder Cancel) gedrückt, setzt du sie auf true.
Ist die aber bei OnClose noch auf false, wurde der Weg über den "X" Button der Alt+F4 usw. gewählt.
Vllcht 5 Zeilen, anstatt von 128
Gruß alias5000
_________________ Programmers never die, they just GOSUB without RETURN
|
|
Spaceguide 
      
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: Fr 27.01.06 20:28
Nunja, ich hab hier ungefähr 60 Forms, die diese Eigenschaft haben sollen, manche werden auch verschachtelt aufgerufen. Die Lösung mit einer globalen Variable ist also bestenfalls Pfusch und unelegant, da ich dann die Logik in jedes Fenster einbauen muss anstatt einfach die Komponente draufzuklatschen.
|
|