Glatte Fenstergrößenanpassung in Windows (mit Direct2D 1.1)?

9

Es nervt mich, dass die Größenanpassung von Fenstern in Windows nicht so "glatt" ist, wie ich es gerne hätte (das ist bei Windows-Programmen im Allgemeinen der Fall und nicht bei meinen. Visual Studio ist ein gutes Beispiel) ). Es macht das Betriebssystem und seine Programme "fadenscheinig" und "billig" (ja, ich sorge mich darum, wie Programme und Benutzeroberflächen sich fühlen, genauso wie mir der Klang und das Gefühl, ein Auto zu schließen, am Herzen liegt) Es ist ein Spiegelbild der Verarbeitungsqualität, was meines Erachtens die gesamte UX und letztlich die Wahrnehmung der Marke beeinflusst.

Das Neuzeichnen von Fensterinhalten hält einfach nicht mit der Mausbewegung während der Größenänderung Schritt. Immer wenn ich die Größe eines Fensters ändere, gibt es einen "stotternden" / "flackernden" Effekt, scheinbar aufgrund des Inhalts der vorherigen Größe des Fensters, das in dem neuen, größenveränderten Fensterrahmen neu gezeichnet wird, bevor der neue, größenveränderte Inhalt gezeichnet wird. p>

Ich baue eine Win32-Anwendung (x64), die Direct2D 1.1 verwendet, um seine Benutzeroberfläche zu zeichnen, und angesichts der Geschwindigkeit von Direct2D sollte es 2014 nicht notwendig sein, solche Artefakte in einem OS zu erleiden. Ich bin selbst auf Windows 8.1 , aber mit dieser Anwendung auf Windows 7 abzielen.

Der Effekt "vorhergehende Größe" ist besonders dann zu erkennen, wenn ein kleines Fenster maximiert wird (da der Unterschied in der Fenstergröße groß genug ist, um das Bild des alten Inhalts leicht zu kontrastieren, wenn es in der oberen linken Ecke des größeren Fensters kurz blinkt) der neue Inhalt wird anschließend übermalt).

Dies scheint so zu sein:

  1. (Nehmen wir an, es gibt ein vollständig gerendertes Fenster auf dem Bildschirm, Größe 500 x 500 Pixel).
  2. Ich maximiere das Fenster:
  3. Der Fensterrahmen ist maximiert
  4. Der alte 500 x 500 Inhalt wird im neuen Rahmen gezeichnet, bevor ..
  5. .. das maximierte Fenster wird mit Inhalt in der richtigen Größe neu gezeichnet.

Ich frage mich, ob es eine Möglichkeit gibt, dies zu mildern (z. B. loszuwerden Schritt 4) - zum Beispiel abfangen einer Windows-Nachricht - und vermeiden Sie das Fenster in der neuen Größe mit dem alten Inhalt vor der endgültigen re neu gemalt werden -Rendering des neuen Inhalts passiert. Es ist so, als wenn Windows das Fenster neu erstellt und dabei die bereits verfügbaren Grafiken verwendet, BEVOR es mich stört, dass ich aktualisierte Inhalte mit einer WM_PAINT-Nachricht oder ähnlichem bereitstellen soll.

Kann es gemacht werden?

Bearbeiten: Es scheint, dass WM_WINDOWPOSCHANGING / WM_SIZING einen "frühen Zugriff" auf die neuen Größen bietet, aber es ist mir immer noch nicht gelungen, das Bild des alten zu unterdrücken Inhalt.

Mein WndProc sieht so aus:

%Vor%

Das Fenster hat nicht CS_HREDRAW oder CS_VREDRAW gesetzt. Die Swapchain ist doppelt gepuffert und der Aufruf Present wird mit SyncInterval = 0 gemacht.

Ich bin mir bewusst, dass das erneute Erstellen der Swapchain-Puffer bei jeder Änderung der Fenstergröße einen einigen Overhead im Vergleich zum einfachen Neuzeichnen auf einer statischen Fensteroberfläche erzeugt. Das "Stottern" wird jedoch nicht dadurch verursacht, wie es auch passiert, wenn die Größenänderung des Puffers deaktiviert ist und vorhandener Fensterinhalt während der Fenstergrößenanpassung einfach skaliert macht ) es geht besser mit Mausbewegung).

    
d7samurai 17.02.2014, 08:12
quelle

