ysc3839 / win32-darkmode

Example application shows how to use undocumented dark mode API introduced in Windows 10 1809.
MIT License
437 stars 48 forks source link

Dark menu bar drawing using UAH messages #17

Closed adzm closed 3 years ago

adzm commented 3 years ago

Dark menu bar drawing!

image

adzm commented 3 years ago

For whatever reason, the dark mode theme in Windows does not define all the different parts, presumably because it is only implementing the ones used by explorer. Using the pop-up item instead of the bar item allows it to use the dark mode theme, otherwise it will draw without dark mode. Really I could probably just fill it with a black brush; thinking about it now, I wonder if the white line at the bottom is an artifact of the pop-up item, and maybe I should just use a black brush instead.

On Sat, Feb 20, 2021, 11:34 AM Jeremy Collake notifications@github.com wrote:

NIce! What is the rationale for MENU_POPUPITEM instead of MENU_BARITEM for DrawThemeBackground?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/ysc3839/win32-darkmode/pull/17#issuecomment-782711299, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABZYAFYYTAW6XEDJTSVXV6TS77QABANCNFSM4XEZMTNQ .

ysc3839 commented 3 years ago

This project aims to use existing APIs to enable dark mode, without using owner draw. I'm considering creating a new branch for owner draw code.

Also IIRC menu bar owner draw can be done without undocumented APIs. I will write a demo.

jeremycollake commented 3 years ago

@adzm Thanks for the clarification on MENU_POPUPITEM

Have you tried this code with 'custom' Windows themes? For instance, 'Themes and Related Settings', then click on any of the stock themes. I have had some weird painting issues. In plain dark or light mode, it works fine.

adzm commented 3 years ago

Makes sense, and I understand. I think the menu bar won't let itself be custom drawn without disabling themes for the window though.

On Mon, Feb 22, 2021, 3:27 PM Richard Yu notifications@github.com wrote:

This project aims to use existing APIs to enable dark mode, without using owner draw. I'm considering creating a new branch for owner draw code.

Also IIRC menu bar owner draw can be done without undocumented APIs. I will write a demo.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/ysc3839/win32-darkmode/pull/17#issuecomment-783652778, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABZYAF7VGEYP2YOM4HZQZ7DTAK42VANCNFSM4XEZMTNQ .

adzm commented 3 years ago

Ah, I have not tried those, though makes sense that it would use those theme styles and not work as expected. You would probably just have to draw everything rather than delegate to the DrawTheme APIs

On Mon, Feb 22, 2021, 3:43 PM Jeremy Collake notifications@github.com wrote:

@adzm https://github.com/adzm Thanks for the clarification on MENU_POPUPITEM

Have you tried this code with 'custom' Windows themes? For instance, 'Themes and Related Settings', then click on any of the stock themes. I have had some weird painting issues. In plain dark or light mode, it works fine.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/ysc3839/win32-darkmode/pull/17#issuecomment-783662263, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABZYAF2Q5K2VBXLKXAZCTE3TAK6Y5ANCNFSM4XEZMTNQ .

jeremycollake commented 3 years ago

Here is what I'm seeing, FWIW. Also, when the window is repositioned or resized, the menu bar isn't redrawn.

The curious thing is it works great when a custom Windows theme isn't used. Dark and light modes are fine. So far, I've yet to discern the difference.

Recording #13

Again, great work @azdm!

And, of course, excellent work on this repo @ysc3839 .. It has been immensely useful. Windows lack of documented, complete Win32 dark mode support has been quite frustrating!

KnIfER commented 3 years ago

Thanks. I need this to create my video player! But... How to enable dark mode for my application and ignore system settings?

jeremycollake commented 3 years ago

Thanks. I need this to create my video player! But... How to enable dark mode for my application and ignore system settings?

It is best to abide by the Windows dark mode setting. This code depends on that.

Users who want to run Windows in one mode and your app in another are surely edge cases not worth the substantial increase in code complexity to accommodate them.

That said, my app does technically support dark mode regardless of Windows setting, but it isn't pretty, or complete. It only exists because I was working towards dark mode prior to finding this repo.

jeremycollake commented 3 years ago

I found that the painting issue occurs when this code is enabled while the Windows app color mode is 'light'. Although the code could simply be disabled when not in dark mode, ideally it should work in either. Can anyone confirm?

jeremycollake commented 3 years ago

@adzm I derived from your UAH menubar code here and this NPP PR from you.

I published my adapted code here (originally a fork of this repository)

I've credited you and, of course, @ysc3839.

Thank you both!

ysc3839 commented 3 years ago

@jeremycollake Personally I don't suggest using undocumented API when documented API is available. IIRC it's possible to use menu owner draw to implement dark mode. Currently I have no time writing a demo, so please wait more if you want to see that.

jeremycollake commented 3 years ago

Agreed, it is a calculated risk. I'll keep an eye out for further demos from you to show me how to do it right!

ysc3839 commented 3 years ago

By saying "I don't suggest using undocumented API when documented API is available", I won't merge this PR. This project is trying to make use of existing API to enable dark mode, instead of drawing dark mode. I will keep this PR open for a place to discuss, or open an issue.

