Mercurial > dwindows
comparison win/dw.c @ 1969:2322769acf88
Win: More Dark Mode work, code based on information found on github...
https://github.com/ysc3839/win32-darkmode/tree/master/win32-darkmode
author | bsmith@81767d24-ef19-dc11-ae90-00e081727c95 |
---|---|
date | Fri, 02 Aug 2019 00:44:52 +0000 |
parents | d510e9bb61c2 |
children | 8cf330e1e331 |
comparison
equal
deleted
inserted
replaced
1968:abb949dd3bb3 | 1969:2322769acf88 |
---|---|
206 #endif | 206 #endif |
207 | 207 |
208 #ifdef AEROGLASS | 208 #ifdef AEROGLASS |
209 HRESULT (WINAPI *_DwmExtendFrameIntoClientArea)(HWND hWnd, const MARGINS *pMarInset) = 0; | 209 HRESULT (WINAPI *_DwmExtendFrameIntoClientArea)(HWND hWnd, const MARGINS *pMarInset) = 0; |
210 HRESULT (WINAPI *_DwmIsCompositionEnabled)(BOOL *pfEnabled) = 0; | 210 HRESULT (WINAPI *_DwmIsCompositionEnabled)(BOOL *pfEnabled) = 0; |
211 HRESULT (WINAPI *_DwmSetWindowAttribute)(HWND, DWORD, LPCVOID, DWORD) = 0; | |
211 HTHEME (WINAPI *_OpenThemeData)(HWND hwnd, LPCWSTR pszClassList) = 0; | 212 HTHEME (WINAPI *_OpenThemeData)(HWND hwnd, LPCWSTR pszClassList) = 0; |
212 HPAINTBUFFER (WINAPI *_BeginBufferedPaint)(HDC hdcTarget, const RECT *prcTarget, BP_BUFFERFORMAT dwFormat, BP_PAINTPARAMS *pPaintParams, HDC *phdc) = 0; | 213 HPAINTBUFFER (WINAPI *_BeginBufferedPaint)(HDC hdcTarget, const RECT *prcTarget, BP_BUFFERFORMAT dwFormat, BP_PAINTPARAMS *pPaintParams, HDC *phdc) = 0; |
213 HRESULT (WINAPI *_BufferedPaintSetAlpha)(HPAINTBUFFER hBufferedPaint, const RECT *prc, BYTE alpha) = 0; | 214 HRESULT (WINAPI *_BufferedPaintSetAlpha)(HPAINTBUFFER hBufferedPaint, const RECT *prc, BYTE alpha) = 0; |
214 HRESULT (WINAPI *_DrawThemeTextEx)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwFlags, LPRECT pRect, const DTTOPTS *pOptions) = 0; | 215 HRESULT (WINAPI *_DrawThemeTextEx)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwFlags, LPRECT pRect, const DTTOPTS *pOptions) = 0; |
215 HRESULT (WINAPI *_EndBufferedPaint)(HPAINTBUFFER hBufferedPaint, BOOL fUpdateTarget) = 0; | 216 HRESULT (WINAPI *_EndBufferedPaint)(HPAINTBUFFER hBufferedPaint, BOOL fUpdateTarget) = 0; |
669 } | 670 } |
670 return NULL; | 671 return NULL; |
671 } | 672 } |
672 #endif | 673 #endif |
673 | 674 |
675 #ifdef AEROGLASS | |
674 int _DW_DARK_MODE_ALLOWED = FALSE; | 676 int _DW_DARK_MODE_ALLOWED = FALSE; |
675 | 677 int _DW_DARK_MODE_SUPPORTED = FALSE; |
676 /* Call this on a window to apply the style */ | 678 int _DW_DARK_MODE_ENABLED = FALSE; |
677 BOOL CALLBACK _set_child_window_theme(HWND window, LPARAM lParam) | 679 |
678 { | 680 typedef enum IMMERSIVE_HC_CACHE_MODE |
679 static int initialized = FALSE; | 681 { |
680 static BOOL (WINAPI * AllowDarkModeForWindow)(HWND a_HWND, BOOL a_Allow) = NULL; | 682 IHCM_USE_CACHED_VALUE, |
681 | 683 IHCM_REFRESH |
682 if(initialized == FALSE && dwVersion) | 684 } IMMERSIVE_HC_CACHE_MODE; |
685 | |
686 typedef enum _PreferredAppMode | |
687 { | |
688 _Default, | |
689 _AllowDark, | |
690 _ForceDark, | |
691 _ForceLight, | |
692 _Max | |
693 } _PreferredAppMode; | |
694 | |
695 HTHEME (WINAPI * _OpenNcThemeData)(HWND, LPCWSTR) = NULL; | |
696 VOID (WINAPI * _RefreshImmersiveColorPolicyState)(VOID) = NULL; | |
697 BOOL (WINAPI * _GetIsImmersiveColorUsingHighContrast)(IMMERSIVE_HC_CACHE_MODE) = NULL; | |
698 BOOL (WINAPI * _ShouldAppsUseDarkMode)(VOID) = NULL; | |
699 BOOL (WINAPI * _AllowDarkModeForWindow)(HWND, BOOL) = NULL; | |
700 BOOL (WINAPI * _AllowDarkModeForApp)(BOOL) = NULL; | |
701 _PreferredAppMode (WINAPI * _SetPreferredAppMode)(_PreferredAppMode) = NULL; | |
702 BOOL (WINAPI * _IsDarkModeAllowedForWindow)(HWND) = NULL; | |
703 BOOL (WINAPI * _ShouldSystemUseDarkMode)(VOID) = NULL; | |
704 | |
705 void _dw_init_dark_mode(void) | |
706 { | |
707 if(_DW_DARK_MODE_ALLOWED && dwVersion && huxtheme) | |
683 { | 708 { |
684 /* Dark mode is introduced in Windows 10 (1809) build 17763 */ | 709 /* Dark mode is introduced in Windows 10 (1809) build 17763 */ |
685 if(LOBYTE(LOWORD(dwVersion)) >= 10 && HIWORD(dwVersion) >= 17763) | 710 if(LOBYTE(LOWORD(dwVersion)) >= 10 && HIWORD(dwVersion) >= 17763) |
686 AllowDarkModeForWindow = (BOOL (WINAPI *)(HWND, BOOL))GetProcAddress(huxtheme, MAKEINTRESOURCEA(133)); | 711 { |
687 initialized = TRUE; | 712 _OpenNcThemeData = (HTHEME (WINAPI *)(HWND, LPCWSTR))GetProcAddress(huxtheme, MAKEINTRESOURCEA(49)); |
688 } | 713 _RefreshImmersiveColorPolicyState = (VOID (WINAPI *)(VOID))GetProcAddress(huxtheme, MAKEINTRESOURCEA(104)); |
689 if(AllowDarkModeForWindow) | 714 _GetIsImmersiveColorUsingHighContrast = (BOOL (WINAPI *)(IMMERSIVE_HC_CACHE_MODE))GetProcAddress(huxtheme, MAKEINTRESOURCEA(106)); |
690 { | 715 _ShouldAppsUseDarkMode = (BOOL (WINAPI *)(VOID))GetProcAddress(huxtheme, MAKEINTRESOURCEA(132)); |
691 AllowDarkModeForWindow(window, _DW_DARK_MODE_ALLOWED); | 716 _AllowDarkModeForWindow = (BOOL (WINAPI *)(HWND, BOOL))GetProcAddress(huxtheme, MAKEINTRESOURCEA(133)); |
692 if(_DW_DARK_MODE_ALLOWED && _SetWindowTheme) | 717 if(HIWORD(dwVersion) < 18334) |
693 { | 718 _AllowDarkModeForApp = (BOOL (WINAPI *)(BOOL))GetProcAddress(huxtheme, MAKEINTRESOURCEA(135)); |
694 _SetWindowTheme(window, L"DarkMode_Explorer", NULL); | 719 else |
695 } | 720 _SetPreferredAppMode = (_PreferredAppMode (WINAPI *)(_PreferredAppMode))GetProcAddress(huxtheme, MAKEINTRESOURCEA(135)); |
696 } | 721 _IsDarkModeAllowedForWindow = (BOOL (WINAPI *)(HWND))GetProcAddress(huxtheme, MAKEINTRESOURCEA(137)); |
722 _ShouldSystemUseDarkMode = (BOOL (WINAPI *)(VOID))GetProcAddress(huxtheme, MAKEINTRESOURCEA(138)); | |
723 } | |
724 /* Make sure we were able to load all the Dark Mode functions */ | |
725 if(_OpenNcThemeData && _RefreshImmersiveColorPolicyState && _ShouldAppsUseDarkMode && _AllowDarkModeForWindow && | |
726 (_AllowDarkModeForApp || _SetPreferredAppMode) && _IsDarkModeAllowedForWindow && _DwmSetWindowAttribute) | |
727 { | |
728 _DW_DARK_MODE_SUPPORTED = TRUE; | |
729 _AllowDarkModeForApp(TRUE); | |
730 _RefreshImmersiveColorPolicyState(); | |
731 } | |
732 } | |
733 } | |
734 | |
735 BOOL AllowDarkModeForWindow(HWND window, BOOL allow) | |
736 { | |
737 if(_DW_DARK_MODE_SUPPORTED) | |
738 return _AllowDarkModeForWindow(window, allow); | |
739 return FALSE; | |
740 } | |
741 | |
742 BOOL IsHighContrast(VOID) | |
743 { | |
744 HIGHCONTRASTW highContrast = { sizeof(highContrast) }; | |
745 if(SystemParametersInfoW(SPI_GETHIGHCONTRAST, sizeof(highContrast), &highContrast, FALSE)) | |
746 return highContrast.dwFlags & HCF_HIGHCONTRASTON; | |
747 return FALSE; | |
748 } | |
749 | |
750 BOOL IsColorSchemeChangeMessage(LPARAM lParam) | |
751 { | |
752 BOOL is = FALSE; | |
753 if(lParam && CompareStringOrdinal((LPCWCH)lParam, -1, L"ImmersiveColorSet", -1, TRUE) == CSTR_EQUAL) | |
754 { | |
755 _RefreshImmersiveColorPolicyState(); | |
756 is = TRUE; | |
757 } | |
758 _GetIsImmersiveColorUsingHighContrast(IHCM_REFRESH); | |
759 return is; | |
760 } | |
761 | |
762 void RefreshTitleBarThemeColor(HWND window) | |
763 { | |
764 BOOL dark = FALSE; | |
765 if (_IsDarkModeAllowedForWindow(window) && _ShouldAppsUseDarkMode() && !IsHighContrast()) | |
766 dark = TRUE; | |
767 _DwmSetWindowAttribute(window, 19, &dark, sizeof(dark)); | |
768 } | |
769 | |
770 /* Call this on a window to apply the style */ | |
771 BOOL CALLBACK _dw_set_child_window_theme(HWND window, LPARAM lParam) | |
772 { | |
773 if(_DW_DARK_MODE_SUPPORTED) | |
774 AllowDarkModeForWindow(window, _DW_DARK_MODE_ENABLED); | |
697 return TRUE; | 775 return TRUE; |
698 } | 776 } |
777 #endif | |
699 | 778 |
700 /* This function adds a signal handler callback into the linked list. | 779 /* This function adds a signal handler callback into the linked list. |
701 */ | 780 */ |
702 void _new_signal(ULONG message, HWND window, int id, void *signalfunction, void *discfunc, void *data) | 781 void _new_signal(ULONG message, HWND window, int id, void *signalfunction, void *discfunc, void *data) |
703 { | 782 { |
2221 if(_DwmExtendFrameIntoClientArea) | 2300 if(_DwmExtendFrameIntoClientArea) |
2222 _DwmExtendFrameIntoClientArea(hWnd, &mar); | 2301 _DwmExtendFrameIntoClientArea(hWnd, &mar); |
2223 } | 2302 } |
2224 } | 2303 } |
2225 break; | 2304 break; |
2305 case WM_SETTINGCHANGE: | |
2306 { | |
2307 if(_DW_DARK_MODE_SUPPORTED && IsColorSchemeChangeMessage(mp2)) | |
2308 SendMessageW(hWnd, WM_THEMECHANGED, 0, 0); | |
2309 } | |
2310 break; | |
2311 case WM_THEMECHANGED: | |
2312 { | |
2313 if(_DW_DARK_MODE_SUPPORTED) | |
2314 { | |
2315 _AllowDarkModeForWindow(hWnd, _DW_DARK_MODE_ENABLED); | |
2316 if(GetParent(hWnd) == HWND_DESKTOP) | |
2317 RefreshTitleBarThemeColor(hWnd); | |
2318 } | |
2319 } | |
2320 break; | |
2226 #endif | 2321 #endif |
2227 #ifdef AEROGLASS1 | 2322 #ifdef AEROGLASS1 |
2228 case WM_ERASEBKGND: | 2323 case WM_ERASEBKGND: |
2229 if(_dw_composition && (GetWindowLongPtr(hWnd, GWL_EXSTYLE) & WS_EX_LAYERED)) | 2324 if(_dw_composition && (GetWindowLongPtr(hWnd, GWL_EXSTYLE) & WS_EX_LAYERED)) |
2230 { | 2325 { |
2231 static HBRUSH hbrush = 0; | 2326 static HBRUSH hbrush = 0; |
2232 RECT rect; | 2327 RECT rect; |
2237 GetClientRect(hWnd, &rect); | 2332 GetClientRect(hWnd, &rect); |
2238 FillRect((HDC)mp1, &rect, hbrush); | 2333 FillRect((HDC)mp1, &rect, hbrush); |
2239 return TRUE; | 2334 return TRUE; |
2240 } | 2335 } |
2241 break; | 2336 break; |
2242 #endif | 2337 #endif |
2243 case WM_PAINT: | 2338 case WM_PAINT: |
2244 { | 2339 { |
2245 PAINTSTRUCT ps; | 2340 PAINTSTRUCT ps; |
2246 | 2341 |
2247 BeginPaint(hWnd, &ps); | 2342 BeginPaint(hWnd, &ps); |
3994 #ifdef AEROGLASS | 4089 #ifdef AEROGLASS |
3995 /* Attempt to load the Desktop Window Manager and Theme library */ | 4090 /* Attempt to load the Desktop Window Manager and Theme library */ |
3996 if(huxtheme && (hdwm = LoadLibrary(TEXT("dwmapi")))) | 4091 if(huxtheme && (hdwm = LoadLibrary(TEXT("dwmapi")))) |
3997 { | 4092 { |
3998 _DwmExtendFrameIntoClientArea = (HRESULT (WINAPI *)(HWND, const MARGINS *))GetProcAddress(hdwm, "DwmExtendFrameIntoClientArea"); | 4093 _DwmExtendFrameIntoClientArea = (HRESULT (WINAPI *)(HWND, const MARGINS *))GetProcAddress(hdwm, "DwmExtendFrameIntoClientArea"); |
4094 _DwmSetWindowAttribute = (HRESULT (WINAPI *)(HWND, DWORD, LPCVOID, DWORD))GetProcAddress(hdwm, "DwmSetWindowAttribute"); | |
3999 if((_DwmIsCompositionEnabled = (HRESULT (WINAPI *)(BOOL *))GetProcAddress(hdwm, "DwmIsCompositionEnabled"))) | 4095 if((_DwmIsCompositionEnabled = (HRESULT (WINAPI *)(BOOL *))GetProcAddress(hdwm, "DwmIsCompositionEnabled"))) |
4000 _DwmIsCompositionEnabled(&_dw_composition); | 4096 _DwmIsCompositionEnabled(&_dw_composition); |
4001 _OpenThemeData = (HTHEME (WINAPI *)(HWND, LPCWSTR))GetProcAddress(huxtheme, "OpenThemeData"); | 4097 _OpenThemeData = (HTHEME (WINAPI *)(HWND, LPCWSTR))GetProcAddress(huxtheme, "OpenThemeData"); |
4002 _BeginBufferedPaint = (HPAINTBUFFER (WINAPI *)(HDC, const RECT *, BP_BUFFERFORMAT, BP_PAINTPARAMS *, HDC *))GetProcAddress(huxtheme, "BeginBufferedPaint"); | 4098 _BeginBufferedPaint = (HPAINTBUFFER (WINAPI *)(HDC, const RECT *, BP_BUFFERFORMAT, BP_PAINTPARAMS *, HDC *))GetProcAddress(huxtheme, "BeginBufferedPaint"); |
4003 _BufferedPaintSetAlpha = (HRESULT (WINAPI *)(HPAINTBUFFER, const RECT *, BYTE))GetProcAddress(huxtheme, "BufferedPaintSetAlpha"); | 4099 _BufferedPaintSetAlpha = (HRESULT (WINAPI *)(HPAINTBUFFER, const RECT *, BYTE))GetProcAddress(huxtheme, "BufferedPaintSetAlpha"); |
4004 _DrawThemeTextEx = (HRESULT (WINAPI *)(HTHEME, HDC, int, int, LPCWSTR, int, DWORD, LPRECT, const DTTOPTS *))GetProcAddress(huxtheme, "DrawThemeTextEx"); | 4100 _DrawThemeTextEx = (HRESULT (WINAPI *)(HTHEME, HDC, int, int, LPCWSTR, int, DWORD, LPRECT, const DTTOPTS *))GetProcAddress(huxtheme, "DrawThemeTextEx"); |
4005 _EndBufferedPaint = (HRESULT (WINAPI *)(HPAINTBUFFER, BOOL))GetProcAddress(huxtheme, "EndBufferedPaint"); | 4101 _EndBufferedPaint = (HRESULT (WINAPI *)(HPAINTBUFFER, BOOL))GetProcAddress(huxtheme, "EndBufferedPaint"); |
4006 _CloseThemeData = (HRESULT (WINAPI *)(HTHEME))GetProcAddress(huxtheme, "CloseThemeData"); | 4102 _CloseThemeData = (HRESULT (WINAPI *)(HTHEME))GetProcAddress(huxtheme, "CloseThemeData"); |
4103 _dw_init_dark_mode(); | |
4007 } | 4104 } |
4008 /* In case of error close the library if needed */ | 4105 /* In case of error close the library if needed */ |
4009 else if(hdwm) | 4106 else if(hdwm) |
4010 { | 4107 { |
4011 FreeLibrary(hdwm); | 4108 FreeLibrary(hdwm); |
4271 { | 4368 { |
4272 int rc; | 4369 int rc; |
4273 RECT rect; | 4370 RECT rect; |
4274 | 4371 |
4275 /* Try to enable dark mode support if our OS supports it */ | 4372 /* Try to enable dark mode support if our OS supports it */ |
4276 _set_child_window_theme(handle, 0); | 4373 _dw_set_child_window_theme(handle, 0); |
4277 EnumChildWindows(handle, _set_child_window_theme, 0); | 4374 EnumChildWindows(handle, _dw_set_child_window_theme, 0); |
4278 | 4375 |
4279 GetClientRect(handle, &rect); | 4376 GetClientRect(handle, &rect); |
4280 | 4377 |
4281 /* If the client area is 0x0 then call the autosize routine */ | 4378 /* If the client area is 0x0 then call the autosize routine */ |
4282 if((rect.bottom - rect.top) == 0 || (rect.right - rect.left) == 0) | 4379 if((rect.bottom - rect.top) == 0 || (rect.right - rect.left) == 0) |