uVersion
Mitglied der NOTIFYICONDATA
Struktur kann 3 mögliche Werte haben, die die Version der API darstellen, die zum Erstellen des Taskleistensymbols verwendet wird.
- Verwenden Sie diesen Wert für Anwendungen für Windows-Versionen entwickelt, vor Windows 2000
- NOTIFYICON_VERSION verwendet das Windows 2000-Verhalten. Verwenden Sie diesen Wert für Anwendungen, die für Windows 2000 und höher entwickelt wurden.
- NOTIFYICON_VERSION_4 Verwenden Sie das aktuelle Verhalten. Verwenden Sie diesen Wert für Anwendungen, die für Windows Vista und höher entwickelt wurden.
Wenn es um Nachrichten-Handler für das Tray-Icon kommt, die wParam
und uParam
haben die Unterschiede, wie im folgenden Bild dargestellt.
Beachten Sie, dass NOTIFYICON_VERSION_4
in dem WParam X gibt, und Y-Koordinaten von verschiedenen Veranstaltungen, aber es gibt keine Vorschrift, die die Koordinaten in NOTIFYICON_VERSION
für immer. Dies führt zu einem interessanten Verhalten (was eine Ursache für einen BUG war, den ich zu lösen versuchte). Wenn Sie NOTIFYICON_VERSION
verwenden und dann das Kontextmenü des Taskleistensymbols aufrufen, wird der Mauszeiger, egal wo Sie ihn gerade aufrufen, direkt in der Mitte des Taskleistensymbols platziert. Auch wenn Sie die Tastatur (WINDOWS + B) zum Aufrufen des Kontextmenüs des Symbols verwenden, bewegt sich der Mauszeiger immer noch auf das Symbol.
Dies ist möglicherweise nicht von besonderem Interesse für Sie, bis Sie auf diese besondere BUG schauen, die ich versuche, in Pico torrent Anwendung zu lösen.
Hier ist das Szenario.
- OS: Windows 10
- Anwendung ist nicht pro-Monitor DPI bewusst, aber es ist auf Systemebene DPI bewusst.
- Es gibt einen Anfangswert der Desktop-Skalierung, sagen wir 150%, wenn sich der Benutzer anmeldet.
- Pico torrent wird ausgeführt.
- DPI-Skalierung Wert wird geändert, sagt 125%
- Kontextmenü des Pico torrent aufgerufen wird Das Kontextmenü wird nicht an der richtigen Stelle angezeigt werden, und wird ein wenig verschoben werden, eine Abweichung zeigt.
Sehen Sie sich die folgenden Bilder an, um zu verstehen, was passiert.
Das Problem ist, dass, obwohl MSDN sagt, dass GET_X_LPARAM(wParam)
und GET_Y_LPARAM(wParam)
richtige Werte in der Prozedur des Tray-Icon geben soll, aber es funktioniert nicht, in Gegenwart von DPI-Skalierung (dh für ein Ändern Sie die DPI-Skalierung, ohne eine Abmeldung durchzuführen und sich anzumelden). Auf der anderen Seite gibt die API GetCursorPos()
den korrekten Wert der Mauszeigerkoordinaten zurück. Beachten Sie, dass NOTIFYICON_VERSION_4
zusammen mit GetCursorPos()
nicht funktioniert, da das Kontextmenü über die Tastatur aufgerufen werden kann, bei der der Mauszeiger an beliebiger Stelle auf dem Bildschirm sein kann.
Also, wie kombinieren Sie alle soeben erlernten Kenntnisse, um das Kontextmenü des Tray-Icons korrekt anzuzeigen, wenn DPI-Skalierung in der oben beschriebenen Weise durchgeführt wird, ohne dass Sie pro DPI-fähige Anwendungen pro Monitor DPI-fähig machen GET_X_LPARAM(wParam)
und GET_Y_LPARAM(wParam)
geben immer den korrekten Wert zurück)?
Verwenden Sie NOTIFYICON_VERSION
anstelle von NOTIFYICON_VERSION_4
, dies wird den Mauszeiger auf das Tray-Symbol positionieren, wenn das Kontextmenü aufgerufen wird, und dann GetCursorPos()
verwenden, um die Position des Mauszeigers zu erhalten. Zeigen Sie das Kontextmenü mit TrackPopupMenu()
mit den Koordinaten an.
PS: Im obigen Beispiel wurde der DPI-Skalierungswert von 150% auf 125% geändert. Die Abweichung des Kontextmenüs ist stärker ausgeprägt, wenn die DPI-Skalierung von einem größeren Wert zu einem kleineren Wert erfolgt, wenn sich Ihr Taskleistensymbolbereich unten rechts auf dem Bildschirm befindet. Dies liegt daran, dass bei der DPI-Skalierung und der Vergrößerung von UI-Elementen, die nicht pro Monitor überwacht werden, mithilfe der DPI-Virtualisierung die Objekte nach rechts und nach unten verschoben werden. z.B. Wenn in einer Anwendung ein Fensterrechteck (0,0,100,100) (Bildschirmkoordinaten) ist, dann kann es nach der Vergrößerung auf 150% (0,0,150,150) werden. Wenn Sie nun für das Symbol des Taskleistensymbols Koordinaten angeben, die sich rechts unten auf dem Bildschirm befinden, wird das Betriebssystem immer noch in der unteren rechten Position angezeigt, die innerhalb des Bildschirms liegt. Dadurch wird sichergestellt, dass das Menü ordnungsgemäß angezeigt wird. z.B. Wenn ein Bildschirm 1920x1080 ist und TrackPopupMenu()
(10000,10000) für Menü angegeben ist, wird das Menü immer noch im Bildschirmrechteck von 1920x1080 angezeigt. Eine Erhöhung der DPI-Skalierung verschiebt das Kontextmenü daher nicht weiter, wenn es bereits die rechte untere Position erreicht hat.
Die richtige Lösung für das Problem ist, das Programm DPI-bewusst zu machen. Laden Sie 'SetProcessDpiAwareness()' zur Laufzeit bei Bedarf dynamisch. – andlabs
Beachten Sie auch, wenn das Popupfenster über die Tastatur aufgerufen wird, können Sie ['Shell_NotifyIconGetRect()'] (https://msdn.microsoft.com/en-us/library/windows/desktop/dd378426 (v = vs.85) .aspx), um die aktuelle Bildschirmposition des Symbols selbst zu erhalten, anstatt 'GetCursorPos()' zu verwenden, um die aktuelle Bildschirmposition der Maus zu erhalten. –
@andlabs Nein, ist es nicht.Denn wenn Sie den Prozess pro Monitor DPI bewusst machen, dann müssen Sie die Skalierung jedes UI-Elements selbst vornehmen. Viele Entwickler wollen die DPI-Virtualisierung dennoch teilweise nutzen. Wenn Ihre Anwendung außerdem eine Binärdatei von einem Drittanbieter verwendet, der UI-Elemente erstellt, können Sie die DPI-Skalierung nicht verarbeiten, da Sie den Code nicht haben. Dies war der Hauptgrund, der Microsoft veranlasste, eine neue API in Windows 10 Aniversary Update, SetThreadDpiAwarenessContext() einzuführen. –