Danke!
die Lösung für meine Bedürfnisse ist letztendlich, für die entsprechenden Fenster die Message WM_WINDOWPOSCHANGING auszuwerten und die Änderung der Position dann im Vorhinein gleich einmal zu unterbinden (wenn man auf dem weiteren Bildschirm landen würde, etc.).
Damit kann ich das Verschieben dieser Popup-Fenster erst einmal unterbinden und kann dann benutzerfreundlicher reagieren.
Code:
procedure Txxx.WMWindowPosChanging(var Message: TWMWindowPosChanging);
begin
// Nachfolgender Code funktioniert vor allem deswegen, weil dieses Fenster hier nicht manuell verschoben werden kann.
// Darum können Positionsänderungen nur aufgrund von Erstellung oder Monitorwechsel auftreten
// SWP_NOMOVE muß auf alle gesetzt sein, sonst ignorieren wir das
if (Message.WindowPos.flags and SWP_NOMOVE = SWP_NOMOVE) then
begin
inherited;
exit;
end;
// SWP_NOOWNERZORDER muß gesetzt sein (um falsches Anspringen bei Erstanzeige Popup zu vermeiden, wenn Anwendung auf zweitem Monitor steht, denn
// das Fenster wird ursprünglich auf dem Default-Monitor erstellt und dann durch Umhängen des Parent auf den zweiten Monitor platziert)
if (Message.WindowPos.flags and SWP_NOOWNERZORDER <> SWP_NOOWNERZORDER) then
begin
inherited;
exit;
end;
// aktuelle Position bestimmen und den zugehörigen Monitor.
var rectPos := TRect.Empty;
GetWindowRect(Message.WindowPos.hwnd, rectPos);
var curMon := Monitor;
// neue Position (des Zentrums, denn dieses triggert eventuelle Umskalierungen)
var ptNewPos := TPoint.Create(Message.WindowPos.x + Message.WindowPos.cx div 2, Message.WindowPos.y + Message.WindowPos.cy div 2);
var newMon := Screen.MonitorFromPoint(ptNewPos);
// wenn sich die Monitore unterscheiden, dann Änderung ignorieren
if newMon.Handle <> curMon.Handle then
begin
// Änderung der Position ignorieren
Message.WindowPos.x := rectPos.Left;
Message.WindowPos.y := rectPos.Top;
Message.WindowPos.cx := rectPos.Width;
Message.WindowPos.cy := rectPos.Height;
Message.Result := 1;
// weitere Aktionen ausführen, abhängig vom Popup
...
end
else
inherited;
end;