Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Vollständige Sichtbarkeit eines Forms (https://www.delphipraxis.net/111533-vollstaendige-sichtbarkeit-eines-forms.html)

taaktaak 4. Apr 2008 21:46


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:
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;
2 - Ist Form auf Monitor vollständig sichtbar?

Die Funktion prüft, ob das übergebene Form aktuell vollständig angezeigt wird.

Delphi-Quellcode:
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;
3 - Vollständige Anzeige des Forms erzwingen

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:
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;
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:

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

OldGrumpy 4. Apr 2008 22:14

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]

taaktaak 6. Apr 2008 15:53

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?

sx2008 6. Apr 2008 18:34

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.

taaktaak 6. Apr 2008 20:01

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

Assertor 21. Jun 2008 19:09

Re: Vollständige Sichtbarkeit eines Forms
 
Hi taaktaak,

Zitat:

Zitat von taaktaak
Ich würde das gern noch mal von einer weiteren Person testen lassen.

Etwas spät, aber hiermit getan ;)

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:

Zitat von taaktaak
- 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

Hast Du daran schon etwas verändert? Dieser Ansatz gefällt mir auch besser.

Ich habe gerade genau das gleiche Problem und sitze in Griffweite eines Multimonitorsystems... Ist das für Dich noch aktuell?

Gruß Assertor

Assertor 21. Jun 2008 22:42

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):
  • Wenn das Fenster in den gesamten Desktop passt, wird es unverändert gelassen (für gewünschte, große Multimonitor-Fenster)
  • Ist das Fenster zum Teil außerhalb des gültigen Gesamtdesktops, wird es auf dem Monitor mit dem größten Anteil zentriert angezeigt
  • Ist das Fenster vollständig außerhalb des gültigen Gesamtdesktops, wird es auf dem Primary-Monitor zentriert angezeigt
  • Ist das Fenster immer noch zu groß für den jeweiligen Monitor, wird es entsprechend in Höhe und Breite angepasst
  • Bei der Anpassung wird die Taskbar berücksichtigt (egal ob Links, Oben, Rechts, Unten)
Delphi-Quellcode:
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;
Im Ergebnis finde ich die Zentrierung auch besser.

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

sirarcher 9. Sep 2008 08:28

Re: Vollständige Sichtbarkeit eines Forms
 
Hi,

beim From die "Position" auf "poScreenCenter" stellen. Dann wirds auch sauber ausgerichtet.

Gruss

Assertor 9. Sep 2008 08:34

Re: Vollständige Sichtbarkeit eines Forms
 
Hi,

Zitat:

Zitat von sirarcher
beim From die "Position" auf "poScreenCenter" stellen. Dann wirds auch sauber ausgerichtet.

Ein fast 3 Monate alter Thread, den Du da auskramst... Aber Dein Vorschlag hilft nicht, da hier Zentrierung nur bei geänderten Monitorverhältnissen gewünscht ist. Die oben gepostete Lösung funktioniert doch einwandfrei...

Warum also der Post :?:

Gruß Assertor

taaktaak 9. Sep 2008 09:14

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:

Wenn das Fenster in den gesamten Desktop passt, wird es unverändert gelassen (für gewünschte, große Multimonitor-Fenster)
optional gestalten. Noch mal Danke für die Optimierung :hi:


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:26 Uhr.
Seite 1 von 2  1 2      

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