2016-05-04 5 views
0

Ich benutze Delphi XE7, um die Probleme zu testen, die eine Anwendung DPI bewusst machen.WM_DPICHANGE Nachricht nicht empfangen

Eine der Aufgaben besteht darin, auf die WM_DPICHANGE-Nachricht zu reagieren, die generiert werden soll, wenn ein Fenster auf einen Monitor mit einem anderen DPI-Wert verschoben wird. Ich habe kein Multi-Monitor-Setup, also schrieb ich ein sehr einfaches Testprogramm, das diese Nachricht generiert, aber es wird nicht auf einer Windows 8.1-Plattform empfangen. Es funktioniert OK auf Windows 7. Das folgende Programm veranschaulicht dies:

unit Main; 

interface 

uses 
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, 
    Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; 

const 
    WM_DPICHANGED = 736; // 0x02E0 

type 
    TMyForm = class(TForm) 
    Button1: TButton; 
    procedure Button1Click(Sender: TObject); 
    private 
    { Private declarations } 
    procedure DPIChanged(var Message: TMessage); message WM_DPICHANGED; 
    public 
    { Public declarations } 
    end; 

var 
    MyForm: TMyForm; 

implementation 

{$R *.dfm} 

procedure TMyForm.Button1Click(Sender: TObject); 
begin 
    PostMessage(Self.Handle,WM_DPICHANGED,0,0); 
end; 

procedure TMyForm.DPIChanged(var Message: TMessage); 
begin 
    ShowMessage('Message WM_DPICHANGED Received'); 
end; 

end. 

Die Showmessage erscheint nicht, wenn unter Windows 8.1 ausgeführt werden. Ist etwas essen die Nachricht, bevor es mein Programm trifft?

+0

Sie haben keine Chance, irgendetwas ohne mehrere Monitore zu erreichen –

+1

Dies wird nichts erreichen. Selbst wenn Sie die Nachricht abfangen könnten, können Sie nicht testen, wie Sie darauf reagieren, ohne einen zweiten Monitor mit einer anderen DPI-Einstellung zu haben. Es ist so, als würde man versuchen, eine Android-App zu schreiben, ohne ein Android-Gerät oder einen Simulator zu haben; Alles, was Sie tun, ist ein einfaches Raten und muss scheitern. –

+1

Auch lesen Sie [die Dokumentation] (https://msdn.microsoft.com/en-us/library/windows/desktop/dn312083%28v=vs.85%29.aspx) wo es heißt, dass diese Nachricht nur von Anwendungen empfangen werden, die sich als "PROCESS_PER_MONITOR_DPI_AWARE" registriert haben, richtig? –

Antwort

2

WM_DPICHANGED wird nur unter Windows 8.1 und neuer unterstützt.

Wenn Sie sagen, dass Ihr Code unter Windows 7 funktioniert, funktioniert es tatsächlich so, dass beim Klicken auf die Schaltfläche die Nachricht an Ihr Fenster gesendet wird und Sie diese Nachricht erfassen. Auf der anderen Seite hat es nichts mit dem tatsächlichen DPI-Wechsel zu tun. Unter Windows 7 wird WM_DPICHANGED genauso behandelt, wie Sie eine benutzerdefinierte Nachricht gesendet haben.

Unter Windows 8.1 und neuer WM_DPICHANGED ist Windows-API-definierte Nachricht. Senden dieser Nachricht mit PostMessage schlägt mit Fehlercode 1159 ERROR_MESSAGE_SYNC_ONLY

Dieser Fehler bedeutet, dass Sie diese bestimmte Nachricht nicht asynchron senden können. Problem hier ist in zweiten Parameter hier, der Zeiger auf RECT Struktur im Fall von WM_DPICHANGED Nachricht wie in Windows-API definiert ist.

WM_DPICHANGED

  • WParam - Die HIWORD des WParam enthält die Y-Achsen-Wert des neuen dpi des Fensters. Das LOWORD des wParam enthält den X-Achsen-Wert des neuen DPI des Fensters. Zum Beispiel 96, 120, 144, oder 192. Die Werte der X-Achse und der Y-Achse sind für Windows-Apps identisch.
  • lParam - A Zeiger auf eine RECT-Struktur, die eine vorgeschlagene Grße und Position des aktuellen Fensters für die neuen DPI skaliert zur Verfügung stellt. Es wird erwartet, dass Apps die Fenster basierend auf den von lParam zur Verfügung gestellten Vorschlägen neu positionieren und ihre Größe ändern werden, wenn sie diese -Nachricht verarbeiten.

PostMessage

Wenn Sie eine Nachricht im Bereich unter WM_USER den asynchronen Meldefunktionen (Postmessage, SendNotifyMessage und SendMessageCallback) senden, kann seine Nachrichtenparameter keine Zeiger enthalten. Andernfalls schlägt der Vorgang fehl. Die Funktionen werden zurückkehren, bevor der empfangende Thread eine Chance hatte, die Nachricht zu verarbeiten, und der Absender den Speicher freigibt, bevor er verwendet wird.

Wenn Sie PostMessage in Ihrem Code SendMessage Ihre Schaltfläche klicken auf Windows 8.1+ funktioniert ändern, auch.

Natürlich, wenn Sie Ihre Anwendung DPI Awareness richtig eingerichtet haben, verarbeitet sie normalerweise WM_DPICHANGED Nachrichten, die von Windows gesendet werden.

+0

Danke für die Erklärung. Ich war besorgt, dass mein Fenster (das DPI mit einem Manifest bewusst war) die Nachricht nicht erhielt, weil es etwas war, was Delphi tat. Ich muss jetzt nur noch eine Multi-Monitor-Testplattform installieren. – kaj66

+0

* "Windows schützt diese Warteschlange vor dem Empfang von WM_DPICHANGED-Nachrichten, die nicht direkt vom System gesendet werden." * Sieht verdächtig für mich aus, * send * Nachrichten landen nicht einmal in der Warteschlange. Auf Nachrichten zu warten, die normalerweise nie in einer Warteschlange erscheinen, wäre eine Verschwendung von Ressourcen. Ich kann jedoch nichts testen/verifizieren ... –

+0

@SertacAkyuz Ich habe diesen Kommentar für 'PostMessage' gemacht, wo Nachrichten an die Nachrichtenwarteschlange gesendet werden. Und es ist offensichtlich, dass sie nicht wie erwartet an Fenster weitergegeben werden. Was genau und warum passiert, weiß ich nicht, und Sie müssten wahrscheinlich MS-Entwickler sein, um genaue Details zu wissen. 'SendMessage' verhält sich anders als ich geschrieben habe. –

Verwandte Themen