![]() |
TFileOpenDialog öffnet immer auf MainMonitor
Hallo,
hat jemand eine Idee, wie ich den TFileOpenDialog bei PerMonitorDPIV2 immer auf dem Monitor meiner App öffne? Bei mir öffnet der immer auf dem MainMonitor, egal ob er zuvor beim letzten Öffnen auf den Zweitmonitor verschoben wurde oder meine App auf dem Zweitmonitor ist. Ergänzung: Dies passiert so, wenn die DPI des Monitore verschieden sind. Bei gleicher DPI öffnet der Dialog immer dort wo er zuvor geschlossen wurde (also auch nicht immer auf dem Moitor meiner App). Dies ist besonders ärgerlich wenn meine App auf dem Zweitmonitor ist und das TFileOpenDialog Fenster einfach auf dem Hauptbildschirm aufgeht, wo man es nicht erwartet. Ich weiß das Windows das automatisch speichert, aber Apps wie Chrome und Notepad funktionieren da ok, obwohl die auch PerMonitorDPIV2 sind. In [HKEY_CURRENT_USER\Software\Microsoft\Windows\Curre ntVersion\Explorer\ComDlg32\CIDSizeMRU] sind die Positionen binär gespeichert, aber wie die kodiert sind ist mir unklar und eine Manipulation daran finde ich recht gewagt. BTW: Ich nutze Delphi Sydney. Hier finde ich die Windows Intelligenz nicht sinnvoll. Notepad macht es hier recht gut. Die Öffnen den Dialog immer relativ zur App (oder verschieben ihn, wenn er nicht auf den Bildschirm passt). Ich hoffe ihr könnt mir da helfen. |
AW: TFileOpenDialog öffnet immer auf MainMonitor
Hast du mal versucht deinem Dialog eine GUID zu geben?
|
AW: TFileOpenDialog öffnet immer auf MainMonitor
Ja, das ändert nichts an dem beschriebenen Verhalten.
|
AW: TFileOpenDialog öffnet immer auf MainMonitor
Dann fallen mir nur noch die Kompatibilitätsmodi ein.
Ohne Kennzeichnung geht Windows davon aus, dein Programm ist alt, bzw. total unfähig, und macht dann blöde Dinge. supportedOS dpiAware dpiAwareness per Monitor usw. ![]() ![]() |
AW: TFileOpenDialog öffnet immer auf MainMonitor
Wird denn das richtige Manifest verwendet (also steht wirklich die erwartete PerMonitorDPIV2 im richtigen Abschnitt/Tag), und ist das Manifest syntaktisch korrekt?
Grüße Dalai |
AW: TFileOpenDialog öffnet immer auf MainMonitor
Liste der Anhänge anzeigen (Anzahl: 1)
Mein Manifest sollte auch ok sein.
Alternativ hab ich das Delphi Standard Manifest für MonitorDPIV2 verwendet => Keine Änderung. Ich habe mal ein Demo angehängt (mit Source): Einfach die Form nach dem Start auf einen Zweitmonitor (mit unterschiedlicher DPI Skalierung) schieben und "FileOpen" klicken. Der Dialog geht immer auf dem Hauptmonitor auf. |
AW: TFileOpenDialog öffnet immer auf MainMonitor
Warum nicht einfach die Position vom Formular auslesen und den Dialog "dahinführen" ?
Wie ich neulich gelernt habe gibts ja das Screen und das Desktop für x/y angaben mit den man wunderbar rumspielen kann. Ich lade mal Projekt und passe es an wie beschrieben, vielleicht ist es ja genau das was Du wolltest. |
AW: TFileOpenDialog öffnet immer auf MainMonitor
Ja, das wäre, was ich will.
Aber den Dialog zu verschieben ist tricky und mir bisher nicht optimal gelungen. |
AW: TFileOpenDialog öffnet immer auf MainMonitor
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habe Dein Projekt "repariert".
Im Anhang ist Projekt Quelltext plus Kompilat zum sofort Testen, bei mir klappt es mit allen vier Knöpfe das der Dialog sich auf das Aufrufer-Formular legt. 3 x standard methoden, ich musste lediglich dem Execute() noch ein Handle mitgeben, schon war das Ziel erreicht. Das war mir noch nicht genug, also forstete ich in meiner Sammlung nach brauchbaren und bin fündig geworden. Ich war so frei TOpen-/SaveDialog zu intercepten, so das man nun auch X und Y koordinaten angeben kann. Hier die Quelltexte falls der Anhang flöten geht:
Delphi-Quellcode:
Hier die Interceptor Unit:
unit TestForm;
interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Themes; type TForm1 = class(TForm) FileOpenDialog1: TFileOpenDialog; Button1: TButton; Label1: TLabel; Button2: TButton; Label2: TLabel; Button3: TButton; Label3: TLabel; Label4: TLabel; Button4: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure Button4Click(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} (* Aufgabe: Dialog soll auf dem Formular plaziert sein. Lösung: Nutzung der Window-Handle im Execute() Aufruf. Notlösung: Nutzung einer frei wählbaren Position per x und y Alternativ: Auf passende Message reagieren? (evtl über WM_NOTIFY tiefer rein oder über WM_SHOWWINDOW eher global? dies sind nur vermutungen da die erste änderung bereits zum ziel führte.) Bemerkungen: Alle varianten haben den gleichen Nachteil. Die positionierung funktioniert nur beim ersten Aufruf wie erwartet. Ab da an übernimmt BigBrother die automatik bis man das HauptFormular Fenster etwas verschiebt, dann geht das Spiel von vorne los. *) uses // Winapi.CommDlg // for hacking into dialogs; bind and use this unit dlgPos // Positionierbarer Dialog rein-intercepted ; // der hier benötigt eine handle angabe damit er sich gut dazu positionieren kann procedure TForm1.Button1Click(Sender: TObject); begin // if FileOpenDialog1.Execute() then if FileOpenDialog1.Execute(Application.ActiveFormHandle) then Label1.Caption := FileOpenDialog1.FileName else Label1.Caption := 'canceled'; end; (* Dynamisches Testen von Dialogen *) // der hier erscheint immer gut positioniert bei mir ohne handle angabe procedure TForm1.Button2Click(Sender: TObject); var Dlg: TOpenDialog; // maintype probe begin Dlg := TOpenDialog.Create(nil); // da Dein FileOpenDialog1 über keinerlei Grundeinstellungen verfügt // setze ich auch keine :-) // ansonsten hier so filter, folder, labels usw setzen // um letzendlich das hier machen zu dürfen: if Dlg.Execute() then Label2.Caption := Dlg.FileName else Label2.Caption := 'canceled'; Dlg.Free; end; // der hier benötigt eine handle angabe damit er sich gut dazu positionieren kann procedure TForm1.Button3Click(Sender: TObject); var Dlg: TFileOpenDialog; // subtype testing begin Dlg := TFileOpenDialog.Create(nil); if Dlg.Execute(Application.ActiveFormHandle) then Label3.Caption := Dlg.FileName else Label3.Caption := 'canceled'; Dlg.Free; end; // dies hier arbeitet mit x und y // und passt sich notfalls selbst an procedure TForm1.Button4Click(Sender: TObject); var Dlg: TOpenDialog; begin Dlg := TOpenDialog.Create(Self); if Dlg.Execute((Left + (Width div 2)), (Top + (Height div 2))) then Label4.Caption := Dlg.FileName else Label4.Caption := 'canceled'; Dlg.Free end; end.
Delphi-Quellcode:
Viel Spass damit.
unit dlgPos;
(* Diese Unit erweitert den originalen TOpenDialog und TSaveDialog der Vcl. Nun kann man auch X und Y Koordinaten im Execute() Aufruf verwenden. Wer keinen Title setzt muss sich erstmal mit simplified English zufrieden geben. Benutzung: Diese als letzte Unit einbinden und dynamisch einen Dialog erzeugen oder per Designer auf Form droppen und bei Ausführung halt die X/Y variante nutzen. Mit letzter Unit ist (falls überhaupt vorhanden) nach Unit Vcl.Dialogs gemeint. Methodik: Diese Variante erzeugt einen Thread der wiederum auf ein Handle wartet. Sobald ein Handle vorliegt wird das Fenster vom Handle verschoben. Beispiel dynamisch: procedure TForm1.Button1Click(Sender: TObject); var Dlg: TOpenDialog; begin Dlg := TOpenDialog.Create(Self); if Dlg.Execute((Left + (Width div 2)), (Top + (Height div 2))) then Label1.Caption := Dlg.FileName else Label1.Caption := 'canceled'; Dlg.Free end; Beispiel per Designer: procedure TForm1.Button1Click(Sender: TObject); begin if OpenDialog1.Execute((Left + (Width div 2)), (Top + (Height div 2))) then Label1.Caption := OpenDialog1.FileName else Label1.Caption := 'canceled'; Dlg.Free end; gefunden auf stackoverflow.com Autor und/oder Uploader: Peter Kapas Lizenz: keine Angabe Änderungen: code formatierung. methoden argumente sind nun const. umgeschrieben zu einer intercepted variante. bezeichner angepasst. Kommentare und Änderungen von KodeZwerg. *) interface uses Winapi.Windows, System.Classes, Vcl.Dialogs; type TSetDialogPosition = class(TThread) private Title: string; XPos: Integer; YPos: Integer; protected procedure Execute; override; end; TOpenDialog = class(Vcl.Dialogs.TOpenDialog) private SDP: TSetDialogPosition; public function Execute(const X, Y: Integer): Boolean; overload; end; TSaveDialog = class(Vcl.Dialogs.TSaveDialog) private SDP: TSetDialogPosition; public function Execute(const X,Y: Integer): Boolean; overload; end; implementation // dieser thread wartet auf ein gefundenes handle. // nach 5000 versuchen wird abgebrochen. // wenn ein handle gefunden wurde, // verschiebe das fenster. // terminiere thread. procedure TSetDialogPosition.Execute; var hDlg: HWND; // handle des dialogs rDlg: TRect; // dimension des dialogs fuse: Integer; // endlos schleifen killer begin hDlg := 0; fuse := 0; while ((hDlg = 0) and (fuse < 5000)) do begin hDlg := FindWindow(nil, PChar(Title)); Inc(fuse, 1); end; if (hDlg <> 0) then if GetWindowRect(hDlg, rDlg) then begin XPos := (XPos - (rDlg.Right - rDlg.Left) div 2); YPos := (YPos - (rDlg.Bottom - rDlg.Top) div 2); if (MoveWindow(hDlg, XPos, YPos, (rDlg.Right - rDlg.Left), (rDlg.Bottom - rDlg.Top), True)) then SetWindowPos(hDlg, HWND_TOP, XPos, YPos, 0, 0, SWP_NOSIZE); end; DoTerminate; end; // erzeuge den wartethread // übermittel aktuelle x und y werte // setze title property // rufe original dialog auf // gebe wartethread wieder frei function TOpenDialog.Execute(const X, Y : Integer): Boolean; begin SDP := TSetDialogPosition.Create(False); SDP.XPos := X; SDP.YPos := Y; if Self.Title <> '' then SDP.Title := Self.Title else begin Self.Title := 'Open'; SDP.Title := Self.Title; end; Result := inherited Execute; SDP.Free; end; // erzeuge den wartethread // übermittel aktuelle x und y werte // setze title property // rufe original dialog auf // gebe wartethread wieder frei function TSaveDialog.Execute(const X, Y : Integer): Boolean; begin SDP := TSetDialogPosition.Create(False); SDP.XPos := X; SDP.YPos := Y; if Self.Title <> '' then SDP.Title := Self.Title else begin Self.Title := 'Save'; SDP.Title := Self.Title; end; Result := inherited Execute; SDP.Free; end; end. |
AW: TFileOpenDialog öffnet immer auf MainMonitor
+1 :thumb:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:14 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