AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein GUI-Design mit VCL / FireMonkey / Common Controls Delphi Positionierung einer Form in Multimonitorumgebung
Thema durchsuchen
Ansicht
Themen-Optionen

Positionierung einer Form in Multimonitorumgebung

Ein Thema von Dalai · begonnen am 8. Aug 2015 · letzter Beitrag vom 16. Nov 2015
Antwort Antwort
delnu
(Gast)

n/a Beiträge
 
#1

AW: Positionierung einer Form in Multimonitorumgebung

  Alt 12. Nov 2015, 12:20
Weil es bei mir dasselbe Problem gibt, habe ich das aus dem letzten Beitrag mal ausprobiert, bekomme aber Fehlermeldungen.

procedure CenterOnMonitor(const AMonitor: TMonitor;
Da fehlt die Klammer vor dem Semikolon.

function GetMonitorOfParent(const AParent: HWND = 0): TMonitor;
procedure CenterOnMonitor(const AMonitor: TMonitor);

-> Ungenügende Forward- oder External-Deklaration.

Habe ich irgendwas übersehen?

Wenn ich das mit dem weiter vorne geposteten Quelltext kombiniere, gibt es andere Fehlermeldungen über fehlende "Bezeichner" :

in "GetMonitorOfParent" : MonitorFromWindow, mdNearest ( Result:= Screen.MonitorFromWindow(AParent, mdNearest); )
in "CenterOnMonitor" : WorkAreaRect, width und height ( Lrect:= AMonitor.WorkAreaRect; Lwidth:= Lrect.Width; Lheight:= Lrect.Height; )

Könntest Du bitte mal einen kompletten Quellcode eines (ansonsten leeren) Basisformulars veröffentlichen, bei dem der TC das Formular wirklich im gerade aktiven Fenster startet ?

Danke im Voraus.

Ach, ich sehe gerade bei dem älteren Beitrag "Hier ein Auszug (ohne die ganzen Ergänzungen für alte Delphis):"

Wie sehen diese "ganzen Ergänzungen" denn für Delphi 5 aus ?
  Mit Zitat antworten Zitat
Benutzerbild von Dalai
Dalai

Registriert seit: 9. Apr 2006
1.683 Beiträge
 
Delphi 5 Professional
 
#2

AW: Positionierung einer Form in Multimonitorumgebung

  Alt 12. Nov 2015, 13:38
Weil es bei mir dasselbe Problem gibt, habe ich das aus dem letzten Beitrag mal ausprobiert, bekomme aber Fehlermeldungen.

procedure CenterOnMonitor(const AMonitor: TMonitor;
Da fehlt die Klammer vor dem Semikolon.
Ja, sorry, das kommt von zuviel Copy'n'Paste meinerseits....

Zitat:
Könntest Du bitte mal einen kompletten Quellcode eines (ansonsten leeren) Basisformulars veröffentlichen, bei dem der TC das Formular wirklich im gerade aktiven Fenster startet ?
Sicher. Gestern habe ich daraus eine Klasse mit erweiterten Methoden gebastelt. Da das etwas mehr als nur ein paar Funktionen sind, hänge ich mal die komplette Unit an. Ich hoffe, da sind nicht allzu grobe Schnitzer drin .

Benutzung der Klasse dann z.B. so:
Delphi-Quellcode:
uses ..., TotalCmdGUI;

type
  TfmSvcProperties = class(TTotalCmdWfxForm)
   //[...]
  end;

implementation

procedure PluginShowForm(const AhParent: HWND);
var fmSvcProperties: TfmSvcProperties;
    Lmon: TFormMonitor;
begin
    fmSvcProperties:= TfmSvcProperties.Create(nil, AhParent);
    try
        case IniFile.Monitor of
          0..4: Lmon:= TFormMonitor(IniFile.Monitor);
          else Lmon:= fmActive;
        end;
        fmSvcProperties.ShowModal(Lmon);
    finally
        FreeAndNil(fmSvcProperties);
    end;
end;
Wenn du die Methode Init nicht brauchst, kannst du auch direkt von TFormEx ableiten (TTotalCmdWfxForm ist eh nur eine leere Hülle).

Zitat:
Wie sehen diese "ganzen Ergänzungen" denn für Delphi 5 aus ?
Hier geht's in erster Linie um Funktionen wie TMonitor.GetWorkareaRect, die nötig ist, um den Arbeitsbereich des jeweiligen Monitors zu ermitteln (statt einfach nur die volle Auflösung).

MfG Dalai
Angehängte Dateien
Dateityp: pas TotalCmdGUI.pas (7,1 KB, 11x aufgerufen)

Geändert von Dalai (12. Nov 2015 um 13:45 Uhr)
  Mit Zitat antworten Zitat
delnu
(Gast)

n/a Beiträge
 
#3

AW: Positionierung einer Form in Multimonitorumgebung

  Alt 13. Nov 2015, 01:04
zunächst fehlt hinter TfmSvcProperties = class(TTotalCmdWfxForm)ein Semikolon.

Unit "TotalCmdGUI" : {$Include Compiler.inc} habe ich keine ...

procedure PluginShowForm :

Delphi-Quellcode:
procedure PluginShowForm(const AhParent: HWND);
var fmSvcProperties: TfmSvcProperties;
    Lmon: TFormMonitor;
begin
    fmSvcProperties:= TfmSvcProperties.Create(nil, AhParent);
    try
        case IniFile.Monitor of
        // -> Undefinierter Bezeichner: 'IniFile'
        // -> ',' oder ':' erwartet, aber 'OF' gefunden
          0..4: Lmon:= TFormMonitor(IniFile.Monitor); // -> ')' erwartet, aber Bezeichner 'Monitor' gefunden
          else Lmon:= fmActive;
        end; // EXCEPT oder FINALLY erwartet
        fmSvcProperties.ShowModal(Lmon);
    finally // 'END' erwartet, aber 'FINALLY' gefunden
        FreeAndNil(fmSvcProperties);
    end; // '.' erwartet, aber ';' gefunden
end;


Aber mal noch was anderes:
Betrifft die Sache auch das Starten von Progs vom TC aus oder ist das nur speziell für TC-Plugins ?

Gehst Du in der Unit "TotalCmdGUI" von 4 Monitoren aus ? Soviel ich weiß, sind bis zu 9 möglich.

Die vorhandene Menge findet man über "Screen.MonitorCount"

Vor weit mehr als 10 Jahren hatte ich sogar mal was mit Delphi 1 gemacht, das immerhin schon 2 Monitore verwalten konnte. Dazu hatte ich wesentliche Teile der Unit "Multimon" in eine eigene Unit "MMM" gepackt. Der eigentliche Anlaß dazu war aber dies:

Die ab Delphi 4 standardmäßig vorhandene Multimonitor-Erkennung
wird nur beim Programmstart vorgenommen und verläßt sich später
fälschlich auf gültige "Handles", die nicht mehr stimmen, wenn
die Zahl der aktivierten Monitore während des Programm-Ablaufs
geändert wird. Werden Monitore abgeschaltet, so ist das weniger
dramatisch. Neu hinzukommende werden allerdings nicht erkannt !

Ich habe mal meine damalige Unit und ein einfachen Testprogramm kurz getestet, neu gespeichert und hier (nur Sourcen, keine EXE) angehängt. Vielleicht ist manches davon brauchbar, zumal es auch teilweise ab Delphi 1 funktioniert. Das Problem, auf welchem Monitor gestartet wird, hatte ich aber damit NICHT gelöst.

Könntest Du bitte mal ein KOMPLETTES und FUNKTIONIERENDES Beispiel Deiner Lösung bringen ?
Angehängte Dateien
Dateityp: zip MULTI_1.ZIP (11,4 KB, 7x aufgerufen)
  Mit Zitat antworten Zitat
Benutzerbild von Dalai
Dalai

Registriert seit: 9. Apr 2006
1.683 Beiträge
 
Delphi 5 Professional
 
#4

AW: Positionierung einer Form in Multimonitorumgebung

  Alt 13. Nov 2015, 02:19
zunächst fehlt hinter TfmSvcProperties = class(TTotalCmdWfxForm)ein Semikolon.
Nicht wirklich. Die Zeile darunter ist eine Platzhalterzeile, die noch mehr Sachen innerhalb der Klasse andeutet und durch das nachfolgende end; erst abgeschlossen wird.

Zitat:
Unit "TotalCmdGUI" : {$Include Compiler.inc} habe ich keine ...
Die kannst du dir notfalls selber bauen. Darin sind nur die verschiedenen Compiler-Versionen vermerkt mit entsprechenden $DEFINE s, damit der Compiler eine bedingte Kompilierung machen kann.

Zitat:
Delphi-Quellcode:
procedure PluginShowForm(const AhParent: HWND);
var fmSvcProperties: TfmSvcProperties;
    Lmon: TFormMonitor;
begin
    fmSvcProperties:= TfmSvcProperties.Create(nil, AhParent);
    try
        case IniFile.Monitor of
        // -> Undefinierter Bezeichner: 'IniFile'
        // -> ',' oder ':' erwartet, aber 'OF' gefunden
          0..4: Lmon:= TFormMonitor(IniFile.Monitor); // -> ')' erwartet, aber Bezeichner 'Monitor' gefunden
          else Lmon:= fmActive;
        end; // EXCEPT oder FINALLY erwartet
        fmSvcProperties.ShowModal(Lmon);
    finally // 'END' erwartet, aber 'FINALLY' gefunden
        FreeAndNil(fmSvcProperties);
    end; // '.' erwartet, aber ';' gefunden
end;
Alles Folgefehler des einen, kein Grund schockiert zu sein. Ein bisschen mitdenken musst du schon. IniFile.Monitor ist ein simpler Integer, wie man leicht an der Case-Bedingung erkennen kann. Einfach dort deine eigene Variable einfügen. Oder den Integer komplett weglassen und ShowModal direkt mit TFormMonitor.irgendwas als Parameter aufrufen.

Zitat:
Aber mal noch was anderes:
Betrifft die Sache auch das Starten von Progs vom TC aus oder ist das nur speziell für TC-Plugins ?
Mir geht es ausschließlich um TC-Plugins, konkret um Dateisystemplugins. Prinzipiell kann man diese Unit aber auch für andere, ganz normale Delphi-Programme benutzen, sofern man die Form nur auf einen bestimmten Monitor bringen und dort zentrieren will. In dem Bereich ist der Nutzen aber eh etwas eingeschränkt, weil es ja noch TForm.DefaultMonitor gibt, auch wenn das auch nicht alles kann.

Wobei es bei eigenständigen Programmen eh schwieriger wird, an den Parent zu kommen, denn der existiert ja erstmal nicht. Im momentanen Zustand ist die Unit für solche Programme nicht wirklich zu gebrauchen, denn dafür müsste man CreateParams entfernen (was den Parent des erzeugten Forms setzt). Naja, dafür müsste man wohl die Unit noch etwas umbauen . Da es mir darum aber nicht ging, überlasse ich das anderen, Quellcode ist ja offen .

Zitat:
Gehst Du in der Unit "TotalCmdGUI" von 4 Monitoren aus ?
Ja, warum nicht? Reicht das nicht?

Zitat:
Soviel ich weiß, sind bis zu 9 möglich.
Das mag sein, interessiert in der Praxis, in der ich mich bewege, aber nicht. Ich selbst habe nur einen Monitor, in der Firma haben einige Rechner zwei Monitore, mehr existieren in meiner Praxis nicht. Hinzu kommt noch, dass die Definition zwar nur bis zum vierten (expliziten) Monitor erlaubt (nebenbei ja ganz simpel auf mehr Monitore erweiterbar), das Benutzen des aktiven Monitors aber völlig frei ist und auch bei hundert Monitoren funktionieren würde.

Zitat:
Die vorhandene Menge findet man über "Screen.MonitorCount"
Ja, genau das benutze ich doch. Aber was bringt mir das für die Definition eines Enum? OK, man könnte jetzt anbringen, da in der Unit letztlich Integer benutzt werden und der Beispiel-Code oben in Form von IniFile.Monitor auch nur Integer, könnte man auf den Enum verzichten. Hatte ich überlegt, aber momentan spielt das für mich keine Rolle. Die Unit tut ihren Dienst und darum ging es letztlich.

Zitat:
Könntest Du bitte mal ein KOMPLETTES und FUNKTIONIERENDES Beispiel Deiner Lösung bringen ?
Ersetze IniFile.Monitor durch einen Integer deiner Wahl, der dem Enum entspricht, binde die angehängte Compiler.inc ein und das müsste genügen.

MfG Dalai
Angehängte Dateien
Dateityp: txt Compiler.txt (4,8 KB, 6x aufgerufen)

Geändert von Dalai (13. Nov 2015 um 02:24 Uhr)
  Mit Zitat antworten Zitat
delnu
(Gast)

n/a Beiträge
 
#5

AW: Positionierung einer Form in Multimonitorumgebung

  Alt 13. Nov 2015, 11:54
Die Compiler-Optionen sind insofern interessant, daß ich dadurch jetzt erstmals einen Überblick über die Definitionen der Versionen nach Delphi 7 habe.

Klar, daß IniFile.Monitor ein integer sein müßte, ist logisch. Aber der Name läßt vermuten, daß Du dessen Wert aus einer (mir unbekannten) Ini-Datei liest. Darum meine Bitte nach einem kompletten Quellcode. Tatsächlich ging ich davon aus, das wäre NICHT NUR für Plugins geeignet. Weil ich nicht weiß, wie man die schreibt, hat sich das dann wohl leider für mich erledigt. Also müßte ich einen Weg finden, auf andere Weise erstmal zu prüfen, auf welchem Monitor sich der TC (bzw. das aufrufende Programm) befindet und dann das aufgerufene Programm auf diesen setzen. Aber das ist mir momentan dann doch zu viel, zumal meine aktiven Jahre mit Delphi schon länger zurückliegen und ich mich erst wieder einarbeiten muß.

Das grundsätzliche Problem sind "DefaultMonitor" und "Position", die durch ihre Festlegung in der Unit "Forms" eher ein Hindernis darstellen. Ausserdem sind deren Original-Berechnungen falsch. Wird "Position" auf "poDesktopCenter" gesetzt, erscheint das Compilat am rechten Rand meines Default-Monitors. Den zweiten habe ich nämlich links und eben nicht rechts davon. Die in Unit "Forms" benutzte Berechnung
Delphi-Quellcode:
        else if FPosition = poDesktopCenter then
        begin
          if FormStyle = fsMDIChild then
          begin
            X := (Application.MainForm.ClientWidth - Width) div 2;
            Y := (Application.MainForm.ClientHeight - Height) div 2;
          end else
          begin
            X := (Screen.DesktopWidth - Width) div 2;
            Y := (Screen.DesktopHeight - Height) div 2;
          end;
          if X < 0 then X := 0;
          if Y < 0 then Y := 0;
          SetBounds(X, Y, Width, Height);
        end;
berücksichtigt nur Höhe und Breite des Desktops, aber nicht links und oben. Zur korrekten Auswertung müssen die einbezogen werden. Leider lassen sich Standardunits nicht problemlos durch eigene ersetzen, sonst sähe nicht nur "Forms" bei mir anders aus.

Momentan nutze ich an den meisten meiner Computer auch nur 2 Monitore, aber an einem 3 und da sollen es auch maximal 4 werden. Nur aus Gründen der Universalität bzw. Vollständigkeit wäre meiner Meinung nach besser, dem Anwender die maximal nutzbare Menge zu ermöglichen. Das kann durchaus auch durch dynamische statt statische Zuweisung erfolgen.

Anbei ein Screenshot eines Screenshot-Programms, das (statisch) von maximal 9 möglichen Monitoren ausgeht. Die nicht vorhandenen sind ausgegraut und es ist möglich, den gesamten Desktop zu snappen. Den Quelltext kann ich momentan nicht liefern, weil für die diversen möglichen Grafikformate Fremdunits benutzt werden und ich die zum einen suchen müßte und zum anderen nicht aus dem Kopf weiß, welche davon nicht direkt nutzbar sind, sondern evtl. installiert werden müssen.
Angehängte Grafiken
Dateityp: png snap.png (6,7 KB, 19x aufgerufen)
  Mit Zitat antworten Zitat
Benutzerbild von Dalai
Dalai

Registriert seit: 9. Apr 2006
1.683 Beiträge
 
Delphi 5 Professional
 
#6

AW: Positionierung einer Form in Multimonitorumgebung

  Alt 13. Nov 2015, 13:24
Die Compiler-Optionen sind insofern interessant, daß ich dadurch jetzt erstmals einen Überblick über die Definitionen der Versionen nach Delphi 7 habe.
Da ich für mein Plugin ein unicodefähiges Delphi brauchte, aber die Tests im alten Delphi einfach schneller gehen, hab ich irgendwann mal diese Include-Datei zusammengezimmert (IIRC hab ich dafür die Vorlage von jemand anders benutzt). Schwierig ist immer, herauszufinden, welches Delphi man im $IFDEF nun setzen muss, seit wann es ein Feature gibt oder ein Fehler korrigiert wurde...

Zitat:
Tatsächlich ging ich davon aus, das wäre NICHT NUR für Plugins geeignet.
Ich werde die Abhängigkeit von CreateParams mal versuchen zu entfernen, kann aber nichts versprechend, weil mir ohne Tests die Reihenfolge der Aufrufe von Create und CreateParams der abgeleiteten und der Basisklasse nicht klar sind. Ist eben doof, wenn man zwei verschiedene Dinge in einer Klasse vermengt, die aber beide auf das Handle des Parent zurückgreifen. Mal sehen.

Zitat:
Also müßte ich einen Weg finden, auf andere Weise erstmal zu prüfen, auf welchem Monitor sich der TC (bzw. das aufrufende Programm) befindet und dann das aufgerufene Programm auf diesen setzen.
Das musst du sowieso. Aber mit MSDN-Library durchsuchenGetActiveWindow oder MSDN-Library durchsuchenGetForegroundWindow liegt man wahrscheinlich nicht ganz falsch.

Zitat:
Das grundsätzliche Problem sind "DefaultMonitor" und "Position", die durch ihre Festlegung in der Unit "Forms" eher ein Hindernis darstellen.
Ja und nein. Einerseits stimmt das, aber die von mir gewählte Variante über CM_SHOWINGCHANGED springt ja erst nach der Positionierung der Form durch die Klasse TForm ein. Insofern überstimme ich jede Positionierung, die Delphi vorher macht.

Zitat:
Ausserdem sind deren Original-Berechnungen falsch. Wird "Position" auf "poDesktopCenter" gesetzt, erscheint das Compilat am rechten Rand meines Default-Monitors.
Das wurde irgendwann zwischen Delphi 5 und XE2 behoben, denn dort ist die Berechnung an den Monitor der Form gekoppelt, wenn ich das richtig verstanden habe.

Zitat:
Nur aus Gründen der Universalität bzw. Vollständigkeit wäre meiner Meinung nach besser, dem Anwender die maximal nutzbare Menge zu ermöglichen.
Ja, aber wer sagt, welches die maximal nutzbare/mögliche Anzahl von Monitoren ist? Hängt vielleicht auch von der jeweiligen Windows-Version oder irgendwelchen anderen Faktoren ab, und da wird's dann nämlich wieder kompliziert.

MfG Dalai
  Mit Zitat antworten Zitat
delnu
(Gast)

n/a Beiträge
 
#7

AW: Positionierung einer Form in Multimonitorumgebung

  Alt 13. Nov 2015, 14:10
zur maximalen Monitormenge:

Als Maximum gilt (ab Windows 98) 9. Ich habe auch keine Informationen, daß es irgendwann mal mehr geworden wären, aber das würde dann wahrscheinlich über übliche Standards hinausgehen. Bei den von mir benutzten Windows-Versionen 98 SE und XP sind jedenfalls 9 das Maximum. Anhand des benutzten Betriebssystems läßt sich ggf. auswerten, wieviel tatsächlich möglich sind - falls mit neueren Versionen (oder durch Zusatztreiber oder wodurch auch immer) mehr als 9 erlaubt wären.

Vielleicht sind hier mehr Informationen versteckt : https://msdn.microsoft.com/de-de/lib...=vs.85%29.aspx, aber ich kann kein "C" ...

Das wirkliche Problem sind wohl in der Regel eher die verfügbaren Steckplätze. Im Zuge der Sparsamkeit am falschen Platz gibt es kaum noch IBM-kompatible Boards mit der üblichen Maximalzahl von 8 Steckplätzen. Mir waren bisher als Maximum integrierter Grafikprozessoren pro Karte 4 bekannt, und diese Karten sind (neu) ziemlich teuer.

In der Wikipedia heißt es allerdings
Zitat:
Während Karten für einen bis zwei Monitore heute Standard sind, sind im höheren Preissegment einzelne Grafikkarten für bis zu 16 Monitore erhältlich. Es lassen sich prinzipiell auch mehrere Standard-Grafikkarten in einem PC betreiben, wodurch problemlos auch mehr als zwei Monitore an einem Computer betrieben werden können. Grundsätzlich ist bei all diesen Lösungen mit Einschränkungen in Bezug auf die 3D-Funktionen zu rechnen.
Dazu fand ich z.B. diese Links:
http://www.chip.de/news/Shuttle-H7-5..._52500408.html
http://www.pcwelt.de/forum/showthrea...nen-PC-steuern
  Mit Zitat antworten Zitat
Antwort Antwort


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 10:50 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 by Thomas Breitkreuz