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