AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein GUI-Design mit VCL / FireMonkey / Common Controls Delphi Hintergrundform abdunkeln, wenn andere Form Modal geöffnet wird?

Hintergrundform abdunkeln, wenn andere Form Modal geöffnet wird?

Ein Thema von NoGAD · begonnen am 30. Apr 2024 · letzter Beitrag vom 14. Mai 2024
Antwort Antwort
Benutzerbild von NoGAD
NoGAD

Registriert seit: 31. Jan 2006
Ort: Weimar
345 Beiträge
 
Delphi 10.4 Sydney
 
#1

AW: Hintergrundform abdunkeln, wenn andere Form Modal geöffnet wird?

  Alt 11. Mai 2024, 22:59
Hallo nochmal


Edit: Problem gelöst, siehe Anmerkungen im Code..


Den Code von Uwe habe ich versucht etwas zu erweiteren, was auch ganz gut klappt.
(Mir gefällt die Parameterliste in der Functionsübergabe noch nicht, das würde ich später als einen Type realiseren.)

Den Schatten der Form kann man auslesen (ein Beispiel habe ich hier gefunden: https://stackoverflow.com/questions/...rs-of-the-form, leider ergibt das bei mir aber Fehler: die Breiten/Höhen werden nicht korrekt ausgelesen.
Die entsprechende Form ist schon sichtbar, daran kann es wohl nicht liegen.


Delphi-Quellcode:

function ShowModalDimmed(Form: TForm; ParentForm: TForm = nil; aDimmed: Boolean = True; Centered: Boolean = True; SpaceBelow: Integer = 0; aAlphaBlendValue: Integer = 192; aBackColor: TColor = clBlack;
  aFadeIn: Boolean = True; aFadeOut: Boolean = True): TModalResult;
var
  Back: TForm;

  Dummy_Rect: TRect;

  targetAlpha: Integer;
  Dummy_Alpha_inc: Integer;
  alphaDiff: Integer;
begin
  (* Hintergrundform abdunkeln *)
  if not aDimmed then
  begin
    Result := Form.ShowModal;
    Exit;
  end;

  Back := TForm.Create(nil);
  try
    Back.Position := poDesigned; //poMainFormCenter; <- war ein Fehler von mir
    Back.AlphaBlend := True;

    targetAlpha := aAlphaBlendValue;
    if targetAlpha > 255 then
      targetAlpha := 255;
    if targetAlpha < 1 then
      targetAlpha := 1;

    if aFadeIn then
      Back.AlphaBlendValue := 1
    else
      Back.AlphaBlendValue := targetAlpha;
    Back.Color := aBackColor;
    Back.DoubleBuffered := True;
    Back.BorderStyle := bsNone;

    if ParentForm <> nil then
    begin
      Dummy_Rect := GetFormShadow(ParentForm);
      Back.SetBounds(ParentForm.Left + Dummy_Rect.Left, ParentForm.Top + Dummy_Rect.Top, ParentForm.Width - Dummy_Rect.Right, ParentForm.Height - Dummy_Rect.Bottom);
    end;
    if ParentForm = nil then
    begin
      Back.SetBounds(0, 0, Screen.Width, Screen.Height);
    end;
    Back.Show;
    if aFadeIn then
    begin
      Dummy_Alpha_inc := Back.AlphaBlendValue;
      while Back.AlphaBlendValue < targetAlpha do
      begin
        alphaDiff := targetAlpha - Back.AlphaBlendValue;
        Inc(Dummy_Alpha_inc, min(alphaDiff, 5));
        Back.AlphaBlendValue := Dummy_Alpha_inc;
        Application.ProcessMessages;
        Sleep(20);
      end;
      Back.AlphaBlendValue := aAlphaBlendValue;
    end;

    if Centered then
    begin
      Form.Position := poMainFormCenter; // Keine extra Berechnung notwendig; außerdem für mehrere Monitore geeignet
    end;

    Result := Form.ShowModal;

    if aFadeOut then
    begin
      while Back.AlphaBlendValue > 1 do
      begin
        Back.AlphaBlendValue := Back.AlphaBlendValue - 12;
        Application.ProcessMessages;
        Sleep(20);
      end;
    end;
    Back.Hide;
  finally
    Back.Free;
  end;
end;

function GetFormShadow(aForm: TForm): TRect;
(* uses: Winapi.DwmApi *)
var
  R1, R2: TRect;
begin
  (* Breite eines Schattens einer TForm *)
  Result := default (TRect);
  if (Win32MajorVersion >= 6) and DwmCompositionEnabled then
  begin
    if DwmGetWindowAttribute(aForm.Handle, DWMWA_EXTENDED_FRAME_BOUNDS, @R1, SizeOf(R1)) = S_OK then
    begin
      R2 := aForm.BoundsRect;
      Result.Left := R2.Left - R1.Left; // Linke Breite des Schattens
      if Result.Left < 0 then
        Result.Left := Result.Left * -1;
      Result.Right := (R2.Right - R1.Right) + Result.Left; // Rechte Breite des Schattens
      if Result.Right < 0 then
        Result.Right := Result.Right * -1;
      Result.Top := R2.Top - R1.Top; // Obere Höhe des Schattens
      if Result.Top < 0 then
        Result.Top := Result.Top * -1;
      Result.Bottom := (R2.Bottom - R1.Bottom) + Result.Top; // Untere Höhe des Schattens
      if Result.Bottom < 0 then
        Result.Bottom := Result.Bottom * -1;
    end;
  end;

end;
Delphi-Quellcode:
(* Diese beiden Brechnungen waren nicht korrekt *)
      Result.Right := (R2.Right - R1.Right) + Result.Left; // Rechte Breite des Schattens
      Result.Bottom := (R2.Bottom - R1.Bottom) + Result.Top; // Untere Höhe des Schattens


Ich hoffe, das ist jetzt fehlerfrei

LG Mathias
Mathias
Ich vergesse einfach zu viel.

Geändert von NoGAD (11. Mai 2024 um 23:55 Uhr) Grund: Fix Code
  Mit Zitat antworten Zitat
Benutzerbild von NoGAD
NoGAD

Registriert seit: 31. Jan 2006
Ort: Weimar
345 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: Hintergrundform abdunkeln, wenn andere Form Modal geöffnet wird?

  Alt 12. Mai 2024, 01:09
(Eigener Thread, wegen neuem Code)

Delphi-Quellcode:

Type
  TDimmFormValues = record
    aForm: TForm;
    aParentForm: TForm;
    aDimmed: Boolean;
    aCentered: Boolean;
    aSpaceBelow: Integer;
    aAlphaBlendValue: Integer;
    aBackColor: TColor;
    aFadeIn: Boolean;
    aFadeOut: Boolean;

    class function Init(
      aDimmed: Boolean = True;
      aCentered: Boolean = True;
      aSpaceBelow: Integer = 0;
      aAlphaBlendValue: Integer = 192;
      aBackColor: TColor = clBlack;
      aFadeIn: Boolean = True;
      aFadeOut: Boolean = True): TDimmFormValues; static;
  end;

function ShowModalDimmed(const Dimm_Values: TDimmFormValues): TModalResult;
function GetFormShadow(aForm: TForm): TRect;

implementation

class function TDimmFormValues.Init(
  aDimmed: Boolean = True;
  aCentered: Boolean = True;
  aSpaceBelow: Integer = 0;
  aAlphaBlendValue: Integer = 192;
  aBackColor: TColor = 0;
  aFadeIn: Boolean = True;
  aFadeOut: Boolean = True): TDimmFormValues;
begin
  Result.aDimmed := aDimmed;
  Result.aCentered := aCentered;
  Result.aSpaceBelow := aSpaceBelow;
  Result.aAlphaBlendValue := aAlphaBlendValue;
  Result.aBackColor := aBackColor;
  Result.aFadeIn := aFadeIn;
  Result.aFadeOut := aFadeOut;
end;

function ShowModalDimmed(const Dimm_Values: TDimmFormValues): TModalResult;
var
  Back: TForm;

  Dummy_Rect: TRect;

  targetAlpha: Integer;
  Dummy_Alpha_inc: Integer;
  alphaDiff: Integer;
begin
  (* Hintergrundform abdunkeln *)
  if not Dimm_Values.aDimmed then
  begin
    Result := Dimm_Values.aForm.ShowModal;
    Exit;
  end;

  Back := TForm.Create(nil);
  try
    Back.Position := poDesigned; // poMainFormCenter;
    Back.AlphaBlend := True;

    targetAlpha := Dimm_Values.aAlphaBlendValue;
    if targetAlpha > 255 then
      targetAlpha := 255;
    if targetAlpha < 1 then
      targetAlpha := 1;

    if Dimm_Values.aFadeIn then
      Back.AlphaBlendValue := 1
    else
      Back.AlphaBlendValue := targetAlpha;
    Back.Color := Dimm_Values.aBackColor;
    Back.DoubleBuffered := True;
    Back.BorderStyle := bsNone;

    if Dimm_Values.aParentForm <> nil then
    begin
      Dummy_Rect := GetFormShadow(Dimm_Values.aParentForm);
      Back.SetBounds(Dimm_Values.aParentForm.Left + Dummy_Rect.Left, Dimm_Values.aParentForm.Top + Dummy_Rect.Top, Dimm_Values.aParentForm.Width - Dummy_Rect.Right, Dimm_Values.aParentForm.Height - Dummy_Rect.Bottom);
    end;
    if Dimm_Values.aParentForm = nil then
    begin
      Back.SetBounds(0, 0, Screen.Width, Screen.Height);
    end;
    Back.Show;
    if Dimm_Values.aFadeIn then
    begin
      Dummy_Alpha_inc := Back.AlphaBlendValue;
      while Back.AlphaBlendValue < targetAlpha do
      begin
        alphaDiff := targetAlpha - Back.AlphaBlendValue;
        Inc(Dummy_Alpha_inc, min(alphaDiff, 5));
        Back.AlphaBlendValue := Dummy_Alpha_inc;
        Application.ProcessMessages;
        Sleep(20);
      end;
      Back.AlphaBlendValue := Dimm_Values.aAlphaBlendValue;
    end;

    if Dimm_Values.aCentered then
    begin
      Dimm_Values.aForm.Position := poMainFormCenter; // Keine extra Berechnung notwendig
    end;

    Result := Dimm_Values.aForm.ShowModal;

    if Dimm_Values.aFadeOut then
    begin
      while Back.AlphaBlendValue > 1 do
      begin
        Back.AlphaBlendValue := Back.AlphaBlendValue - 12;
        Application.ProcessMessages;
        Sleep(20);
      end;
    end;
    Back.Hide;
  finally
    Back.Free;
  end;
end;

function GetFormShadow(aForm: TForm): TRect;
var
  R1, R2: TRect;
begin
  (* Breite eines Schattens einer TForm *)
  Result := default (TRect);
  if (Win32MajorVersion >= 6) and DwmCompositionEnabled then
  begin
    if DwmGetWindowAttribute(aForm.Handle, DWMWA_EXTENDED_FRAME_BOUNDS, @R1, SizeOf(R1)) = S_OK then
    begin
      R2 := aForm.BoundsRect;
      Result.Left := R2.Left - R1.Left; // Linke Breite des Schattens
      if Result.Left < 0 then
        Result.Left := Result.Left * -1;
      Result.Right := (R2.Right - R1.Right) + Result.Left; // Rechte Breite des Schattens
      if Result.Right < 0 then
        Result.Right := Result.Right * -1;
      Result.Top := R2.Top - R1.Top; // Obere Höhe des Schattens
      if Result.Top < 0 then
        Result.Top := Result.Top * -1;
      Result.Bottom := (R2.Bottom - R1.Bottom) + Result.Top; // Untere Höhe des Schattens
      if Result.Bottom < 0 then
        Result.Bottom := Result.Bottom * -1;
    end;
  end;

end;

Falls nun viele Aufrufe von ShowModalDimmed im Code erfolgen, würde ich eine globale Variable nutzen, damit nicht jedes Mal eine neue Variable erstellt werden muss. Durch class function TDimmFormValues.Init kann diese wieder auf die Standardwerte zurück gesetzt werden.

Aufruf (z.B.):

Delphi-Quellcode:
{
[..]
}

var
 Dimm_Values: TDimmFormValues;
{
[..]
}

 Dimm_Values := Dimm_Values.Init();
 Dimm_Values.aForm := Form2;
 Dimm_Values.aParentForm := Form1;
 Dimm_Values.aBackColor := clInfoBk;
 ShowModalDimmed(Dimm_Values);

LG Mathias
Mathias
Ich vergesse einfach zu viel.
  Mit Zitat antworten Zitat
DaCoda

Registriert seit: 21. Jul 2006
Ort: Hamburg
165 Beiträge
 
Delphi 12 Athens
 
#3

AW: Hintergrundform abdunkeln, wenn andere Form Modal geöffnet wird?

  Alt 12. Mai 2024, 06:05
Hallo Mathias (NoGAD),
der Ansatz ist nicht schlecht, aber es gibt zumindest unter Windows 11 noch ein weiteres Problemchen.
Die Fensterecken können Rund sein, dein Bereich ist aber immer eckig und das sieht dann etwas komisch aus.

Ich habe noch zusätzlich in deinen Code eingefügt:
Code:
 
if aParentForm <> nil then
  Back.RoundedCorners := Dimm_Values.aParentForm.RoundedCorners;

Ansonsten gut gemacht

LG
DaCoda™
Debuggers don’t remove bugs, they only show them in slow-motion.

Geändert von DaCoda (12. Mai 2024 um 06:40 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von NoGAD
NoGAD

Registriert seit: 31. Jan 2006
Ort: Weimar
345 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: Hintergrundform abdunkeln, wenn andere Form Modal geöffnet wird?

  Alt 12. Mai 2024, 07:23

Ich habe noch zusätzlich in deinen Code eingefügt:
Code:
 
if aParentForm <> nil then
  Back.RoundedCorners := Dimm_Values.aParentForm.RoundedCorners;

Ich konnte es unter Windows 11 nicht testen, ist der Feier mit deinem zusätzlichen Code behoben?

LG Mathias
Mathias
Ich vergesse einfach zu viel.
  Mit Zitat antworten Zitat
DaCoda

Registriert seit: 21. Jul 2006
Ort: Hamburg
165 Beiträge
 
Delphi 12 Athens
 
#5

AW: Hintergrundform abdunkeln, wenn andere Form Modal geöffnet wird?

  Alt 12. Mai 2024, 07:51
[QUOTE=NoGAD;1536601]
Ich konnte es unter Windows 11 nicht testen, ist der Feier mit deinem zusätzlichen Code behoben?

LG Mathias
Ja, damit ist das behoben
Debuggers don’t remove bugs, they only show them in slow-motion.
  Mit Zitat antworten Zitat
Benutzerbild von NoGAD
NoGAD

Registriert seit: 31. Jan 2006
Ort: Weimar
345 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: Hintergrundform abdunkeln, wenn andere Form Modal geöffnet wird?

  Alt 12. Mai 2024, 08:49
Vielen lieben Dank.

Lieben Gruß Mathias
Mathias
Ich vergesse einfach zu viel.
  Mit Zitat antworten Zitat
DaCoda

Registriert seit: 21. Jul 2006
Ort: Hamburg
165 Beiträge
 
Delphi 12 Athens
 
#7

AW: Hintergrundform abdunkeln, wenn andere Form Modal geöffnet wird?

  Alt 12. Mai 2024, 09:02
Ich habe mich aber entschieden den Code bzw. Aufruf von Uwe Raabe seinem Basiscode zu verwenden und das "Faden" nicht zu nutzen.
Damit ist der Aufruf aus meiner Sicht schöner/einfacher.

Aufrufbeispiele:
Code:
  ShowModalDimmed(Form, nil);

  ShowModalDimmed(Form, ParentForm);

  ShowModalDimmed(Form, ParentForm, Alphablend, BackColor, Centered);
Function:
Code:
function ShowModalDimmed(aForm: TForm; aParentForm: TForm; AlphaBlendValue: Integer = 100; BackColor: TColor = clGray; Centered: Boolean = True): TModalResult;
var
  Back: TForm;

  Dummy_Rect: TRect;

  targetAlpha: Integer;
  Dummy_Alpha_inc: Integer;
  alphaDiff: Integer;
begin
  Back := TForm.Create(nil);
  try
    Back.AlphaBlend := True;

    targetAlpha := AlphaBlendValue;
    if targetAlpha > 255 then
      targetAlpha := 255;
    if targetAlpha < 1 then
      targetAlpha := 1;

    Back.AlphaBlendValue := targetAlpha;
    Back.Color := BackColor;
    Back.DoubleBuffered := True;
    Back.BorderStyle := bsNone;

    if aParentForm <> nil then begin
      Back.Position := aParentForm.Position;
      Back.RoundedCorners := aParentForm.RoundedCorners;
      Dummy_Rect := GetFormShadow(aParentForm);
      Back.SetBounds(aParentForm.Left + Dummy_Rect.Left, aParentForm.Top + Dummy_Rect.Top, aParentForm.Width - Dummy_Rect.Right, aParentForm.Height - Dummy_Rect.Bottom);
    end else begin
      Back.SetBounds(0, 0, Screen.Width, Screen.Height);
    end;
    Back.Show;

    if Centered then begin
      aForm.Position := poMainFormCenter;
    end;

    Result := aForm.ShowModal;
    Back.Hide;
  finally
    Back.Free;
  end;
end;
Und die Function von Mathias (NoGAD):
Code:
function GetFormShadow(aForm: TForm): TRect;
var
  R1, R2: TRect;
begin
  (* Breite eines Schattens einer TForm *)
  Result := default (TRect);
  if (Win32MajorVersion >= 6) and DwmCompositionEnabled then
  begin
    if DwmGetWindowAttribute(aForm.Handle, DWMWA_EXTENDED_FRAME_BOUNDS, @R1, SizeOf(R1)) = S_OK then
    begin
      R2 := aForm.BoundsRect;
      Result.Left := R2.Left - R1.Left; // Linke Breite des Schattens
      if Result.Left < 0 then
        Result.Left := Result.Left * -1;
      Result.Right := (R2.Right - R1.Right) + Result.Left; // Rechte Breite des Schattens
      if Result.Right < 0 then
        Result.Right := Result.Right * -1;
      Result.Top := R2.Top - R1.Top; // Obere Höhe des Schattens
      if Result.Top < 0 then
        Result.Top := Result.Top * -1;
      Result.Bottom := (R2.Bottom - R1.Bottom) + Result.Top; // Untere Höhe des Schattens
      if Result.Bottom < 0 then
        Result.Bottom := Result.Bottom * -1;
    end;
  end;
Debuggers don’t remove bugs, they only show them in slow-motion.

Geändert von DaCoda (12. Mai 2024 um 09:05 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:34 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