Einzelnen Beitrag anzeigen

Schokohase
(Gast)

n/a Beiträge
 
#9

AW: Modaler Doppelklick gibt Event an Ursprungsfenster weiter

  Alt 12. Sep 2018, 09:20
Dein Problem ist also das der Wert der Eigenschaft ModalResult zurückgegeben wird.. weil dein Parent Fenster aktiv ist.
Das stimmt so leider nicht.

Unter Delphi 10.2 Tokyo wird beim ShowModal für jedes Fenster der Anwendung MSDN-Library durchsuchenEnableWindow aufgerufen mit bEnable = false .
Delphi-Quellcode:
// Vcl.Forms.pas 2215
function DoDisableWindow(Window: HWnd; Data: LPARAM): Bool; {$IFNDEF CLR}stdcall;{$ENDIF}
var
  P: TTaskWindowType;
begin
  if (Window <> TaskActiveWindow) and IsWindowVisible(Window) and
    IsWindowEnabled(Window) then
  begin
{$IF DEFINED(CLR)}
    P := TTaskWindow.Create;
{$ELSE}
    New(P);
{$ENDIF}
    P.Next := TaskWindowList;
    P.Window := Window;
    TaskWindowList := P;
    EnableWindow(Window, False);
  end;
  Result := True;
end;
Diesen Wert kann man aber nicht über Delphi-Referenz durchsuchenTForm.Enabled auslesen. Trotz dass
Delphi-Referenz durchsuchenTForm.Enabled auf true steht, ist es für das Betriebssystem aber disabled.

Das Problem ist, dass das modale Fenster versteckt wird und das vorherige Fenster aktiviert wird, obwohl in der Message-Queue noch Nachrichten enthalten sind, die vom modalen Fenster verarbeitet werden müssten (MouseUp) und jetzt aber vom falschen Fenster verarbeitet werden.

Delphi-Quellcode:
// VCL.Forms.pas 7352
function TCustomForm.ShowModal: Integer;
var
  WindowList: TTaskWindowList;
  LSaveFocusState: TFocusState;
  SaveCursor: TCursor;
  SaveCount: Integer;
  ActiveWindow: HWnd;
begin
  // ... schnipp ...
  Application.ModalStarted;
  try
    { RecreateWnd could change the active window }
    ActiveWindow := GetActiveWindow;
    // ... schnipp ...
    WindowList := DisableTaskWindows(0);
    try
      Show;
      try
        SendMessage(Handle, CM_ACTIVATE, 0, 0);
        ModalResult := 0;
        repeat // Message-Loop zum Verarbeiten der Messages
          Application.HandleMessage;
          if Application.Terminated then ModalResult := mrCancel else
            if ModalResult <> 0 then CloseModal;
        until ModalResult <> 0;
        Result := ModalResult;
        SendMessage(Handle, CM_DEACTIVATE, 0, 0);
        if GetActiveWindow <> Handle then ActiveWindow := 0;
      finally
        Hide;
      end;
    finally
      if Screen.CursorCount = SaveCount then
        Screen.Cursor := SaveCursor
      else Screen.Cursor := crDefault;
      EnableTaskWindows(WindowList);
      if Screen.SaveFocusedList.Count > 0 then
      begin
        Screen.FocusedForm := TCustomForm(Screen.SaveFocusedList.First);
        Screen.SaveFocusedList.Remove(Screen.FocusedForm);
      end else Screen.FocusedForm := nil;

      // Hier wird jetzt versucht das alte Fenster wieder zu aktivieren

      { ActiveWindow might have been destroyed and using it as active window will
        force Windows to activate another application }

      if (ActiveWindow <> 0) and not IsWindow(ActiveWindow) then
        ActiveWindow := FindTopMostWindow(0);
      if ActiveWindow <> 0 then
        SetActiveWindow(ActiveWindow);
      RestoreFocusState(LSaveFocusState);
      Exclude(FFormState, fsModal);
    end;
  finally
    Application.ModalFinished;
  end;
end;
  Mit Zitat antworten Zitat