Teile, die mit DrawThemeBackground unter Windows 10 gezeichnet wurden, sind nicht korrekt

8

Problembeschreibung

Ich möchte eine Windows API-Anwendung in C erstellen, die das Menü und die Beschriftungsschaltflächen im selben Nicht-Client-Bereich wie Firefox darstellt

Um dies zu tun, habe ich bestimmt, die Lösung muss:

  • sei WS_POPUP, damit das Menü nach oben ausgerichtet wird
  • Übernehmen Sie den Besitz des Nicht-Kundenbereichs (wo das Menü gerendert wird)
  • Rendern Sie die Schaltflächen zum Minimieren / Maximieren / Schließen
  • manuell

Die Lösung muss unter Windows 7, 8 und 10 (und idealerweise auch zukünftigen Versionen) funktionieren.

Wie es jetzt aussieht

Ich habe ein Testprogramm auf GitHub verfügbar .

In meiner App habe ich die entsprechenden Ereignisse außer Kraft gesetzt:

WM_NCCALCSIZE , WM_NCHITTEST , WM_NCLBUTTONDOWN , WM_NCLBUTTONUP , WM_NCMOUSEMOVE , WM_NCPAINT

Und dann male ich nicht-kundenbezogene Bereiche für diese Ereignisse neu: WM_NCACTIVATE , WM_SETTEXT

Hier ist ein Beispiel, wie ich das Rendering mache:

%Vor%

Das gerenderte Ergebnis sieht folgendermaßen aus: Leider sehen die für die Teile verwendeten Stile (Minimieren, Maximieren / Wiederherstellen, Schließen) aus wie die Stile für Windows 7/8 und nicht die nativen Windows 10-Steuerelemente . Ich habe mehrere Tage lang nach einem Weg gesucht, dies ohne Glück zu machen. Ich brauche Hilfe zu verstehen, wie diese Schaltflächen für Windows 10 mit der Windows-API zu rendern.

Aktueller Status (und was ich bisher versucht habe)

Mein erster Gedanke war, dass ich Visual Styles richtig aktivieren muss.

Hier sind einige Screenshots der relevanten Projekteinstellungen, die ich ausprobiert habe:

Andere Ideen

Mir geht es schlecht, um es zu versuchen. Bevor ich das Handtuch warf, gab es einige Dinge, die ich ausprobieren wollte:

  • Idee 1: Verwenden Sie GetThemeStream ermöglicht es Ihnen, die Größe / Bitmap für Steuerelemente abzurufen.

    • Laden Sie die aero msstyles-Datei wie folgt:

    HMODULE themeFile = LoadLibraryEx(TEXT("C:\Windows\Resources\Themes\aero\aero.msstyles"), NULL, LOAD_LIBRARY_AS_DATAFILE);

    • Holen Sie die Bitmap für den Teil (Schaltfläche minimieren, Schaltfläche maximieren usw.) wie folgt (Übergabe der geladenen Motivdatei):

    GetThemeStream(h, WP_MAXBUTTON, MAXBS_NORMAL, TMT_DISKSTREAM, (void**)&buffer, &bufferSize, themeFile);

    • Laden Sie die Bitmap; es scheint im PNG-Format zu sein (ich bin nicht so weit gekommen)
    • Zeichnen Sie die Bitmap
  • Idee 2: Kopieren Sie den Nicht-Client-Bereich aus einem ausgeblendeten Fenster mit dem Beschriftungsbereich (und Minimieren, Maximieren, Schließen).

    • Erstellen Sie ein Fenster, in dem die Beschriftung und die Min / Max-Schaltflächen nicht aktiviert sind.
    • Erhalte in der Nicht-Client-Farbe den DC für dieses Fenster und zeichne die Pixel für die Min / Max / Close-Schaltfläche
    • auf
    • Rendere sie mit bitblt
Brian Clifton 04.09.2016, 17:07
quelle

1 Antwort

0

Ich denke, das Problem kommt von dem Versuch, WM_NCPAINT auf der Betriebssystemversion zu verwenden & gt; = Vista zu gewinnen. Seit Vista wird das gesamte NC-Rendering von DWM (Desktop Window Manager) gesteuert. Wenn Sie es immer noch wagen, mit WM_NCPAINT umzugehen, wird das DWM-Rendering deaktiviert und Sie erhalten ein "Old School" -Look:

Aus dem Shell Revealed Blog :

  

Die DWM hat keine Bedenken, weil Anwendungen dies nicht können   Zeichnen Sie in den Glasrahmen, da es von einem gerendert und verwaltet wird   völlig anderer Prozess. Wenn eine Anwendung es versucht, Windows   wird es erkennen und den Glasrahmen vollständig entfernen (und deshalb   zum Grundbild zurückkehren), damit die Anwendung zeichnen kann, was es ist   möchte zeichnen.

Um korrekte Ergebnisse zu erhalten, müssen Sie die " DWM-Weg " (speziell die Abschnitte "Entfernen des Standardrahmens" und "Zeichnen im erweiterten Rahmenfenster"). Dies funktioniert, indem DWM den Frame im Clientbereich rendert, sodass Sie über darauf malen können. Auch bei dieser Lösung müssen Sie die Beschriftungsschaltflächen nicht selbst zeichnen. Diese Antwort fasst die erforderlichen Schritte zusammen (unter "Aero-unterstützte Lösung").

Der Nachteil ist, dass Sie das Menü wahrscheinlich selbst zeichnen müssen und Sie die meisten GDI-API dafür nicht verwenden können, weil GDI den Alphakanal ignoriert und die Dinge hässlich aussehen, wenn der Rahmen durchsichtig ist (Vista und Win 7 standardmäßig, Win8 + mit Erweiterungen). BitBlt() funktioniert, wenn die Quelle ein Speicher-DC ist, der eine 32-Bit-Bitmap mit einem Alphakanal enthält. GDI + funktioniert auch.

    
zett42 28.04.2017 20:41
quelle

Tags und Links