AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Fensterposition zurücksetzen

Ein Thema von haentschman · begonnen am 19. Feb 2020 · letzter Beitrag vom 9. Jun 2020
Antwort Antwort
Seite 1 von 3  1 23      
Benutzerbild von haentschman
haentschman

Registriert seit: 24. Okt 2006
Ort: Seifhennersdorf / Sachsen
5.388 Beiträge
 
Delphi 12 Athens
 
#1

Fensterposition zurücksetzen

  Alt 19. Feb 2020, 10:07
Hallöle...

Nur aus Interesse. Unsere Anwendung speichert die Positionen der einzelnen Fenster. Soweit so gut.

Geht der Mitarbeiter an einen anderen Platz, wo die Monitore vertauscht sind, ist ggf. das Fenster nicht sichtbar. (Position außerhalb des Desktops)
Ich habe mir selbst eine simple Logik dafür implementiert. Die Frage ist, gibt es was vom System, um das Fenster in den sichtbaren Bereich zu bringen?

Diskussion eröffnet...
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Fensterposition zurücksetzen

  Alt 19. Feb 2020, 10:13
MakeFullyVisible
MakeFullyVisible

So etwas eventuell? Keine Ahnung ob es das jetzt noch gibt?
Gruß vom KodeZwerg
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.475 Beiträge
 
Delphi 12 Athens
 
#3

AW: Fensterposition zurücksetzen

  Alt 19. Feb 2020, 10:17
Gibt es: Vcl.Forms.TCustomForm.MakeFullyVisible
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von haentschman
haentschman

Registriert seit: 24. Okt 2006
Ort: Seifhennersdorf / Sachsen
5.388 Beiträge
 
Delphi 12 Athens
 
#4

AW: Fensterposition zurücksetzen

  Alt 19. Feb 2020, 11:08
Danke...

Man lernt nicht aus. Ich habe meine Logic ausgetauscht.

Delphi-Quellcode:
procedure TfoBase.RestoreForm(Name: string);
var
  Desktop: TRect;
begin
  FIniPath := FFolders.Items[ftPositionFolder] + Name; // wiederverwendbar für Save
  prsBase.StorageName := FIniPath;
  prsBase.RestoreFrom;

  // wieder einblenden
  if Self.WindowState = wsMinimized then
  begin
    Self.WindowState := wsNormal;
  end;

  // Prüfung ob im Desktop
  Desktop := Screen.DesktopRect;
  if Self.Left < Desktop.Left then
  begin
    Self.MakeFullyVisible(Screen.Monitors[0]);
  end;
  if Self.Left > Desktop.Width then
  begin
    Self.MakeFullyVisible(Screen.Monitors[Screen.MonitorCount - 1]);
  end;

  SaveForm;
end;
  Mit Zitat antworten Zitat
Benutzerbild von uligerhardt
uligerhardt

Registriert seit: 19. Aug 2004
Ort: Hof/Saale
1.746 Beiträge
 
Delphi 2007 Professional
 
#5

AW: Fensterposition zurücksetzen

  Alt 19. Feb 2020, 11:23
Du könntest auch MSDN-Library durchsuchenSetWindowPlacement & Co. verwenden. Das sorgt automatisch dafür, dass das Fenster nicht komplett verschwindet.
Uli Gerhardt
  Mit Zitat antworten Zitat
TigerLilly

Registriert seit: 24. Mai 2017
Ort: Wien, Österreich
1.211 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Fensterposition zurücksetzen

  Alt 21. Feb 2020, 10:01
Gibt es MakeFullyVisible nur für die VCL? Nicht FMX?
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.475 Beiträge
 
Delphi 12 Athens
 
#7

AW: Fensterposition zurücksetzen

  Alt 21. Feb 2020, 10:56
Das ist leider so.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
TigerLilly

Registriert seit: 24. Mai 2017
Ort: Wien, Österreich
1.211 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: Fensterposition zurücksetzen

  Alt 21. Feb 2020, 11:19
Ja, ich hab grad im Source nachgesehen. Für FMX ist das wohl aufwändiger, weil die plattformspezifischen Dienste ins Spiel kommen.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#9

AW: Fensterposition zurücksetzen

  Alt 21. Feb 2020, 11:54
Hatte das vorher nicht gekannt und mir sowas selbst gebaut.

Ist jetzt kein Hexenwerk ... einfach gucken ob Form in einem Monitor liegt und wenn nicht, dann die Werte anpassen.
Und dabei lassen sich dann auch sondefälle behandeln.

