Asked by:
How to get colors of default app mode "Dark" in my Win32 App

Question
-
There is "choose your default app mode" in Win10 setting with two options, "Light" and "Dark". I know an UWP app automatically respond to the setting and change its appearance automatically. Now the Win32 common file open dialog in a simple MFC app also respond to this setting and change its appearance automatically. I can respond to this setting change by respond to WM_SETTINGCHANGE, but how can I get the colors of this "Dark" mode in a Win32 app or a MFC app. I tried to use theme API as following, but it always return the color of "Current Theme" but not the "default app mode".
HTHEME hTheme = OpenThemeData (NULL, L"CompositedWindow::Window");
if (hTheme)
{
COLORREF btnFaceColor = GetThemeSysColor (hTheme, TMT_BTNFACE);
}BTW, I'm not talking about high contrast Theme, but "choose your default app mode" setting. I suppose they are different settings which are set separately.
I guess if I can get correct HTHEME of it, then I can get all colors in it. but how?
Wednesday, July 1, 2020 12:36 PM
All replies
-
With Immersive color APIs like GetImmersiveColorFromColorSetExWednesday, July 1, 2020 12:43 PM
-
thanks. is it a window SDK API? which header file is it in? and which lib I should link to.Wednesday, July 1, 2020 1:12 PM
-
I found it in uxtheme.dll, it's an exported interface, but not included in uxtheme.h. I should use GetProcAddress to get it.
thanks anyway.
Wednesday, July 1, 2020 1:39 PM -
A test enumerating Immersive colors in a ListView (Windows 10) =>
(re-initialized on WM_SETTINGCHANGE)
#include <windows.h> #include <tchar.h> #include <commctrl.h> #pragma comment (lib, "comctl32") #pragma comment(linker,"\"/manifestdependency:type='win32' \ name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \ processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") HINSTANCE hInst; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int nWidth = 600, nHeight = 400; #define IDC_LISTVIEW 10 DWORD nTicksOld = 0; void FillListView(HWND hWndLV); typedef int (WINAPI *PGetImmersiveColorSetCount)(); typedef DWORD(WINAPI *PGetImmersiveColorFromColorSetEx)(UINT dwImmersiveColorSet, UINT dwImmersiveColorType, bool bIgnoreHighContrast, UINT dwHighContrastCacheMode); typedef WCHAR **(WINAPI *PGetImmersiveColorNamedTypeByIndex)(UINT dwImmersiveColorType); typedef int (WINAPI *PGetImmersiveColorTypeFromName)(const WCHAR *name); typedef int (WINAPI *PGetImmersiveUserColorSetPreference)(bool bForceCheckRegistry, bool bSkipCheckOnFail); PGetImmersiveColorSetCount pGetImmersiveColorSetCount = NULL; PGetImmersiveColorFromColorSetEx pGetImmersiveColorFromColorSetEx = NULL; PGetImmersiveColorNamedTypeByIndex pGetImmersiveColorNamedTypeByIndex = NULL; PGetImmersiveColorTypeFromName pGetImmersiveColorTypeFromName = NULL; PGetImmersiveUserColorSetPreference pGetImmersiveUserColorSetPreference = NULL; int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { HMODULE hUxTheme = LoadLibrary(TEXT("uxtheme.dll")); pGetImmersiveColorSetCount = (PGetImmersiveColorSetCount)GetProcAddress(hUxTheme, MAKEINTRESOURCEA(94)); pGetImmersiveColorFromColorSetEx = (PGetImmersiveColorFromColorSetEx)GetProcAddress(hUxTheme, MAKEINTRESOURCEA(95)); pGetImmersiveColorNamedTypeByIndex = (PGetImmersiveColorNamedTypeByIndex)GetProcAddress(hUxTheme, MAKEINTRESOURCEA(100)); pGetImmersiveColorTypeFromName = (PGetImmersiveColorTypeFromName)GetProcAddress(hUxTheme, MAKEINTRESOURCEA(96)); pGetImmersiveUserColorSetPreference = (PGetImmersiveUserColorSetPreference)GetProcAddress(hUxTheme, MAKEINTRESOURCEA(98)); if (!pGetImmersiveColorSetCount || !pGetImmersiveColorFromColorSetEx || !pGetImmersiveColorNamedTypeByIndex || !pGetImmersiveColorTypeFromName || !pGetImmersiveUserColorSetPreference) return MessageBox(NULL, TEXT("Cannot load Immersive colors APIs !"), TEXT("Error"), MB_ICONERROR | MB_OK); hInst = hInstance; WNDCLASSEX wcex = { sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, WndProc, 0, 0, hInst, LoadIcon(NULL, IDI_APPLICATION), LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_WINDOW + 1), NULL, TEXT("WindowClass"), NULL, }; if (!RegisterClassEx(&wcex)) return MessageBox(NULL, TEXT("Cannot register class !"), TEXT("Error"), MB_ICONERROR | MB_OK); int nX = (GetSystemMetrics(SM_CXSCREEN) - nWidth) / 2, nY = (GetSystemMetrics(SM_CYSCREEN) - nHeight) / 2; HWND hWnd = CreateWindowEx(0, wcex.lpszClassName, TEXT("Test Immersive colors"), WS_OVERLAPPEDWINDOW, nX, nY, nWidth, nHeight, NULL, NULL, hInst, NULL); if (!hWnd) return MessageBox(NULL, TEXT("Cannot create window !"), TEXT("Error"), MB_ICONERROR | MB_OK); ShowWindow(hWnd, SW_SHOWNORMAL); UpdateWindow(hWnd); MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int)msg.wParam; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static HWND hWndButton = NULL; static HWND hWndLV = NULL; int wmId, wmEvent; switch (message) { case WM_CREATE: { hWndLV = CreateWindowEx(0, WC_LISTVIEW, TEXT(""), WS_VISIBLE | WS_CHILD | WS_BORDER | LVS_REPORT | LVS_SINGLESEL, 10, 10, nWidth - 35, nHeight - 60, hWnd, (HMENU)IDC_LISTVIEW, hInst, NULL); DWORD dwExStyle = ListView_GetExtendedListViewStyle(hWndLV); dwExStyle |= LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP | LVS_EX_LABELTIP | LVS_EX_DOUBLEBUFFER; ListView_SetExtendedListViewStyle(hWndLV, dwExStyle); LVCOLUMN lvCol; TCHAR wszBuf[32]; wsprintf(wszBuf, TEXT("Color")); ZeroMemory(&lvCol, sizeof(lvCol)); lvCol.mask = LVCF_TEXT | LVCF_FMT | LVCF_WIDTH; lvCol.fmt = LVCFMT_LEFT; lvCol.cx = 440; lvCol.pszText = wszBuf; ListView_InsertColumn(hWndLV, 0, &lvCol); wsprintf(wszBuf, TEXT("ARGB")); lvCol.pszText = wszBuf; lvCol.cx = 100; ListView_InsertColumn(hWndLV, 1, &lvCol); FillListView(hWndLV); return 0; } break; case WM_NOTIFY: { LPNMHDR pnmhdr = (LPNMHDR)lParam; LPNMLISTVIEW pnmListView = (LPNMLISTVIEW)lParam; switch (pnmhdr->code) { case NM_CUSTOMDRAW: { NMLVCUSTOMDRAW* pnmlv = (NMLVCUSTOMDRAW*)pnmhdr; int nItem = pnmlv->nmcd.dwItemSpec; int nSubItem = pnmlv->iSubItem; BOOL bHighlighted = 0; if (pnmlv->nmcd.dwDrawStage == CDDS_PREPAINT) { return CDRF_NOTIFYITEMDRAW; } else if (pnmlv->nmcd.dwDrawStage == CDDS_ITEMPREPAINT) { bHighlighted = (pnmlv->nmcd.uItemState & (CDIS_SELECTED | CDIS_FOCUS)); if (bHighlighted) { pnmlv->clrText = RGB(255, 255, 0); pnmlv->clrTextBk = RGB(255, 0, 0); ListView_SetItemState(pnmhdr->hwndFrom, nItem, 0, LVIS_SELECTED); } else { WCHAR wsText[255] = L""; ListView_GetItemText(pnmhdr->hwndFrom, nItem, 1, wsText, ARRAYSIZE(wsText)); DWORD nColor = _wtof(wsText); COLORREF color = RGB(0xFF & nColor, (0xFF00 & nColor) >> 8, (0xFF0000 & nColor) >> 16); pnmlv->clrTextBk = color; if (color == 0) pnmlv->clrText = RGB(255, 255, 255); } return CDRF_DODEFAULT | CDRF_NOTIFYPOSTPAINT; } else if (pnmlv->nmcd.dwDrawStage == CDDS_ITEMPOSTPAINT) { } } break; } } break; case WM_SIZE: { MoveWindow(hWndLV, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE); return 0; } break; case WM_SETTINGCHANGE: { WCHAR* plParam = (LPWSTR)lParam; if (plParam) { if (lstrcmp(plParam, TEXT("ImmersiveColorSet")) == 0) { DWORD nTicks = GetTickCount(); if (nTicks - nTicksOld > 5000 || nTicksOld == 0) { Beep(6000, 50); ListView_DeleteAllItems(hWndLV); FillListView(hWndLV); } nTicksOld = nTicks; } } return 0; } break; case WM_DESTROY: { PostQuitMessage(0); return 0; } break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } void FillListView(HWND hWndLV) { TCHAR wsName[255] = TEXT(""); TCHAR wsNameImmersive[300] = TEXT(""); TCHAR wszBuf[32]; if (pGetImmersiveColorSetCount && pGetImmersiveColorFromColorSetEx && pGetImmersiveColorNamedTypeByIndex && pGetImmersiveColorTypeFromName) { int nItem = 0; for (int i = 0; i <= 1250; i++) { WCHAR** pName = pGetImmersiveColorNamedTypeByIndex(i); if (pName) { lstrcpy(wsName, *pName); LVITEM lvItem = { 0 }; lvItem.mask = LVIF_TEXT; lvItem.cchTextMax = 256; lvItem.iItem = i; lvItem.pszText = wsName; ListView_InsertItem(hWndLV, &lvItem); lstrcpy(wsNameImmersive, TEXT("Immersive")); lstrcat(wsNameImmersive, wsName); DWORD rgba = pGetImmersiveColorFromColorSetEx(pGetImmersiveUserColorSetPreference(false, false), pGetImmersiveColorTypeFromName(wsNameImmersive), false, 0); lvItem.iSubItem = 1; wsprintf(wszBuf, TEXT("%lu"), rgba); lvItem.pszText = wszBuf; ListView_SetItem(hWndLV, &lvItem); } } } }
- Proposed as answer by valat Saturday, July 4, 2020 6:12 AM
Wednesday, July 1, 2020 7:21 PM -
it really help. thanks a lotThursday, July 2, 2020 3:59 AM