locked
How to get colors of default app mode "Dark" in my Win32 App RRS feed

  • 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 GetImmersiveColorFromColorSetEx
    Wednesday, 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 lot
    Thursday, July 2, 2020 3:59 AM