Ist jetzt auch VCL, aber lässt sich bestimmt leicht anpassen, wenn es dort sowas wie Screens gibt. (Vcl.Forms.Screens, Vcl.Forms.Application, usw. auf Fmx.Forms stellen)

Wobei, für Android/iOS kann man es ignoeieren, wenn/da dort alle Fenster Vollbild sind und bei Anschluß eines externen Monitors der Screen nur gespiegelt wird.
Und wenn nicht, dann kann man Android/iOS zumindestens fragen wie groß der "eine" Screen ist und das als WorkArea nutzen, oder einfach die Position seiner Hauptform verwenden, die Vollbild ist und daher weiß so sie liegt.
Brauchst also nur noch was für MAC und Linux kannst'e mit FMX eh vergessen.

WorkArea = das ohne Taskleiste und andere AppBars

Delphi-Quellcode:
procedure CorrectWindowPosition(Form: TForm);
begin
  if Form.WindowState <> wsNormal then
    Exit;

  Monitor := Form.Monitor;
  if not Assigned(Monitor) then
    Monitor := Application.MainForm.Monitor;
  
  if Form.Width > RectWidth(Monitor.WorkareaRect) then
    Form.Width := RectWidth(Monitor.WorkareaRect);
  if Form.Height > RectHeight(Monitor.WorkareaRect) then
    Form.Height := RectHeight(Monitor.WorkareaRect);

  if Form.Left < Monitor.WorkareaRect.Left then
    Form.Left := Monitor.WorkareaRect.Left;
  if Form.Top < Monitor.WorkareaRect.Top then
    Form.Top := Monitor.WorkareaRect.Top;

  if Form.Left + Form.Width >= Monitor.WorkareaRect.Right then
    Form.Left := Monitor.WorkareaRect.Right - Form.Width;
  if Top + Form.Height >= Monitor.WorkareaRect.Bottom then
    Form.Top := Monitor.WorkareaRect.Bottom - Form.Height;
end;
Für RectWidth/RectHeight gibt es inzwischen einen ClassHelper mit Property Width/Height.

Dann noch paar Optimierungen, wie z.B. die Größe/Position nicht schrittweise anzupassen, sondern das nur einmal zuzuweisen.
Delphi-Quellcode:
procedure CorrectWindowPosition(Form: TForm; Monitor: TMonitor = nil);
var
  R: TRect;
  Left, Top, Width, Height: Integer;
begin
  if Form.WindowState <> wsNormal then
    Exit;

  Left := Form.Left;
  Top := Form.Top;
  Width := Form.Width;
  Height := Form.Height;

  if not Assigned(Monitor) then begin
    Monitor := Screen.MonitorFromRect(Bounds(Left, Top, Width, Height)); //Monitor := Form.Monitor; aber falls Form noch nicht sichtbar war...
    if not Assigned(Monitor) then
      Monitor := Application.MainForm.Monitor;
  end;
  R := Monitor.WorkareaRect;

  if Width > RectWidth(R) then
    Width := RectWidth(R);
  if Height > RectHeight(R) then
    Height := RectHeight(R);

  if Left < R.Left then
    Left := R.Left;
  if Top < R.Top then
    Top := R.Top;

  if Left + Width >= R.Right then
    Left := R.Right - Width;
  if Top + Height >= R.Bottom then
    Top := R.Bottom - Height;

  if not EqualRect(Form.BoundsRect, Bounds(Left, Top, Width, Height)) then
    Form.BoundsRect := Bounds(Left, Top, Width, Height);
end;
Nun noch paar "persönliche" Sonderfälle rein, die MakeFullyVisible natürlich nicht wissen kann.
Und hier kann es auch eine Form auf dem "ganzen" Desktop sein, bzw. die über mehrere Monitore geht.
Delphi-Quellcode:
const
  ScreenOverDesktop = TMonitor(1); // Multimonitor: über gesamten Desktop
  ScreenOverMonitor = TMonitor(0); // über einen einzelnen Monitor

procedure CorrectWindowPosition(Form: TForm; Monitor: TMonitor = ScreenOverMonitor);
var
  R: TRect;
  W20, H33, FormGlassFrameWidth: Integer;
  Left, Top, Width, Height: Integer;
