![]() |
Vollständige Sichtbarkeit eines Forms
Moin, Moin.
Ich arbeite abwechselnd mit einem Notebook und einem PC(mit 2 Monitoren). Da hat es genervt, dass die Wiederherstellung der letzten Fensterposition beim Wechsel von PC auf Notebook immer problematisch war - das hat ja nun mal leider keine 2 Bildschirme eingebaut :( Nun habe ich mich mal an einer endgültige Problemlösung versucht. Das Ergebnis sorgt nach erstem Test dafür, dass das Programmfenster vollständig sichtbar angezeigt wird, auch wenn aus der INI-Datei Koordinaten zur Positionierung gelesen wurden, mit der das Fenster in der aktuellen Monitorumgebung eigentlich nicht oder nicht vollständig sichtbar dargestellt werden könnte. 1 - Auf welchem Monitor wird Form dargestellt? Ermittelt, auf welchem Monitor das Form angezeigt wird. Bildet das Form auf Multi-Monitorsystemen Schnittflächen mit mehreren Monitoren, wird derjenige Monitor zurückgeliefert, der die größte Schnittfläche mit dem Form hat. Ist das Form aufgrund einer völlig abweichenden Monitorkonfiguration auf keinem aktuell verfügbaren Monitor sichtbar, wird als Ergebnis der Primärmonitor zurückgeliefert.
Delphi-Quellcode:
2 - Ist Form auf Monitor vollständig sichtbar?
function GetCurrentMonitor(Form:TForm):Integer;
var Rect : TRect; i,A,maxA : Integer; begin Result:=0; maxA :=0; for i:=0 to Screen.MonitorCount-1 do if IntersectRect(Rect,Screen.Monitors[i].BoundsRect,Form.BoundsRect) then begin A:=(Rect.Right-Rect.Left)*(Rect.Bottom-Rect.Top); if A>maxA then begin maxA :=A; Result:=i; end end end; Die Funktion prüft, ob das übergebene Form aktuell vollständig angezeigt wird.
Delphi-Quellcode:
3 - Vollständige Anzeige des Forms erzwingen
function FormFullInView(Form:TForm):Boolean;
var MonNo, MonL,MonW, MonT,MonH : Integer; begin MonNo:=GetCurrentMonitor(Form); MonL :=Screen.Monitors[MonNo].Left; MonW :=Screen.Monitors[MonNo].Width; MonT :=Screen.Monitors[MonNo].Top; MonH :=Screen.Monitors[MonNo].Height; Result:=(Form.Left >=MonL) and (Form.Top >=MonT) and (Form.Left+Form.Width <=MonL+MonW) and (Form.Top +Form.Height<=MonT+MonH) end; Die Prozedur erzwingt die vollständige Anzeige (zentriert) des Forms auf dem Monitor der mit dem Formular die größte Schnittfläche besitzt. Hat das Form in der aktuellen Konfiguration mit keinem vorhandenen Monitor eine Schnittfläche, wird der primäre Monitor verwendet. Der Aufruf kann (natürlich) erst erfolgen, nachdem Left, Top, Width und Height des Forms festgelegt wurden.
Delphi-Quellcode:
Nach Setzen der in der INI-Datei gespeicherten letzten Fensterkoordinaten wird die zuletzt gezeigte Prozedur aufgerufen. Damit wird dann sichergestellt, dass das Form unter jeder Monitorkonfiguration immer vollständig angezeigt wird - hoffe ich jedenfalls :mrgreen:
procedure FitFormFullInView(Form:TForm);
var MonNo, MonL,MonW, MonT,MonH : Integer; begin if not(FormFullInView(Form)) then begin MonNo:=GetCurrentMonitor(Form); MonL :=Screen.Monitors[MonNo].Left; MonW :=Screen.Monitors[MonNo].Width; MonT :=Screen.Monitors[MonNo].Top; MonH :=Screen.Monitors[MonNo].Height; with Form do begin Left:=MonL+(MonW-Width ) div 2; Top :=MonT+(MonH-Height) div 2; end end end; Warum poste ich das Ganze nun? Ich würde das gern noch mal von einer weiteren Person testen lassen. Vielleicht gibt es sogar in der DP-Gemeinde ein Mitglied mit 3, 4 oder noch mehr Monitoren. // edit : Rechtschreibfehler beseitigt |
Re: Vollständige Sichtbarkeit eines Forms
Oh das werde ich gleich morgen früh mal ausprobieren, ich hab nämlich gerade das Phänomen dass meine App mit XP-Manifest zwar im Modus "maximiert" auf dem Bildschirm erscheint, aber trotzdem deutlich kleiner als der Bildschirm ist. Erst zweimaliges Klicken aufs Border Icon maximiert die Applikation dann korrekt (grummel!) - ohne XP-Manifest klappts. Mal sehen ob Dein Ansatz da Abhilfe schafft :)
[edit=Phoenix]Text wiedergeholt.. Mfg, Phoenix[/edit] |
Re: Vollständige Sichtbarkeit eines Forms
Moin, Moin.
Gibt's hier im Forum kein Mitglied, das mehr als zwei Monitore hat und das mal testen kann? |
Re: Vollständige Sichtbarkeit eines Forms
Also ich hab leider keinen 2. Monitor, aber ich hab deine Funktionen im Kopf überprüft und würde sagen: Daumen hoch, sieht sehr gut aus.
GetCurrentMonitor ist piffig gelöst. Vielleicht statt TForm die Klasse TCustomForm verwenden. FitFormFullInView könnte man vielleicht besser lösen. Sobald ein Form die Monitorfläche um ein Pixel verlässt, wird es in x- und y-Richtung zentriert. Es würde aber reichen, das Form nur soweit zu verschieben, bis es nirgends mehr übersteht. Also 1.) GetCurrentMonitor aufrufen 2.) ermitteln, um wieviele Pixel das Form in x- und/oder y-Richtung übersteht 3.) Form um genau diese x/y-Beträge so verschieben, dass es vollständig im Monitor ist. Ich würde dazu nicht FormFullInView aufrufen, sondern gleich in die Rechnung einsteigen. |
Re: Vollständige Sichtbarkeit eines Forms
Vielen Dank für den Check :hi:
- TCustomForm werde ich ändern, - den zweiten Punkt erst einmal mal in der Praxis austesten. Hatte das Zentrieren gewählt, damit besonders deutlich wird, dass das Form vom Programm abweichend von der letzten Position neu positioniert wurde |
Re: Vollständige Sichtbarkeit eines Forms
Hi taaktaak,
Zitat:
Ich habe es eben mit 2 Monitoren in unterschiedlicher Anordnung getestet (1,2 / 2,1). Ich sehe auf Anhieb zwei Probleme: 1) Du berücksichtigest bei einem Resize nicht die Höhe der Taskbar und auf welchem der Monitore diese ist. WorkareaRect wäre hier der richtige Ansatz. 2) Was ist, wenn ein Benutzer wirklich das Form über mehrere Monitore vergrößern will? Es gibt ja auch Multimonitorsysteme ohne Displayrahmen, die zusammen einen großen Desktop ergeben. Dabei würde Deine Lösung immer auf einen einzelnen Monitor verkleinern. Zitat:
Ich habe gerade genau das gleiche Problem und sitze in Griffweite eines Multimonitorsystems... Ist das für Dich noch aktuell? Gruß Assertor |
Re: Vollständige Sichtbarkeit eines Forms
So,
hier mal ein Lösungsansatz für die angesprochenen Probleme: Damit erledigt FitFormFullInView zusammen mit seinen Hilfsfunktionen die folgenden Aufgaben (für Einzel- oder Multi-Monitor):
Delphi-Quellcode:
Im Ergebnis finde ich die Zentrierung auch besser.
function GetCurrentMonitor(AForm: TCustomForm): Integer;
var Rect: TRect; i, A, maxA: Integer; begin { man kann sich diese Funktion auch sparen und einfach AForm.Monitor aufrufen, wobei diese u.U. nicht so gründlich und schön auf die Maximalnutzung prüft } Result := 0; maxA := 0; for i := 0 to Screen.MonitorCount-1 do if IntersectRect(Rect, Screen.Monitors[i].BoundsRect, AForm.BoundsRect) then begin A := (Rect.Right-Rect.Left) * (Rect.Bottom-Rect.Top); if A > maxA then begin maxA := A; Result:=i; end; end; end; function FormFullInView(AForm: TCustomForm): Boolean; var MonNo, MonL, MonW, MonT, MonH: Integer; begin MonNo := GetCurrentMonitor(AForm); MonL := Screen.Monitors[MonNo].WorkareaRect.Left; MonW := Screen.Monitors[MonNo].WorkareaRect.Right - Screen.Monitors[MonNo].WorkareaRect.Left; MonT := Screen.Monitors[MonNo].WorkareaRect.Top; MonH := Screen.Monitors[MonNo].WorkareaRect.Bottom - Screen.Monitors[MonNo].WorkareaRect.Top; // handle multi-monitor windows if (AForm.Left >= Screen.DesktopLeft) and (AForm.Top >= Screen.DesktopTop) and ((AForm.Left + AForm.Width) <= (Screen.DesktopWidth + Screen.DesktopLeft)) and ((AForm.Top + AForm.Height) <= (Screen.DesktopHeight + Screen.DesktopTop)) then Result := True else Result:= (AForm.Left >= MonL) and (AForm.Top >= MonT) and (AForm.Left + AForm.Width <= MonL + MonW) and (AForm.Top + AForm.Height <= MonT + MonH); end; procedure FitFormFullInView(AForm: TCustomForm); var MonNo, MonL, MonW, MonT, MonH: Integer; begin if not (FormFullInView(AForm)) then begin MonNo := GetCurrentMonitor(AForm); MonL := Screen.Monitors[MonNo].WorkareaRect.Left; MonW := Screen.Monitors[MonNo].WorkareaRect.Right - Screen.Monitors[MonNo].WorkareaRect.Left; MonT := Screen.Monitors[MonNo].WorkareaRect.Top; MonH := Screen.Monitors[MonNo].WorkareaRect.Bottom - Screen.Monitors[MonNo].WorkareaRect.Top; with AForm do begin if Height > MonH then Height := MonH; if Width > MonW then Width := MonW; Left := MonL + (MonW-Width) div 2; Top := MonT + (MonH-Height) div 2; end; end; end; Nützlich ist die Funktion, wenn z.B. 1) ein Anwender seinen Monitor / seine Grafikkarte durch ein Modell mit anderer Standard-Auflösung ersetzt und ein Programm dann mit diesen neuen Einstellungen klar kommen muß oder 2) eine Anwendung mit Einstellungen für einen Multimonitor-PC z.B. auf einem USB-Stick mobil am Notebook eingesetzt wird. Gruß Assertor |
Re: Vollständige Sichtbarkeit eines Forms
Hi,
beim From die "Position" auf "poScreenCenter" stellen. Dann wirds auch sauber ausgerichtet. Gruss |
Re: Vollständige Sichtbarkeit eines Forms
Hi,
Zitat:
Warum also der Post :?: Gruß Assertor |
Re: Vollständige Sichtbarkeit eines Forms
Moin, Moin.
... weil ich sonst gar nicht mitbekommen hätte, dass Assertor meinen Code verbessert hast. Prima! Werde allerdings die Funktionalität Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:56 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