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:
Die Lösung muss unter Windows 7, 8 und 10 (und idealerweise auch zukünftigen Versionen) funktionieren.
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.
Mein erster Gedanke war, dass ich Visual Styles richtig aktivieren muss.
In diesem Artikel werden Aufrufe überprüft Die Betriebssystemversion erhält Windows 8 , wenn Sie Windows 10 nicht explizit über ein Manifest anvisieren. Klicken Sie hier, um mein Manifest anzuzeigen . Das funktioniert:
Hier sind einige Screenshots der relevanten Projekteinstellungen, die ich ausprobiert habe:
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.
HMODULE themeFile = LoadLibraryEx(TEXT("C:\Windows\Resources\Themes\aero\aero.msstyles"), NULL, LOAD_LIBRARY_AS_DATAFILE);
GetThemeStream(h, WP_MAXBUTTON, MAXBS_NORMAL, TMT_DISKSTREAM, (void**)&buffer, &bufferSize, themeFile);
Idee 2: Kopieren Sie den Nicht-Client-Bereich aus einem ausgeblendeten Fenster mit dem Beschriftungsbereich (und Minimieren, Maximieren, Schließen).
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:
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.
Tags und Links c visual-c++ winapi