![]() |
Fensterposition zurücksetzen
Hallöle...:P
Nur aus Interesse. Unsere Anwendung speichert die Positionen der einzelnen Fenster. Soweit so gut. :wink: 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? :wink: Diskussion eröffnet... :wink: |
AW: Fensterposition zurücksetzen
|
AW: Fensterposition zurücksetzen
|
AW: Fensterposition zurücksetzen
Danke... :P
Man lernt nicht aus. Ich habe meine Logic ausgetauscht. :thumb:
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; |
AW: Fensterposition zurücksetzen
Du könntest auch
![]() |
AW: Fensterposition zurücksetzen
Gibt es MakeFullyVisible nur für die VCL? Nicht FMX?
|
AW: Fensterposition zurücksetzen
Das ist leider so.
|
AW: Fensterposition zurücksetzen
Ja, ich hab grad im Source nachgesehen. Für FMX ist das wohl aufwändiger, weil die plattformspezifischen Dienste ins Spiel kommen.
|
AW: Fensterposition zurücksetzen
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:
Für RectWidth/RectHeight gibt es inzwischen einen ClassHelper mit Property Width/Height.
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; Dann noch paar Optimierungen, wie z.B. die Größe/Position nicht schrittweise anzupassen, sondern das nur einmal zuzuweisen.
Delphi-Quellcode:
Nun noch paar "persönliche" Sonderfälle rein, die MakeFullyVisible natürlich nicht wissen kann.
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; 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; |
AW: Fensterposition zurücksetzen
Zitat:
Delphi-Quellcode:
Und falls es MonitorFromWindow für FMX nicht gibt, dann haben die FMX-Leute eben Pech gehabt ;)
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; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:29 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