Autor Beitrag
Spaceguide
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 552


(D3/D7/D8) Prof.
BeitragVerfasst: 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:

ausblenden 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



BeitragVerfasst: Mo 23.01.06 21:27 
Und warum nutzt du nicht das OnClose Ereignis der Form?
Spaceguide Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 552


(D3/D7/D8) Prof.
BeitragVerfasst: 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.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 552


(D3/D7/D8) Prof.
BeitragVerfasst: 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.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Di 24.01.06 00:36 
Ich bezog mich auf diesen Einwand:
user profile iconSpaceguide 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 552


(D3/D7/D8) Prof.
BeitragVerfasst: 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.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 552


(D3/D7/D8) Prof.
BeitragVerfasst: 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.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 552


(D3/D7/D8) Prof.
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 552


(D3/D7/D8) Prof.
BeitragVerfasst: 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.

ausblenden volle Höhe Delphi-Quelltext
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);

  //Overwrite Form's Modalresult
  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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 312

Win 9x, Win XP
Delphi 3pro, 7PE
BeitragVerfasst: 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):
ausblenden 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;     //If Windows exit ('X' on Form Top) chosen
begin
  rply := Application.MessageBox(Pchar(text5),'Exit Program',
                           mb_IconQuestion + mb_YesNoCancel + mb_DefButton3);
  if rply = mrYes
  then SaveSettings               //if 'YES' then save settings
  else if rply = mrCancel         // (if 'NO' then don't save )
       then CanClose := false;    //if 'CANCEL', don't leave program
end;
.
.
procedure TForm1.Button2Click(Sender: TObject);  // Exit-Program Button
begin
  Form1.Close;   //actually, this calls above CloseQuery routine
end;


Vielleicht hilft's. T'schuldigung für's Englisch.
Spaceguide Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 552


(D3/D7/D8) Prof.
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 154



BeitragVerfasst: Fr 27.01.06 08:54 
Setze doch einen Standardwert in FormShow (mrCancel) und nur auf den Ok-Button etwas anderes (mrOk)
Spaceguide Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 552


(D3/D7/D8) Prof.
BeitragVerfasst: Fr 27.01.06 20:09 
Ja genau, ich setze in FormShow modalresult auf mrCancel ... mann, mann, noch so ein Vorschlag?
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Fr 27.01.06 20:11 
user profile iconSpaceguide hat folgendes geschrieben:
mann, mann, noch so ein Vorschlag?
Bitte achte auf Deinen Tonfall! :mahn:

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
alias5000
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
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)
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 552


(D3/D7/D8) Prof.
BeitragVerfasst: 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.