5 Antworten

0

Obwohl Ihr Ziel lobenswert ist, vermute ich, dass jeder Versuch, dies zu tun, nur als Kampf zwischen Ihnen und Windows enden wird - den Sie nicht gewinnen werden (obwohl Sie es vielleicht schaffen würden, sich zu einem ehrenhaften Remis zu kämpfen). Tut mir leid, negativ zu sein.

    
Tim Bergel 16.02.2014 20:53
quelle
0

Setzen Sie WM_SETREDRAW auf FALSE, nehmen Sie die Größenänderung vor, und aktivieren Sie die Zeichnung erneut, machen Sie das Fenster ungültig und das Betriebssystem blittiert es.

Ich habe dies für das Aktivieren und Deaktivieren von Schaltflächen bei der Auswahl verschiedener Elemente aus einer Liste getan, niemals für ein ganzes Fenster.

    
graham.reeds 17.02.2014 07:04
quelle
0

Wenn Sie ein randloses untergeordnetes Fenster (der Typ, der nur innerhalb des übergeordneten Elements rendert) in einer festen Größe (wie in der Vollbildauflösung) haben, sollten Sie viel glattere Ergebnisse erhalten, da es keine Speicherumleitung gibt (was ich denke was ist) verursacht die Jitterie).

Wenn es immer noch nicht perfekt ist, schaue sowohl in WM_SIZE als auch in WM_SIZING nach und überprüfe, ob du mit ihnen zaubern kannst. Zum Beispiel könnten Sie in WM_SIZING wahr aussagekräftige Windows zurückgeben, dass Sie die Nachricht bearbeitet haben (Fenster so belassen wie sie ist) und Ihre UI in einen Puffer mit der von WM_SIZING bereitgestellten Größe rendern und wenn dies geschehen ist, senden Sie Ihre eigene WM_SIZING aber mit einem manipulierten unbenutzten Bit in WPARAM (zusammen mit seinem vorherigen Inhalt), das Ihnen sagt, dass Sie einen vorgerenderten Puffer dafür haben, den Sie einfach blit-out können. Aus der WM_SIZING Dokumentation auf msdn sieht es so aus, als ob WPARAM ein paar Bits zu Ihrer Verfügung haben sollte.

Hoffe, das hilft.

    
Pritam 11.04.2014 15:28
quelle
0

Das ist das Beste, was ich mir ausgedacht habe, und die Größe ist großartig, obwohl das Backbuffer-Blitting Kantenflackern verursacht, noch nicht mit DX oder OGL getestet wurde, aber es sollte noch besser mit Hardwarebeschleunigung funktionieren. Es ist ein bisschen sperrig, aber wird als Beweis des Konzeptes tun.

Wenn die Zeichenfläche ohne Verwendung von MDI abgeschnitten werden könnte, wäre das sogar noch besser, wie bei Verwendung eines Bitmaskenpuffers.

Eine Sache, über die ich nicht glücklich bin, sind die Positionskoordinaten des untergeordneten Fensters, da sie möglicherweise nicht auf allen Systemen funktionieren, aber eine Kombination von GetSystemMetrics-Aufrufen, um Rand- und Beschriftungsgrößen zu erhalten, sollte das beheben.

%Vor%

Edit: Ein weiteres Beispiel mit "bitmask" / layered window.

%Vor%     
Pritam 17.04.2014 15:02
quelle
0

Stellen Sie beim Aufruf von CreateSwapChainForHwnd sicher, dass Sie die Eigenschaft Scaling der Swap-Kette description auf DXGI_SCALING_NONE festgelegt haben. Dies wird nur unter Windows 7 mit dem Plattform-Update unterstützt, daher müssen Sie möglicherweise auf den Standard DXGI_SCALING_STRETCH zurückgreifen (letzteres verursacht das Flimmern).

    
Mark Ingram 17.11.2015 12:16
quelle

Tags und Links