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 Positionierung einer Form in Multimonitorumgebung (https://www.delphipraxis.net/186156-positionierung-einer-form-multimonitorumgebung.html)

Dalai 8. Aug 2015 12:31

Positionierung einer Form in Multimonitorumgebung
 
Hallo Leute,

hier ist schon wieder der ohne Lama :mrgreen:.

Vorgestern ist mir eine Sache in meinen Total Commander Plugins aufgefallen: Die Positionierung der Formulare ist falsch, wenn sie in einer Multimonitorumgebung benutzt werden. Es werden alle davon auf dem linken Monitor plaziert, und zwar unabhängig davon, welcher der primäre Monitor ist. Interessanterweise trifft das nur auf das mit XE2 erstellte Kompilat zu. Die mit Delphi 5 erstellte DLL positioniert alle Forms immer auf dem aktiven Monitor, d.h. dort, wo sich Total Commander befindet.

Nun hab ich mir natürlich die Eigenschaft TForm.DefaultMonitor angeschaut und damit ein bisschen rumgespielt, aber der Satz
Zitat:

Note: DefaultMonitor has no effect if the application does not have a main form
ist wohl ernstzunehmen, auch wenn mich wundert, dass es im alten Delphi funktioniert, obwohl dieser Hinweis auch dort schon zu finden ist.

Frage:
An welcher Schraube muss ich drehen, um eine Änderung der Formpositionierung zu erreichen? Geht das ohne manuelle Plazierung der Formulare oder muss ich wirklich alles von Hand machen?

MfG Dalai

haentschman 8. Aug 2015 13:15

AW: Positionierung einer Form in Multimonitorumgebung
 
Hallo...

Ich rate mal: :zwinker:
Stelle mal die PlugInForm auf poMainFormCenter z.B. Ich tippe sie steht auf poDesigned. Da dein Plugin vom TotalCommander geladen wird sollte "MainForm" TotalCommander heißen.

Dalai 8. Aug 2015 13:55

AW: Positionierung einer Form in Multimonitorumgebung
 
TForm.Position steht auf poOwnerFormCenter. poScreenCenter hab ich ebenfalls probiert, aber das ändert nichts. Auch poMainFormCenter bringt nichts, weil es keine MainForm gibt (Application.MainForm ist nicht zugewiesen, also vermutlich nil).

MfG Dalai

Perlsau 8. Aug 2015 15:08

AW: Positionierung einer Form in Multimonitorumgebung
 
Also ich merke mir immer die linke obere Ecke einer Form, deren Position ich speichern will, damit hatte ich noch nie Probleme. Wenn dein Haupt-Monitor eine horizontale Bildschirmauflösung von 1920 hat und der zweite rechts davon positioniert ist, dann ist das erste Pixel des zweiten Monitors in der Spalte 1920.

Dalai 7. Nov 2015 21:50

AW: Positionierung einer Form in Multimonitorumgebung
 
Tut mir leid, dass ich so lange nichts von mir hören ließ. Es war zuviel Arbeit, und da musste sich dieses Privatprojekt hinten anstellen.

Heute kam ich wieder dazu, mich damit zu beschäftigen. Zuerst eine Korrektur: Es ist wohl anders als ich bisher annahm, dass die Forms nicht immer auf dem linken Monitor dargestellt werden sondern immer auf dem primären; ich hoffe, das ist diesmal richtig, denn momentan ist nicht hundertprozentig sicher, wie die Anordnung auf dem einen Rechner war, an dem mir die Sache überhaupt erst aufgefallen war.

Weiterhin ist es so, dass die Sache nicht nur dieses spezifische Projekt (Total Commander Plugin) betrifft sondern offenbar alle Delphi-Programme - nach einigen Tests mit meinen normalen Programmen erlaube ich mir, diese Behauptung aufzustellen. Das erste Form eines Delphi-Programms wird offenbar immer auf dem primären Monitor angezeigt. Soweit ist das ja auch in Ordnung. Aber bei Forms aus DLLs wird die Sache knifflig, vor allem dann, wenn man TApplication.MainForm und/oder TApplication.Handle nicht gesetzt hat - was in diesem Fall seine Gründe hat (für Hintergründe siehe Modales Fenster in DLL, Taskleiste).

Kommen wir zum Wesentlichen. Ich habe eine Möglichkeit gefunden, mein Ziel mit ein wenig Code zu erreichen. Hier ein Auszug (ohne die ganzen Ergänzungen für alte Delphis):
Delphi-Quellcode:
type
  TTotalCmdWfxForm = class(TForm)
  private
    { Handle to TC's main window }
    FhTotalCmd  : HWND;
    function GetMonitorOfParent(const AParent: HWND = 0): TMonitor;
    procedure CenterOnMonitor(const AMonitor: TMonitor);
    procedure FormActivate(Sender: TObject);
  public
    procedure Init; virtual;
  end;
 


procedure TTotalCmdWfxForm.Init;
begin
    Self.OnActivate:= Self.FormActivate;
end;

//------------------------------------------------------------------------------

function TTotalCmdWfxForm.GetMonitorOfParent(const AParent: HWND = 0): TMonitor;
begin
    Result:= Screen.MonitorFromWindow(AParent, mdNearest);
end;

//------------------------------------------------------------------------------

procedure TTotalCmdWfxForm.CenterOnMonitor(const AMonitor: TMonitor);
var Lrect: TRect;
    Lwidth, Lheight: integer;
begin
    if AMonitor <> nil then begin
        Lrect:= AMonitor.WorkAreaRect;
        Lwidth:= Lrect.Width;
        Lheight:= Lrect.Height;
        Self.Left:= AMonitor.Left + ((Lwidth div 2) - (Self.Width div 2));
        Self.Top:= AMonitor.Top + ((Lheight div 2) - (Self.Height div 2));
    end;
end;

//------------------------------------------------------------------------------

procedure TTotalCmdWfxForm.FormActivate(Sender: TObject);
var Lmon: TMonitor;
begin
    if (Screen.MonitorCount > 1) then begin
        Lmon:= GetMonitorOfParent(FhTotalCmd);
        CenterOnMonitor(Lmon);
    end;
end;
Hinweis: Der Wert von FhTotalCmd wird im Konstruktor gesetzt, der in obigem Code fehlt.

Was mit daran überhaupt nicht gefällt, ist die Benutzung des OnActivate-Ereignisses. Dummerweise setzt die VCL irgendwann im OnShow (SetVisible) die Position der Form um, so dass irgendwelche vorherigen Änderungen überschrieben werden. Ich muss also nach OnShow ansetzen; da kommt aber nur noch OnActivate, oder liege ich da falsch?

Hat dazu jemand Ideen?

MfG Dalai

Sir Rufo 7. Nov 2015 23:23

AW: Positionierung einer Form in Multimonitorumgebung
 
Der richtige Zeitpunkt wäre wohl der erste Idle-Zustand nach dem OnShow

HolgerX 8. Nov 2015 09:30

AW: Positionierung einer Form in Multimonitorumgebung
 
Wenn ich ein 'OnAfterShow' benötige, dann sende ich im Show eine Message per PostMessage an die Form selber und kann dann in

procedure WndProc(var Message: TMessage); override;

darauf reagieren.

Bei OnIdle ist das Problem, das ich mir merken muss, das es das erste OnIdle nach dem Show ist, da OnIdle immer wieder aufgerufen wird, wenn nichts zu tun ist.

Durch das Postmessage am Ende von OnShow werden zunächst noch alle Windows-Messages verarbeitet und dann kommt erst deine eigene 'OnAfterShow', so dass Du sicher sein kannst, dass alle Messages beim Formularanzeigen, wie z.B. die korrekte Anzeige aller Controlls abgeschlossen ist.

Ach..
Und bei OnActivate hatte ich die Probleme, das es manchmal gar nicht aufgerufen wurde oder wenn die Form mit Show statt ShowModal angezeigt wurde bei jedem Formularwechsel wieder aufgerufen wurde.. ;)

Dalai 8. Nov 2015 13:25

AW: Positionierung einer Form in Multimonitorumgebung
 
Ich wollte eigentlich auf etwas anderes hinaus: Wenn ich mich an ein Event (OnActivate, OnShow) hänge, das von außen gesetzt werden kann - entweder im Objektinspektor oder im Code - wird der Code zur Plazierung des Forms nicht ausgeführt, und zwar ohne, dass es eine Warnung gibt oder sonstwas.

Daher habe ich etwas tiefer gegraben und bin fündig geworden:
Delphi-Quellcode:
TTotalCmdWfxForm = class(TForm)
  private
    { Handle to TC's main window }
    FhTotalCmd  : HWND;
    { Has this form been centered on the active screen? }
    FCentered   : Boolean;
    function GetMonitorOfParent(const AParent: HWND = 0): TMonitor;
    procedure CenterOnMonitor(const AMonitor: TMonitor;
    procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED;
  end;


procedure TTotalCmdWfxForm.CMShowingChanged(var Message: TMessage);
var Lmon: TMonitor;
begin
    inherited;
    if Self.Showing then begin
        if NOT FCentered then begin
            if (Screen.MonitorCount > 1) then begin
                Lmon:= GetMonitorOfParent(FhTotalCmd);
                CenterOnMonitor(Lmon);
            end;
            FCentered:= True;
        end;
    end;
end;
Anscheinend ist es so (ausgehend von gezielt gesetzten Breakpoints auf das
Delphi-Quellcode:
inherited;
und die nachfolgende Zeile), dass die Nachricht einerseits zum richtigen Zeitpunkt und andererseits selten genug gesendet wird, so dass es nicht stört.

Offenbar ist es auf diese Weise möglich, in der Basisklasse privat deklarierte Messages zu überschreiben.

Sofern es keine (begründeten) Einwände gegen diese Variante gibt, werde ich es dabei belassen. Danke auf jeden Fall an alle Beteiligten! :thumb:

MfG Dalai

delnu 12. Nov 2015 11:20

AW: Positionierung einer Form in Multimonitorumgebung
 
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 ?:roll:

Danke im Voraus.:thumb:

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 ?:cyclops:

Dalai 12. Nov 2015 12:38

AW: Positionierung einer Form in Multimonitorumgebung
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von delnu (Beitrag 1321275)
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 ?:roll:
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 :cyclops:.

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 ?:cyclops:
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

delnu 13. Nov 2015 00:04

AW: Positionierung einer Form in Multimonitorumgebung
 
Liste der Anhänge anzeigen (Anzahl: 1)
zunächst fehlt hinter TfmSvcProperties = class(TTotalCmdWfxForm)ein Semikolon.:lol:

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

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 ?

Dalai 13. Nov 2015 01:19

AW: Positionierung einer Form in Multimonitorumgebung
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von delnu (Beitrag 1321371)
zunächst fehlt hinter TfmSvcProperties = class(TTotalCmdWfxForm)ein Semikolon.:lol:

Nicht wirklich. Die Zeile darunter ist eine Platzhalterzeile, die noch mehr Sachen innerhalb der Klasse andeutet und durch das nachfolgende
Delphi-Quellcode:
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
Delphi-Quellcode:
$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;
:shock:
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 :wink:.

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

delnu 13. Nov 2015 10:54

AW: Positionierung einer Form in Multimonitorumgebung
 
Liste der Anhänge anzeigen (Anzahl: 1)
Die Compiler-Optionen sind insofern interessant, daß ich dadurch jetzt erstmals einen Überblick über die Definitionen der Versionen nach Delphi 7 habe. :lol:

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.

Dalai 13. Nov 2015 12:24

AW: Positionierung einer Form in Multimonitorumgebung
 
Zitat:

Zitat von delnu (Beitrag 1321409)
Die Compiler-Optionen sind insofern interessant, daß ich dadurch jetzt erstmals einen Überblick über die Definitionen der Versionen nach Delphi 7 habe. :lol:

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
Delphi-Quellcode:
$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

delnu 13. Nov 2015 13:10

AW: Positionierung einer Form in Multimonitorumgebung
 
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

Dalai 13. Nov 2015 16:40

AW: Positionierung einer Form in Multimonitorumgebung
 
Liste der Anhänge anzeigen (Anzahl: 1)
So, ich hab die Klassen TTotalCmdWfxForm und TFormEx nun besser voneinander getrennt, so dass man auch direkt von TFormEx ableiten kann, ohne dass WndParent durch den Aufruf von CreateParams gesetzt wird. Das heißt, die Klasse TFormEx ist nun prinzipiell auch für eigenständige Programme nutzbar. Ich kann aber keinerlei Aussage darüber treffen, ob das in dem Bereich auch für das erste/primäre Formular der Anwendung funktioniert, denn das wird ja in der .dpr mittels
Delphi-Quellcode:
Application.CreateForm()
erzeugt...

Im Anhang findet sich ein komplettes Demo-Projekt (nur Source) mit allen benötigten Dateien (hoffentlich), also auch eine aktualisierte Unit TotalCmdGUI. Dabei sind zwei Formulare, von der das zweite beim Klick auf das erste erzeugt und dann nacheinander auf verschiedenen Monitoren (primär, sekundär, aktiv) angezeigt wird.

Ich hoffe, es funktioniert alles :cyclops:.

MfG Dalai

delnu 15. Nov 2015 13:43

AW: Positionierung einer Form in Multimonitorumgebung
 
Hallo ! Ich kam erst heute dazu, mir das runterzuladen. Seltsam, daß sich die Zahl der Downloads dadurch nicht erhöht hat. :roll:

Gewohnheitsmäßig starte ich Beispiele erstmal sowie sie sind. Erst als ich dann lediglich ein leeres Formular vorfand, guckte ich in den Quelltext und habe den fehlenden Button ergänzt.

Leider ergibt sich nicht die erwünscht Funktionalität. Gestartet und geendet wird immer auf dem primären Monitor. Zwischendurch geht es dann auf den zweiten.

Wahrscheinlich werde ich es nun so machen, Programme, von denen ich weiß, daß ich sie über den TC starte, grundsätzlich auf dem zweiten Monitor erscheinen lasse (falls einer da ist) ...

Obwohl: Wenn der nicht angeschaltet ist (was sich wohl nicht softwaremäßig prüfen läßt) wird das nix und es bringts auch nicht, wenn man den TC selbst auf demm zweiten Monitor startet.

Trotzdem danke ich Dir für Deine Mühe :thumb: und werde mir mal irgendwann (wenn ich dafür mehr Zeit finde) Deine Quelltexte sorgfältig durchsehen und prüfen, ob ich es damit doch irgendwie hinbekomme, das aufgerufene Programm auf dem jeweils anderen Bildschirm starten zu lassen.

Dalai 15. Nov 2015 14:46

AW: Positionierung einer Form in Multimonitorumgebung
 
Zitat:

Zitat von delnu (Beitrag 1321515)
Gewohnheitsmäßig starte ich Beispiele erstmal sowie sie sind. Erst als ich dann lediglich ein leeres Formular vorfand, guckte ich in den Quelltext und habe den fehlenden Button ergänzt.

Nein, da fehlt kein Button. Ich hatte zwar mal einen drin, aber später dachte ich mir, dass der gar nicht nötig ist, denn auch TForm kennt ein OnClick-Ereignis - und genau bei diesem wird die Routine aktiv (eben beim Klick auf das leere Formular).

Zitat:

Leider ergibt sich nicht die erwünscht Funktionalität. Gestartet und geendet wird immer auf dem primären Monitor. Zwischendurch geht es dann auf den zweiten.
Na also macht es doch das, was es soll, denn ich schrieb ja: nacheinander wird das zweite Formular auf verschiedenen Monitoren angezeigt, ganz so, wie es in der Ereignisbehandlungsroutine steht. Die paar Zeilen sind ja nun wirklich nicht schwer zu verstehen.

Zitat:

Wahrscheinlich werde ich es nun so machen, Programme, von denen ich weiß, daß ich sie über den TC starte, grundsätzlich auf dem zweiten Monitor erscheinen lasse (falls einer da ist) ...
Da musst du aber selber rumprobieren, denn zum ersten/primänre Formular hab ich mich ja bereits ausgelassen.

MfG Dalai

delnu 15. Nov 2015 18:34

AW: Positionierung einer Form in Multimonitorumgebung
 
Zitat:

Na also macht es doch das, was es soll, denn ich schrieb ja: nacheinander wird das zweite Formular auf verschiedenen Monitoren angezeigt, ganz so, wie es in der Ereignisbehandlungsroutine steht. Die paar Zeilen sind ja nun wirklich nicht schwer zu verstehen.
Weitere Formulare auf beliebige Bildschirme zu setzen, ist erheblich einfacher möglich als mit solchem Aufwand.
Ging es nicht eigentlich um das Haupt-Formular ? Aber lassen wir das, weil weitere Diskussionen nichts bringen.

Ich bin jetzt erstmal eine Weile raus aus dem Forum, weil ich paar neue Netzwerke einrichten muß.

Dalai 15. Nov 2015 18:42

AW: Positionierung einer Form in Multimonitorumgebung
 
Zitat:

Zitat von delnu (Beitrag 1321522)
Weitere Formulare auf beliebige Bildschirme zu setzen, ist erheblich einfacher möglich als mit solchem Aufwand.

Dann lass mal hören. Vor allem würde mich interessieren, wie du das bei ShowModal machen würdest.

Zitat:

Ging es nicht eigentlich um das Haupt-Formular ?
Nein, mir ging es in erster Linie um TC-Plugins, oder allgemeiner formuliert: in DLLs gelagerte VCL-Forms, die kein Application.Handle und vor allem kein Application.MainForm haben. Dass ich das später auch für reguläre Delphi-Anwendungen umgeschrieben habe, war mehr oder weniger nur Beiwerk. Hauptformulare habe ich ganz bewusst ausgeklammert, weil die mich nicht interessieren, und es dafür auch andere Möglichkeiten gibt (z.B. Position beim Beenden speichern und beim Laden wiederherstellen).

Zitat:

Ich bin jetzt erstmal eine Weile raus aus dem Forum, weil ich paar neue Netzwerke einrichten muß.
Na dann viel Erfolg dafür!

MfG Dalai

delnu 16. Nov 2015 02:55

AW: Positionierung einer Form in Multimonitorumgebung
 
Liste der Anhänge anzeigen (Anzahl: 2)
Zitat:

Na dann viel Erfolg dafür!
Danke, das kann ich brauchen.

Zitat:

Dann lass mal hören. Vor allem würde mich interessieren, wie du das bei ShowModal machen würdest.
Mit ShowModal habe ich sowas noch nie probiert. Aber weil Du wissen wolltest, wie die Umschaltung auch ohne viele Verrenkungen möglich ist, habe ich mal ein altes Delphi 1-Projekt (wie sich vielleicht erkennen läßt) abgespeckt. Wahrscheinlich sind noch Reste von Teilen drin, die für das Beispiel nicht mehr benutzt werden.

Das eigentliche Umschalten ist sehr simpel. Was das angehängte Beispiel aufbläht ist nur der Rest.:lol:

Hier zum Verständnis paar Auszüge:
Delphi-Quellcode:
...
    f_left, f_top      : integer;
    MyMonitor          : TMonitor;
    DefaultMonitor     : integer;
    procedure GetMonitors;
...
procedure TBaseForm.GetMonitors;
VAR
 cnt : INTEGER;
BEGIN
 RadioGroup1.Items.Clear;

  FOR cnt:=0 TO Screen.MonitorCount-1 DO
  WITH Screen.Monitors[cnt]
  DO  BEGIN
   RadioGroup1.Items.Add(
             ' Monitor '+IntToStr(MonitorNum)+' : '+
                IntToStr(width)+' *'+IntToStr(Height));
  END;

END; { procedure TBaseForm.GetMonitors }

procedure TBaseForm.FormCreate(Sender: TObject);
begin
  f_left := left;
  f_top := top;
  DefaultMonitor:=0; { sicherheitshalber }
end;

procedure TBaseForm.FormShow(Sender: TObject);
begin
 MyMonitor:=TMonitor.Create;
 GetMonitors;
   RadioGroup1.ItemIndex:=0; // sicherheitshalber erster Monitor ?
// RadioGroup1.ItemIndex:=Screen.MonitorCount-1; //letzter Monitor
   IF Screen.MonitorCount>1 THEN if askuser // global
   THEN Start_Mon; // = Benutzer wählen lassen !
   RadioGroup2.visible:=Screen.MonitorCount>1;
   Caption:=IntToStr(Screen.MonitorCount)+' Monitore';
   Form2.Show;
end;

procedure TBaseForm.FormDestroy(Sender: TObject);
begin
 MyMonitor.Free;
end;
Im innerhalb von "FormShow" (na gut, das könnte vielleicht woanders geschehen) dynamisch erzeugten und in "FormDestroy" freigebenen "MyMonitor" des Typs "TMonitor" wird alles Wesentliche erfaßt. Je nach Anzahl vorhandener Monitore wird in "GetMonitors" für jeden dynamisch ein Eintrag in "RadioGroup1" erzeugt.

Das Umschalten, wo Form1 ("BaseForm") gezeigt werden soll (mit mehr als 2 Monitoren habe ich es auf die Schnelle nicht umgesetzt) erfolgt über "RadioGroup1", entsprechend für "Form2" über "RadioGroup2". Wie Du siehst, besteht in meinem Beispiel der Hauptaufwand woanders.

Nun ja, wenn Du TC-Plugins schreibst (wäre nett, wenn Du an anderer Stelle mal ein Tutorial dafür erstellen könntest) wäre in dem Fall natürlich das Hauptformular der TC selbst. Aber trotzdem wird der von Dir betriebene Aufwand unnötig sein.

Vielleicht bringt Dir das angehängte Beispiel neue Denkanstöße.:roll:

So, jetzt bin ich aber wirklich mal für eine Weile weg.

EDIT: Die Hardware für die Netzwerke ist noch nicht vollständig angekommen. Darum hatte ich Zeit, das Beispiel etwas zu optimieren. Jetzt werden (DESKTEST-NEU.ZIP) für beide Forms alle vorhandenen Monitore (bis zur erlaubten Maximalzahl) möglich. Außerdem eine dritte Radiogroup, mit der beide Forms synchron auf jeden der vorhandenen Monitore gesetzt werden können. Die Auswertung habe ich vereinfacht. Hier nur das Wesentliche. Alles andere im angehängten kompletten Source.
Delphi-Quellcode:
procedure TBaseForm.GetMonitors;
VAR
 cnt : INTEGER;
BEGIN
 RadioGroup1.Items.Clear;
 RadioGroup2.Items.Clear;
 RadioGroup3.Items.Clear;

  FOR cnt:=0 TO Screen.MonitorCount-1 DO
  WITH Screen.Monitors[cnt]
  DO  BEGIN
   RadioGroup1.Items.Add(
             ' Monitor '+IntToStr(MonitorNum)+' : '+
                IntToStr(width)+' *'+IntToStr(Height));
   RadioGroup2.Items.Add(
             ' Monitor '+IntToStr(MonitorNum)+' : '+
                IntToStr(width)+' *'+IntToStr(Height));
   RadioGroup3.Items.Add(
             ' Monitor '+IntToStr(MonitorNum)+' : '+
                IntToStr(width)+' *'+IntToStr(Height));
  END;

END; { procedure TBaseForm.GetMonitors }
...
procedure TBaseForm.RadioGroup3Click(Sender: TObject);
var
 m: integer;
begin
 m:= RadioGroup3.ItemIndex;
 BaseForm.left:= Screen.Monitors[m].left+f_left;
 BaseForm.top := Screen.Monitors[m].top+f_top;
 Form2.left:= Screen.Monitors[m].left+Form2.baseleft;
 Form2.top := Screen.Monitors[m].top+Form2.basetop;
end;

Dalai 16. Nov 2015 14:47

AW: Positionierung einer Form in Multimonitorumgebung
 
Der Gag an meiner Variante ist die Kapselung in einer Klasse, die für sich den Kram macht und nur anhand der im Show/ShowModal übergebenen Parameter entscheidet, wo sie angezeigt werden soll. Dieser Code kann einfach wiederverwendet werden: Unit einbinden, Variable der Klasse deklarieren und lost geht's (vorausgesetzt, es existiert ein passendes DFM, denn sonst bekommt man nur die Fehlermeldung "Ressource nicht gefunden", wie ich erfahren musste :stupid:). Und die Klasse funktioniert auch für modale Aufrufe.

Deine Variante greift viel zu viel auf globale Variablen zurück (ja, ich weiß, alter Code und so ;)) und wird für ShowModal nicht funktionieren; das ist eben ein blockierender Funktionsaufruf.

Die Geschichte mit dem Anzeigen des Hauptformulars auf einem bestimmten Monitor hast du nicht mit drin, oder? Ich hab zwar testweise
Delphi-Quellcode:
askuser:= True;
gesetzt, das führt aber nicht zum Anzeigen des Hauptformulars auf dem zweiten Monitor.

MfG Dalai

delnu 16. Nov 2015 16:34

AW: Positionierung einer Form in Multimonitorumgebung
 
Klar kann man das auch in einer Unit kapseln, aber im Grunde würde sogar eine INCLUDE-Datei reichen. Das basiert ja alles auf Werten der Unit "Forms". Weil dafür bei Delphi 1 die Unit "Multimon" fehlt, hatte ich dann daraus die weiter vorne in einem Beispiel enthaltene Unit "MMM" gebastelt, die auch mit Delphi 1 funktioniert. Wenn man also die Direktzugriffe in eine eigene Unit kapseln will, reicht es, die Initalisierung und Freigabe von "MyMonitor" (das ist vom Typ "TMonitor" der Unit "Forms") vorzunehmen und die in meinen Beispielen direkt auf die RadioGroups gesetzten Ergebnisse eben entsprechend der eigenen Bedürfnisse anzupassen. Das sind doch nur reine Abfragen dessen, was "Forms" schon selbst automatisch zur Verfügung stellt.

Was "askuser" betrifft, so gibt es da jetzt tatsächlich einen Fehler. Das liegt an der Reihenfolge der Zuweisungen hinsichtlich der neuen RadioGroup3.

Ändere "FormShow" mal so:
Delphi-Quellcode:
procedure TBaseForm.FormShow(Sender: TObject);
var
 s: string;
 m: integer;
begin
 MyMonitor:=TMonitor.Create;
 s:=' Monitor';
 GetMonitors;
 m:=Screen.MonitorCount;
   RadioGroup3.visible:=m>1;
   RadioGroup3.ItemIndex:=0; // sicherheitshalber erster Monitor ?
   RadioGroup1.ItemIndex:=0; // sicherheitshalber erster Monitor ?
// RadioGroup1.ItemIndex:=m-1; //letzter Monitor
   IF m>1 THEN if askuser // global
   THEN Start_Mon; // = Benutzer wählen lassen !
   RadioGroup2.visible:=m>1;
   RadioGroup2.ItemIndex:=0; // sicherheitshalber erster Monitor ?
   if m>1 then s:=s+'e';
   Caption:=IntToStr(m)+s;
   Form2.Show;
end;
Dann wird der ItemIndex für RadioGroup3 vor dem für RadioGroup1 gesetzt. Wenn die Zuweisungen für Form2 auch vorgezogen werden, würde Form2 bereits vor der Abfrage (also auch vor der Sichtbarkeit der Hauptform) gezeigt.

In ein paar Tagen habe ich hoffentlich verbesserte Möglichkeiten und mehr Zeit, das zu verfeinern. Beispielsweise habe ich ja auch keine dynamische Höhenanpassung der Radiogroups drin, die entsprechend der Monitoranzahl nötig wäre. Bei der momentanen fest eingestellten Höhe könnte man schon ab ca. 4 oder 5 Monitoren nichts mehr lesen, weil alles zusammen gequetscht wäre.

Außerdem müßte man noch berücksichtigen, daß der Anwender natürlich die Forms auch unabhängig vom jeweiligen Monitor manuell verschieben können will. Die geänderten Relativpositionen müßten dann natürlich angepaßt werden. Wenn die Monitore unterschiedliche Grafikauflösungen haben, muß dafür gesorgt werden, daß die Forms nicht im Nirvana verschwinden, sondern dann zumindest in den noch sichtbaren Bereich verschoben werden. Aber das sind alles Ausgestaltungen und haben mit der reinen Funktionalität, etwas auf einem bestimmten Monitor zu platzieren, nichts mehr zu tun.

Im Grunde steht doch alles Wesentliche im Typ "TMonitor" drin. Es kommt also allenfalls darauf an, Schnittstellen bereitzustellen, mit denen das Hauptprogramm dann kommunizieren kann. In meinem Beispiel sind das die Radiogroups, weil dadurch die Umschaltung erfolgt. Natürlich kann man die Zuweisung auch in Prozeduren kapseln, vielleicht sogar besser in Funktionen (wegen der Möglichkeit z.B. eines Rückgabewerts "FALSE") ...

Aber erzähl doch mal, was Du gekapselt haben willst, bzw. auch wie.

Die Sache mit nicht gefundenen Resourcen läßt sich in der Regel per Übergabeparameter regeln. Das mit "ShowModal" läßt sich wohl auch noch rausfinden, aber ich würde sowas eher mit FormStyle "fsStayOnTop" und BorderStyle "bsToolWindow" machen, wie z.B. bei diversen Grafikprogrammen.

Mir ging es ja mit dem Beispiel nur drum, zu zeigen, daß die eigentliche Umschaltung auch sehr einfach erfolgen kann. Wirklich komplexe Multimonitoranwendungen mit echter Funktionalität könnten auch gut als Gemeinschaftprojekte mehrere Beteiligter zustandekommen.

Dalai 16. Nov 2015 17:51

AW: Positionierung einer Form in Multimonitorumgebung
 
Zitat:

Zitat von delnu (Beitrag 1321591)
Klar kann man das auch in einer Unit kapseln, aber im Grunde würde sogar eine INCLUDE-Datei reichen.

Ich meine nicht Unit sondern Klasse. Dass die Klasse in einer eigenen Unit steht, bietet sich logischerwese an, heißt aber erstmal nicht viel und könnte auch anders geregelt sein.

Zitat:

Das basiert ja alles auf Werten der Unit "Forms".
Ja klar, deswegen hab ich ja meine Klasse von TForm abgeleitet.

Zitat:

Im Grunde steht doch alles Wesentliche im Typ "TMonitor" drin. Es kommt also allenfalls darauf an, Schnittstellen bereitzustellen, mit denen das Hauptprogramm dann kommunizieren kann.
Ja, eben. Und dafür sind globale Variablen ungeeignet.

Zitat:

Aber erzähl doch mal, was Du gekapselt haben willst, bzw. auch wie.
Ich kann meine Unit nehmen und - so wie sie ist - wiederverwenden. Beispiel: Ich erstelle ein neues Projekt, binde diese Unit ein, erstelle ein weiteres Formular, ändere dort die Ableitung von TForm auf TFormEx und benutze dann simpel z.B. den Aufruf
Delphi-Quellcode:
neueForm.Show(fmActive, Self.Handle)
. Fertig. Ich brauche keine weiteren Variablen (vor allem keine globalen), ich muss nichts mehr an der Form rumschieben (auch wenn das natürlich weiterhin möglich ist) oder mich in irgendeiner Weise mit der Ermittlung von Monitoren rumschlagen, weil das alles die Klasse TFormEx bereits macht. Oder ich geb die Unit weiter an jemand anders, und der kann sie ohne viel Gefummel einbinden. Wiederverwendung von Code eben.

Zitat:

Die Sache mit nicht gefundenen Resourcen läßt sich in der Regel per Übergabeparameter regeln.
Nein, tut es nicht. Jedes Formular einer von TForm abgeleiteten Klasse braucht eine passende DFM(-Ressource).

Zitat:

Das mit "ShowModal" läßt sich wohl auch noch rausfinden, aber ich würde sowas eher mit FormStyle "fsStayOnTop" und BorderStyle "bsToolWindow" machen, wie z.B. bei diversen Grafikprogrammen.
Ein modales Fenster hat nichts mit einem immer im Vordergrund befindlichen Fenster zu tun. Das sind zwei völlig verschiedene Dinge.

MfG Dalai

delnu 16. Nov 2015 18:45

AW: Positionierung einer Form in Multimonitorumgebung
 
Zitat:

ändere dort die Ableitung von TForm auf TFormEx
Wieso so umständlich ? Es ist doch schon alles von Anfang an in der Unit Forms vorhanden. Man muß es nur abfragen, kann es allenfalls ergänzen. Im Grunde machst Du nichts anderes, als ein neues Formular zu erzeugen, das unnötig aufgebläht ist. Was Du als "globale Variablen" bemängelst, sind bei Dir dafür die vielen zusätzlichen, verkomplizierenden Vorgänge. Das halte ich für viel undurchschaubarer.

Zitat:

Ja, eben. Und dafür sind globale Variablen ungeeignet.
Wozu sind sie denn dann schon VON HAUS AUS vorhanden? Man muß sie doch einfach nur benutzen. Aber klar: Wieso einfach, wenn's auch umständlich geht.:roll: Sind viele Zusatzprozeduren einfacher? Meiner Meinung ist es eher gegenteilig.

Zitat:

Jedes Formular einer von TForm abgeleiteten Klasse braucht eine passende DFM(-Ressource).
Wovon ich ausging, waren Prozeduren und Funktionen.

Zitat:

Ein modales Fenster hat nichts mit einem immer im Vordergrund befindlichen Fenster zu tun. Das sind zwei völlig verschiedene Dinge.
Ich habe mir lediglich einen möglichen Grund vorgestellt, wieso Du unbedingt ein modales Fenster haben willst. Sowas käme für mich nur in Betracht, wenn es dauernd offen sein soll, um es besser wiederfinden zu können. Dann würde ich es aber so machen, wie erwähnt. Darum mein Vorschlag. Es gibt schon viel zu viele Anwendungen, die einen mit modalen Fenstern nerven, beispielsweise störende Abfragen, die sich nicht einfach wegklicken lassen.

Aber egal. Weil Du unbedingt Deine komplizierte Methode beibehalten willst, statt auf das zugreifen zu wollen, was die Unit Forms von Haus aus bietet, wird das mit der möglichen Entwicklung gemeinsamer Multimonitor-Projekte wohl nichts.

Damit bin ich aus dem Thema raus, weil Du meine Anregungen offenbar nicht verstehst.

Nachtrag:
Die von mir benutzte Variable "MyMonitor" des Typs "TMonitor" ist unnötiges Überbleibsel.

Alle nötigen Informationen stehen VON HAUS AUS bereits in "Screen.Monitors" !

Dalai 16. Nov 2015 19:46

AW: Positionierung einer Form in Multimonitorumgebung
 
Zitat:

Zitat von delnu (Beitrag 1321607)
Zitat:

ändere dort die Ableitung von TForm auf TFormEx
Wieso so umständlich ? Es ist doch schon alles von Anfang an in der Unit Forms vorhanden.

Wie positionierst du denn ein Formular auf dem zweiten Monitor? Du durchsuchst das Array Screen.Monitor. Ich tue das zwar auch, aber ich biete das durch den Enum TFormMonitor auch nach außen an, so dass man eben ohne zusätzliche Arbeit direkt auf den zweiten Monitor plazieren kann, allein durch den Aufruf von
Delphi-Quellcode:
TFormEx.Show(fmSecondary)
.

Wo bietet denn die Unit Forms eine solche Funktionalität an, ein Formular auf dem zweiten oder dritten Monitor zu plazieren? Standardmäßig gibt's doch nur die Möglichkeiten von Delphi-Referenz durchsuchenTForm.DefaultMonitor, das aber eben keine weiteren Monitore beinhaltet. Ich sehe daher nichts, nur das Durchackern des Screen.Monitor Arrays. Und genau das habe ich in eine Klasse gepackt, die das gezielte Plazieren erlaubt.

Zitat:

Im Grunde machst Du nichts anderes, als ein neues Formular zu erzeugen, das unnötig aufgebläht ist.
Aufgebläht ist daran gar nichts, es bietet nur erweiterte Funktionalität.

Zitat:

Was Du als "globale Variablen" bemängelst, sind bei Dir dafür die vielen zusätzlichen, verkomplizierenden Vorgänge. Das halte ich für viel undurchschaubarer.
Es mag auf den ersten Blick undurchschaubarer sein, ist es aber nicht wirklich.

Zitat:

Zitat:

Ja, eben. Und dafür sind globale Variablen ungeeignet.
Wozu sind sie denn dann schon VON HAUS AUS vorhanden?
Du meinst die globale Variable Screen? Ja, nun, Delphi hat auch mal klein angefangen, und damals™ hat man noch häufiger globale Variablen benutzt. Das heißt aber nicht, dass man das im eigenen Code fortsetzen muss. Globale Variablen sind böse, auch wenn ich sie ebenfalls hin und wieder verwende.

Zitat:

Zitat:

Jedes Formular einer von TForm abgeleiteten Klasse braucht eine passende DFM(-Ressource).
Wovon ich ausging, waren Prozeduren und Funktionen.
Nun, Funktionen sind nunmal keine Ressourcen. Ressourcen sind das, was im Kompilat landet und man nachträglich auslesen kann, Bilder, Audio, Video, Manifeste etc. pp. - und eben Formulare.

Zitat:

Zitat:

Ein modales Fenster hat nichts mit einem immer im Vordergrund befindlichen Fenster zu tun. Das sind zwei völlig verschiedene Dinge.
Ich habe mir lediglich einen möglichen Grund vorgestellt, wieso Du unbedingt ein modales Fenster haben willst.
Ich benutze fast ausschließlich modale Fenster, weil es bei mir sehr oft darum geht, vom Benutzer Daten abzufragen, ohne die es nicht weitergehen kann, aber auch, um den Codefluss für mich einfacher zu gestalten (ich hab in den allerwenigsten Fällen mehr als drei Formulare in meinen Anwendungen, insofern will ich da auch keinen Aufwand treiben). Und gerade bei den TC-Plugins gibt es überhaupt keinen Grund, nicht-modale Fenster zu verwenden.

Zitat:

Es gibt schon viel zu viele Anwendungen, die einen mit modalen Fenstern nerven, beispielsweise störende Abfragen, die sich nicht einfach wegklicken lassen.
Stimmt. Daher sind Fenster in meinen Anwendungen oft durch ESC schließ-/abbrechbar.

Zitat:

Weil Du unbedingt Deine komplizierte Methode beibehalten willst, statt auf das zugreifen zu wollen, was die Unit Forms von Haus aus bietet
Ne, sie bietet ja eben nicht alles, was ich brauche, daher ja die Ableitung und Erweiterung.

Zitat:

Damit bin ich aus dem Thema raus, weil Du meine Anregungen offenbar nicht verstehst.
Ich glaube schon, dass ich sie verstehe, nur sehe ich nicht, wie ich deine Varianten in meinem Code umsetzen sollte, ohne erheblich mehr Aufwand zu treiben, als das bei meiner Variante der Fall ist.

Wahrscheinlich gehen wir von zu unterschiedlichen Vorstellungen aus, dass wir aneinander vorbei reden/schreiben.

MfG Dalai


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