If anyone interested in owner draw dark menu, take a look at ImmersiveContextMenu.

adzm commented 3 years ago

That does not draw the menubar dark though, just the popup menu. I believe you can indeed set custom colors for the menubar but only if you disable themes for the window, which has its own downsides. I understand not wanting to merge this into the repo though. The UAH approach is pretty neat since it does let you do other random things too like drawing graphics or whatever easily into the menubar.

Anyway, there does not seem to be any alternative to using this UAH approach to get a custom menubar short of creating a menubar yourself (which means it is no longer part of the nonclient window area) or perhaps disabling themes and trying the old ways.

@jeremycollake you may want to check out a later push to notepad++ which overwrites the white line under the menu, which I was unable to figure out how to get rid of (though did eventually figure out how to simply overwrite it)

ysc3839 commented 3 years ago

@adzm That project is not the owner draw menu bar I said before. It's another project using only documented API to implement a dark mode. And theoretically it supports Windows 8.1 (because 8.1 has those theme) or even Windows 7 (by drawing colors yourself without relying theme).

ysc3839 commented 3 years ago

@adzm Sorry for my late. I made minor changes to make ImmersiveContextMenu support menu bar owner draw. https://github.com/ysc3839/ImmersiveContextMenu/commit/692eb9ccef05df717256c2b45bf0b429e8fd6b68 image If you don't need context menu owner draw, the code can be reduced. This is just a demo to show possibility of menu bar owner draw.

ysc3839 commented 3 years ago

If you don't want to apply owner draw to context menu, just make these changes:

diff --git a/ImmersiveContextMenu.hpp b/ImmersiveContextMenu.hpp
index f520e11..6225494 100644
--- a/ImmersiveContextMenu.hpp
+++ b/ImmersiveContextMenu.hpp
@@ -205,13 +205,13 @@ namespace ImmersiveContextMenu
                        if (SetMenuItemInfoW(hMenu, i, TRUE, &mii))
                        {
                            hr = S_OK;
-                           if (mii.hSubMenu)
+                           /*if (mii.hSubMenu)
                            {
                                if (WI_IsFlagSet(icmoFlags, ICMO_OVERRIDECOMPATCHECK))
                                    HandleMergedMenus(mii.hSubMenu, hWnd);
                                else
                                    ApplyOwnerDrawToMenu(mii.hSubMenu, hWnd, point, (icmoFlags & ~ICMO_MENUBAR) | ICMO_ICMBRUSHAPPLIED, cmrdArray);
-                           }
+                           }*/
                        }
                    }
                    renderData->parentArray = cmrdArray;
@@ -349,7 +349,7 @@ namespace ImmersiveContextMenu

        MENUINFO mi = {
            .cbSize = sizeof(mi),
-           .fMask = MIM_APPLYTOSUBMENUS | MIM_BACKGROUND,
+           .fMask = /*MIM_APPLYTOSUBMENUS | */MIM_BACKGROUND,
            .hbrBack = CreateSolidBrush(color)
        };
        RETURN_IF_WIN32_BOOL_FALSE(SetMenuInfo(hMenu, &mi));

image

adzm commented 2 years ago

This is great! Thanks for figuring it out.

On Sun, Sep 12, 2021, 10:45 PM Richard Yu @.***> wrote:

If you don't want to apply owner draw to context menu, just make these changes:

diff --git a/ImmersiveContextMenu.hpp b/ImmersiveContextMenu.hpp index f520e11..6225494 100644--- a/ImmersiveContextMenu.hpp+++ b/ImmersiveContextMenu.hpp@@ -205,13 +205,13 @@ namespace ImmersiveContextMenu if (SetMenuItemInfoW(hMenu, i, TRUE, &mii)) { hr = S_OK;- if (mii.hSubMenu)+ /if (mii.hSubMenu) { if (WI_IsFlagSet(icmoFlags, ICMO_OVERRIDECOMPATCHECK)) HandleMergedMenus(mii.hSubMenu, hWnd); else ApplyOwnerDrawToMenu(mii.hSubMenu, hWnd, point, (icmoFlags & ~ICMO_MENUBAR) | ICMO_ICMBRUSHAPPLIED, cmrdArray);- }+ }/ } } renderData->parentArray = cmrdArray;@@ -349,7 +349,7 @@ namespace ImmersiveContextMenu

  MENUINFO mi = {
      .cbSize = sizeof(mi),-          .fMask = MIM_APPLYTOSUBMENUS | MIM_BACKGROUND,+         .fMask = /*MIM_APPLYTOSUBMENUS | */MIM_BACKGROUND,
      .hbrBack = CreateSolidBrush(color)
  };
  RETURN_IF_WIN32_BOOL_FALSE(SetMenuInfo(hMenu, &mi));

[image: image] https://user-images.githubusercontent.com/12028138/133016215-24eda841-6cb9-4db4-b2d6-793a012b1b97.png

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/ysc3839/win32-darkmode/pull/17#issuecomment-917791332, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABZYAF3VQDEMIWXMXNAIND3UBVQTFANCNFSM4XEZMTNQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.