2017-05-18 1 views
0

Ich geerbt eine Legacy-Anwendung, die jetzt auf Windows 10 ausgeführt werden muss. Während des Testens fanden wir, dass Teil des Programms (das ist ein untergeordnetes Fenster als Symbolleiste platziert) nur teilweise beim Start des Programms zeichnen - mehr als die Hälfte von der rechten Seite der Symbolleiste würde nur schwarz zeichnen. Zur Laufzeit sollte die Größe des gesamten Fensters geändert werden, wodurch das Symbolleistenfenster in der Größe geändert bzw. neu gezeichnet wurde. Wir fanden schließlich heraus, dass, wenn wir "Disable display scaling" einstellen, den Bug vollständig zu verhindern scheint (bis zu einem Vertrauen von knapp über 1-in-10.000 getestet, was für mich gut genug ist).Welchen Fehler habe ich wahrscheinlich mit "Disable Display Scaling" behoben?

Die Frage ist:

diese Fehler nur mit einer Wahrscheinlichkeit wahrscheinlich zwischen 12.01 und 20.01 aufgetreten (die ich von Video unserer automatischen Tests des Programms bestimmt, die zu 185 Chancen für den Bug beteiligt auftreten. Es wurde kein Muster des Auftretens festgestellt. Ich habe mich noch nie mit einem solchen Fehler herumschlagen müssen, und deshalb frage ich mich: Angesichts der offensichtlichen Zufälligkeit des Fehlers und der Lösung, was passierte? Eine Race-Bedingung zwischen dem Bitmap-Rendering, das Windows dann für "High DPI" hochskaliert und den Funktionen, die die Symbolleiste auslegen?

Antwort

1

Windows 10 erweitert das Konzept der DPI-Awareness. Früher war das DPI-Bewusstsein eine pro-Prozess-Einstellung, aber jetzt ist es ein pro-Thread-Konzept. Die MSDN docs Formulierung ist jetzt ein wenig schwer zu entziffern, aber es klingt wie das Aufrufen von SetProcessDPIAwareness (was ich erwarte, dass die Legacy-App funktioniert) betrifft nur das Aufrufen von Threads (obwohl "Process" im Namen ist).

Theorie # 1: Vielleicht wird Ihr Werkzeugleistenfenster manchmal auf einem Thread mit DPI-Bewusstsein erstellt und manchmal ist es in einem anderen Thread erstellt.

Theorie # 2: Es gibt einen Wettlauf zwischen der App, die SetProcessDPIAware aufruft, und einem UI-Code, der eine Anzeigemessgröße zwischenspeichert, die später zum Zeichnen des Symbolleistenfensters verwendet wird. Abhängig davon, wer das Rennen gewinnt, können Sie das falsche Verhalten erhalten.

Die Dokumente legen nahe, dass ältere Anwendungen (ua ältere Anwendungen) DPI mithilfe der Manifesteinstellung für den gesamten Prozess festlegen. Ich glaube, das würde sicherstellen, dass die Einstellung auf alle Threads im Prozess angewendet wird, und dies sollte passieren, bevor ein Benutzercode ausgeführt wird, sodass es kein Rennen geben sollte. Da die Deaktivierung der Skalierung das Problem zu lösen scheint und die Einstellung der DPI-Erkennung ungefähr gleichwertig sein sollte (in der Praxis), würde ich erwarten, dass das Problem gelöst wird, wenn eine der beiden Theorien richtig ist.

Die documentation for SetProcessDpiAware erläutert, wie DPI-Awareness mit einem Manifest festgelegt wird.

+0

Ich denke * Ich verstehe das in Ihrem ersten Absatz, aber nur um sicher zu sein - ich verwende die Kompatibilitätsflags entweder in der Verknüpfung oder für die "Eigenschaften" der EXE selbst (wie in der Registrierung festgelegt)) um DPI-Awareness zu deaktivieren, also Sie denken, dass SetProcessDPIAwareness aufgerufen wird, weil das gesetzt ist? Manifeste werden wahrscheinlich in zukünftigen Versionen kommen, aber leider wird die nächste Version wahrscheinlich eine Weile dauern. –

+0

Nicht ganz. Durch das Deaktivieren der Skalierung in den Eigenschaften wird SetProcessDPIAwareness nicht aufgerufen, aber es hat ähnliche Auswirkungen. Da es scheinbar immer funktioniert, wenn Sie die Skalierung manuell deaktivieren, vermute ich, dass der Code so geschrieben wurde, dass er hohe DPI-Werte versteht. Da es manchmal funktioniert, wenn Sie die Skalierung nicht deaktivieren, denke ich, versucht das Programm dem Betriebssystem mitzuteilen, dass es DPI kennt (indem es SetProcessDPIAware oder SetProcessDPIAwareness aufruft), aber es wird nicht auf alle Threads angewendet (Windows 10 hat das geändert) eine Race-Bedingung (manchmal sagt es dem Betriebssystem etwas zu spät). –

+0

Der Code der Anwendung versteht definitiv nicht High DPI (oder vollständig verstehen), aber alle GUI-Elemente sind Standard-Win32, so dass ich nicht weiß, was dort passiert. Wir haben es auch nicht auf einem der Betriebssysteme zwischen Win 7 und Win 10 laufen lassen, so dass ich nicht in der Lage sein würde, festzustellen, welche OS-Versionen den Fehler zeigen (außer 7 und 10). Einer der anderen Gründe, warum High DPI ein Problem darstellte, war, dass das automatische Testen an der falschen Stelle klickte, wenn man versuchte, mit der Menüleiste zu interagieren ... die Race Condition scheint jetzt glaubwürdiger zu sein. –