begin
  if Form.WindowState <> wsNormal then
    Exit;

  Left := Form.Left;
  Top := Form.Top;
  Width := Form.Width;
  Height := Form.Height;
  W20 := Form.Width div 5; // darf bis zu 20% links oder rechts überstehen
  H33 := Form.Height div 3; // darf bis zu 33% unten überstehen

  {$REGION 'SETFORMPOS: Toolform ausrichten wenn Modulform verschoben wurde'}
  if Form.ClassNameIs('TToolForm') and (Form.Owner is TForm) then begin
    W20 := 0;
    H33 := 0;
    FormGlassFrameWidth := 4;
    if not NoNewCommonControls then // WinXP schmalere Ränder
      FormGlassFrameWidth := 8;
    if ((Form.Owner as TForm).BorderStyle in [bsToolWindow, bsSizeToolWin]) or ((TForm(Form.Owner).FormStyle = fsNormal) and (TForm(Form.Owner).BorderStyle in [bsSizeable, bsDialog])) then
      FormGlassFrameWidth := FormGlassFrameWidth - IfThen(NoNewCommonControls, 3, 5);

    if Form.Parent = Application.MainForm then begin //FormStyle=fsMDIChild
      Left := Max(Max(TFormAccsess(Form.Owner).GetClientOrigin.X - 34, Application.MainForm.Left - 30) - Application.MainForm.Left - FormGlassFrameWidth, 0);
      Top := Max( TFormAccsess(Form.Owner).GetClientOrigin.Y, Application.MainForm.Top) - Application.MainForm.Top;
    end else begin
      Left := TForm(Form.Owner).Left - 24 - FormGlassFrameWidth;
      Top := TForm(Form.Owner).Top + 20;
    end;
  end;
  {$ENDREGION}

  if Form.FormStyle = fsMDIChild then begin
    R := Application.MainForm.ClientRect;
    Dec(R.Bottom, RibbonHeight); // MainForm.RibbonMain.Height (Top/Left ist verschoben)
    Dec(R.Right, 25); // MainForm.PanelLeft.Width
    { TODO : alternativ alle Komponenten, mit Align <> alNone und alClient, von R abrechnen}
  end else if Assigned(Form.Parent) then
    R := Form.Parent.ClientRect
  else if Monitor = ScreenOverDesktop then begin
    // Bugfix: Fenster über mehrere Monitore http://redmine.prodat-sql.de/issues/5855
    { TODO : Schwarze Bereiche, bei unterschiedlich großen oder verschobenen Monitoren, werden nicht beachtet }
    R := Screen.DesktopRect;
  end else begin
    //R := Screen.MonitorFromRect(Form.Monitor.BoundsRect, mdNearest).WorkareaRect;
    if not Assigned(Monitor) then begin
      Monitor := Screen.MonitorFromRect(Bounds(Left, Top, Width, Height)); //Monitor := Form.Monitor;
      if not Assigned(Monitor) then
        Monitor := Application.MainForm.Monitor;
    end;
    R := Monitor.WorkareaRect;
  end;

  {$REGION 'SETFORMPOS: Fensterposition prüfen und anpassen'}
  if Width > RectWidth(R) then
    Width := RectWidth(R);
  if Height > RectHeight(R) then
    Height := RectHeight(R);

  if Left + W20 < R.Left then
    Left := R.Left;
  if Top {+ H33} < R.Top then
    Top := R.Top;

  if Left + Width - W20 > R.Right then
    Left := R.Right - Width;
  if Top + Height - H33 > R.Bottom then
    Top := R.Bottom - Height;
  {$ENDREGION}

  if not EqualRect(Form.BoundsRect, Bounds(Left, Top, Width, Height)) then begin
    Form.BoundsRect := Bounds(Left, Top, Width, Height); // Form.Left/Top/Width/Height := ...
    ProcessDrawMessages(False);
  end;
end;
$2B or not $2B

Geändert von himitsu (21. Feb 2020 um 12:05 Uhr)
  Mit Zitat antworten Zitat
DieDolly

Registriert seit: 22. Jun 2018
2.175 Beiträge
 
#10

AW: Fensterposition zurücksetzen

  Alt 22. Feb 2020, 11:02
Zitat:
Gibt es MakeFullyVisible nur für die VCL? Nicht FMX?
Wenn das Fenster nicht sichtbar ist, setzt man es einfach auf den ersten Monitor. Dafür braucht man keine großartigen Funktionen mit tollen Namen, die es nur für VCL aber nicht FMX gibt.

Delphi-Quellcode:
if (Screen.MonitorFromWindow(AForm.Handle, mdNull) = nil) and (Screen.MonitorCount > 0) then
 begin
  // AForm.Top := (Screen.Monitors[0].Height - AForm.Height) div 2;
  // AForm.Left := (Screen.Monitors[0].Width - AForm.Width) div 2;
 end;
Und falls es MonitorFromWindow für FMX nicht gibt, dann haben die FMX-Leute eben Pech gehabt

Geändert von DieDolly (22. Feb 2020 um 14:46 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


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 11:33 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz