Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi MonitorCount im Betrieb aktualisieren? (https://www.delphipraxis.net/158798-monitorcount-im-betrieb-aktualisieren.html)

Rabe 3. Mär 2011 14:09

MonitorCount im Betrieb aktualisieren?
 
Hi all,

ich schreibe einen PDF-Presenter. Die PDF soll natürlich auf einem Beamer angezeigt werden - die Steuerung am Liebsten auf einem separatem Monitor.

Das funktioniert sowohl im 1-Monitor(nur Beamer)- als auch im 2-Monitor(Monitor + Beamer)-Betrieb.

ABER - wird der Beamer nach Start des Präsenters an- oder abgestöpselt, so wird diese Änderung nicht registriert. Screen.MonitorCount bleibt auf dem Initialisierungswert.

Wie kann ich vor dem form.show des Beamer-Bildschirms Screen.MonitorCount "aktualisieren" lassen?

Viele Grüße
RaBe...

s.h.a.r.k 3. Mär 2011 14:16

AW: MonitorCount im Betrieb aktualisieren?
 
Das hier steckt hinter der Getter-Methode von Screen.MonitorCount:
Delphi-Quellcode:
function TScreen.GetMonitorCount: Integer;
begin
  if FMonitors.Count = 0 then
    Result := GetSystemMetrics(SM_CMONITORS)
  else
    Result := FMonitors.Count;
end;

Memnarch 3. Mär 2011 15:32

AW: MonitorCount im Betrieb aktualisieren?
 
Schlag mich, aber bedeutet der getetr nicht, das FMonitors.count nach einem frischen auslesen nicht gesetzt wird o.O. Dan bleibt FMonitors.count ja 0.(Also nur erste IF)

MFG
Memnarch

DeddyH 3. Mär 2011 15:36

AW: MonitorCount im Betrieb aktualisieren?
 
Wenn der Getter zum ersten Mal aufgerufen wird, fragt er beim OS nach, danach gibt er diese ermittelte Zahl bei jedem weiteren Aufruf zurück.

Memnarch 3. Mär 2011 15:39

AW: MonitorCount im Betrieb aktualisieren?
 
Also wird die Variable, die der Getter zurückgibt, automatisch in dem ihm zugehörigen Feld gespeichert?

DeddyH 3. Mär 2011 15:44

AW: MonitorCount im Betrieb aktualisieren?
 
Ich habe leider gerade kein Delphi zur Hand, weiß daher nicht, wie, wann und wie oft FMonitors befüllt bzw. refreshed wird. Laut Beschreibung im Ausgangspost scheint es aber so zu sein, dass das nur einmal geschieht.

Memnarch 3. Mär 2011 15:48

AW: MonitorCount im Betrieb aktualisieren?
 
Die frage ist nicht wie OFT, sondern WO. Der getter gibt in meinen augen nur die Anfrage zurück, schreibt das Ergebnis aber fürs nächste mal(zweite if anweisung wäre dass) nicht in die Feldvariable. Die Feldvariable selbst müsste also 0 bleiben(wird dann auch nie zurückgegeben) Muss ich mal eben testen wie sich das verhält o.O.


MFG
Memnarch

s.h.a.r.k 3. Mär 2011 15:51

AW: MonitorCount im Betrieb aktualisieren?
 
Jup. Der Wert wird somit nur einmal via Windows-API-Call ausgelesen und intern gespeichert. Das Problem dabei ist, dass wenn während der Laufzeit des Programms sich die Anzahl der Monitore ändert, der Wert falsch ist und falsch bleibt.

Hab hier totalen Käse geschrieben. Die Zeile mit der Windows-API-Aufruf ist nur eine Fallback-Methode, wenn beim Konstrutor von TScreen das hier wohl nicht geklappt hat:
Delphi-Quellcode:
{$IF DEFINED(CLR)}
  EnumDisplayMonitors(0, nil, TMonitorEnumerator.Create(FMonitors).FEnumProc, 0);
{$ELSE}
  EnumDisplayMonitors(0, nil, @EnumMonitorsProc, LongInt(FMonitors));
{$IFEND}
FMonitors ist vom Typ TList und beinhaltet TMonitor-Instanzen. TMonitorEnumerator ist eine "Hilfs"-Klasse mit einer Callback-Methode, die von der Windows-API aufgerufen wird, eine TMonitor-Instanz erzeugt und diese in FMonitors wirft.

shmia 3. Mär 2011 15:57

AW: MonitorCount im Betrieb aktualisieren?
 
In der Klasse TCustomForm habe ich etwas Code aufgespürt, wie die VCL auf Veränderungen der Monitore reagiert:

Delphi-Quellcode:
for i := 0 to Screen.MonitorCount-1 do
    TMonitor(Screen.FMonitors[i]).Free;
Screen.FMonitors.Clear;
// EnumDisplayMonitors ist ein Funktionszeiger in Unit MultiMon
EnumDisplayMonitors(0, nil, @EnumMonitorsProc, LongInt(Screen.FMonitors));
Das ist natürlich sehr unfein, was da in
Delphi-Quellcode:
function TCustomForm.GetMonitor
gemacht wird.
Borland hätte der TScreen-Klasse eine "RefreshMonitors"-Methode spendieren sollen.

PS: Ahhh..es fehlt natürlich auch noch lokaler Code aus Unit Forms:
Delphi-Quellcode:
function EnumMonitorsProc(hm: HMONITOR; dc: HDC; r: PRect; Data: Pointer): Boolean; stdcall;
var
  L: TList;
  M: TMonitor;
begin
  L := TList(Data);
  M := TMonitor.Create;
  M.FHandle := hm;
  M.FMonitorNum := L.Count;
  L.Add(M);
  Result := True;
end;

Memnarch 3. Mär 2011 15:58

AW: MonitorCount im Betrieb aktualisieren?
 
@Shark:Okay, das heißt aber, das die variable erst gegetted wird, und dan manuel gespeichert wird(z.B im Create()). Automatisch wird da zumindest nichts gespeichert.

MFG
Memnarch

HeikoAdams 3. Mär 2011 15:59

AW: MonitorCount im Betrieb aktualisieren?
 
ohne es getestet zu haben, dürfte die sauberste Methode sein, eine neue Klasse von TScreen abzuleiten und diese neue Klasse um eine Refresh-Methode zu erweitern.

s.h.a.r.k 3. Mär 2011 16:00

AW: MonitorCount im Betrieb aktualisieren?
 
Nochmal mein Edit oben lesen! Oder einfach das von shmia lesen. Mein VCL-Source ist nur etwas neuer als der von shmia ;)

Rabe 4. Mär 2011 16:24

AW: MonitorCount im Betrieb aktualisieren?
 
Mit den Anregungen hier bin ich mal auf Endeckungsreise gegangen und habe an unterschiedlichen Stellen ind forms.pas den Aufruf von "Screen.GetMonitors" entdeckt.

Code:
procedure TScreen.GetMonitors;
begin
  ClearMonitors;
{$IF DEFINED(CLR)}
                                         
  EnumDisplayMonitors(0, nil, TMonitorEnumerator.Create(Screen.FMonitors).FEnumProc, 0);
{$ELSE}
  EnumDisplayMonitors(0, nil, @EnumMonitorsProc, LongInt(Screen.FMonitors));
{$IFEND}
end;
Ich würde das für eine Art "Refresh" halten. Aber - die Methode ist private.

Jetzt wollte ich TScreen in forms.pas um eine öffentliche Methode ergänzen, die GetMonitors aufruft. Es ist mir fast perinlich aber ich bekomme forms.pas nicht übersetzt.

Kann mir mal kurz einer nen Schubs geben? Müsste forms.pas als Bestandteil des Projektes nach Veränderung nicht automatisch übersetzt werden??? In jedem Fall ist forms.pas in dem im Optionen.Suchpfad eingetragegen Verzeichnis $(BDS)\SOURCE\WIN32\VCL vorhanden und lesbar.

Gruß
RaBe


Ups: Posts auf 2. Seite nicht gesehen - pfui über mich.

himitsu 4. Mär 2011 16:59

AW: MonitorCount im Betrieb aktualisieren?
 
Die VCL Resourcen ändert man halt nicht.

Delphi nutzt nie die PAS, sondern die entsprechenden vorkompilierten DCUs oder die Units, welche in den BPLs liegen, wenn man Runtimepackages nutzt.

Wenn doch, dann muß man diese DCUs manuell kompilieren und die abhängigen BPLs neu erzeugen.



Delphi-Quellcode:
Screen.FindMonitor(0);
führt einen Refresh durch ... man mag es kaum glauben. :lol:

Rabe 4. Mär 2011 17:25

AW: MonitorCount im Betrieb aktualisieren?
 
Zitat:

Zitat von himitsu (Beitrag 1085947)
Die VCL Resourcen ändert man halt nicht.

und man geht auch nicht bei rot über die Ampel ;-)

Zitat:

Zitat von himitsu (Beitrag 1085947)
Delphi-Quellcode:
Screen.FindMonitor(0);
führt einen Refresh durch ... man mag es kaum glauben. :lol:

ruft ja auch
Delphi-Quellcode:
Screen.GetMonitors
auf. Aber beide Methoden sind private deklariert.

Kann mich mal einer aufklären, wie ich da ran komme OHNE die VCL zu ändern?

Anscheinend sehe ich gerade den Wald vor Bäumen nicht...

himitsu 4. Mär 2011 18:04

AW: MonitorCount im Betrieb aktualisieren?
 
Ups, dann hatte ich mich vorhin verguckt. :shock:

OK, dann versuchen wir's einfach mal so
Delphi-Quellcode:
Screen.MonitorFromWindow(INVALID_HANDLE_VALUE, mdNull);
?

Rabe 4. Mär 2011 18:45

gelöst: MonitorCount im Betrieb aktualisieren
 
Zitat:

Zitat von himitsu (Beitrag 1085957)
OK, dann versuchen wir's einfach mal so
Delphi-Quellcode:
Screen.MonitorFromWindow(INVALID_HANDLE_VALUE, mdNull);

Ausgezeichnet - könnte besser nicht sein!

Im FormShow aufgerufen und danach wieder Mointorkonfiguration auswerten - schon wird das Formular für dem Beamer passgenau angezeigt, auch wenn der Beamer während der laufenden Anwendung an- oder abgestöpselt wird.

Viel Dank an Alle...

Gruß
RaBe

himitsu 4. Mär 2011 18:53

AW: gelöst: MonitorCount im Betrieb aktualisieren
 
Eigentlich dachte ich ja, daß auch dieses bei der INI/Settings-Change-Message mit aktualisiert wird.
Statt im OnShow kannste in Application.OnIniChange oder besser über diese TApplication-VCL-Komponente, auf eine Änderung reagieren, auch/vorallem wärend das Programm läuft.

Rabe 4. Mär 2011 19:01

AW: gelöst: MonitorCount im Betrieb aktualisieren
 
Zitat:

Zitat von himitsu (Beitrag 1085969)
besser über diese TApplication-VCL-Komponente, auf eine Änderung reagieren, auch/vorallem wärend das Programm läuft.

Die Anwendung wird wie PowerPoint eingesetzt. F5 = Präsentation starten, ESC = beenden. Ich gehe einfach davon aus, dass während einer laufenden Präsentation nicht am Beamer rumgefummelt wird. Die Situation ist eher die, dass beim Aufbau schon mal die Anwendung gestartet wird und mit F5 dann festgestellt wird, dass der Beamer nicht läuft (weil nicht angeschlossen).

Wenn dann der dann Beamer angeschlossen wird, kann ruhig mit ESC die "Testpräsentation" beendet und mit F5 neu gestartet werden. Das läuft meist schon intuitiv ab. Somit finde ich, dass es im FormShow bestens aufgehoben ist.

Wichtig ist nur, dass die Anwendung nicht beendet werden muss. Da kommt Otto-N nicht sooo schnell drauf ;-)

Gruß
RaBe

HeikoAdams 8. Mär 2011 08:09

AW: gelöst: MonitorCount im Betrieb aktualisieren
 
Zitat:

Zitat von Rabe (Beitrag 1085972)
Ich gehe einfach davon aus, dass während einer laufenden Präsentation nicht am Beamer rumgefummelt wird.

Unterschätze niemals Anwender. Die bringen Dinge fertig, auf die kommt man teilweise gar nicht :wall:


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:02 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