How to change the caption titlebar of my window to black?

Eliza 21 Reputation points
2022-08-14T17:41:46.54+00:00

This is what i have written so far, my doubt is how to set the caption color of my new window to black.

 // Step 4: the Window Procedure.  
    LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)  
    {  
    	switch (msg)  
    	{  
    	case WM_CLOSE:  
    		DestroyWindow(hWnd);  
    		TerminateProcess(GetCurrentProcess(), 0);  
    		break;  
      
    	case WM_DESTROY:  
    	case WM_QUIT:  
    		PostQuitMessage(0);  
    		break;  
      
    	default:  
    		return DefWindowProc(hWnd, msg, wParam, lParam);  
    	}  
      
    	return DefWindowProc(hWnd, msg, wParam, lParam);  
      
    }  
      
    // Step 1-3 Creating a window procedure.  
    int Main()  
    {  
    	WNDCLASSEX wc{};  
    	MSG Msg;  
    	LPCWSTR title = L"MyWindow";  
      
    	//Step 1: Registering the Window Class  
    	wc.cbSize = sizeof(WNDCLASSEX);  
    	wc.style = 0;  
    	wc.lpfnWndProc = WndProc;  
    	wc.cbClsExtra = 0;  
    	wc.cbWndExtra = 0;  
    	wc.hInstance = 0;  
    	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);  
    	wc.hCursor = LoadCursor(NULL, IDC_ARROW);  
    	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);  
    	wc.lpszMenuName = NULL;  
    	wc.lpszClassName = title;   
    	wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);  
      
    	if (!RegisterClassEx(&wc))  
    	{  
    		DWORD err = GetLastError();  
      
    		std::wstring error = L"Window Registration Failed.\nError: " + std::to_wstring(int(err));  
      
    		MessageBox(NULL, error.c_str(), L"Error!",  
    			MB_ICONEXCLAMATION | MB_OK);  
    		return 0;  
    	}  
      
    	// Step 2: Creating the Window  
    	hWnd = CreateWindowW(  
    		title,  
    		title,  
    		//WS_OVERLAPPEDWINDOW,  
    		WS_OVERLAPPED | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU,  
    		CW_USEDEFAULT, CW_USEDEFAULT, 600, 300, // X,Y,W,H  
    		nullptr, nullptr, nullptr, nullptr);  
      
    	DWORD err = GetLastError();  
      
    	if (hWnd == NULL)  
    	{  
    		std::wstring error = L"Window creation failed.\nError: " + std::to_wstring(int(err));  
      
    		MessageBox(NULL, error.c_str(), L"Error!",  
    			MB_ICONEXCLAMATION | MB_OK);  
    		return 0;  
    	}  
      
    	ShowWindow(hWnd, SW_SHOW);  
    	UpdateWindow(hWnd);  
      
    	// Step 3: The Message Loop  
    	while (GetMessage(&Msg, NULL, 0, 0) > 0)  
    	{  
    		TranslateMessage(&Msg);  
    		DispatchMessage(&Msg);  
    	}  
    	return 0; // Msg.wParam;  
    }  
C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
2,752 questions
No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Castorix31 68,671 Reputation points
    2022-08-14T19:08:53.93+00:00

    Custom captions are done with DWM : Custom Window Frame Using DWM

    For example, a test with a gradient :
    231073-custom-caption4.jpg

    1 person found this answer helpful.

  2. Eliza 21 Reputation points
    2022-08-14T20:49:53.82+00:00

    I tried to follow the sample you linked, I'm getting these errors even after including uxtheme.h

    231046-devenv-2022-08-14-17-47-37.png

    #include <windows.h>  
      
    #include <uxtheme.h>  
    #include <string>  
    #pragma comment (lib,"UxTheme.lib")  
      
      
    // Paint the title on the custom frame.  
    void PaintCustomCaption(HWND hWnd, HDC hdc)  
    {  
        RECT rcClient;  
        GetClientRect(hWnd, &rcClient);  
      
        HTHEME hTheme = OpenThemeData(NULL, L"CompositedWindow::Window");  
        if (hTheme)  
        {  
            HDC hdcPaint = CreateCompatibleDC(hdc);  
            if (hdcPaint)  
            {  
                int cx = RECTWIDTH(rcClient);  
                int cy = RECTHEIGHT(rcClient);  
      
                // Define the BITMAPINFO structure used to draw text.  
                // Note that biHeight is negative. This is done because  
                // DrawThemeTextEx() needs the bitmap to be in top-to-bottom  
                // order.  
                BITMAPINFO dib = { 0 };  
                dib.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);  
                dib.bmiHeader.biWidth = cx;  
                dib.bmiHeader.biHeight = -cy;  
                dib.bmiHeader.biPlanes = 1;  
                dib.bmiHeader.biBitCount = BIT_COUNT;  
                dib.bmiHeader.biCompression = BI_RGB;  
      
                HBITMAP hbm = CreateDIBSection(hdc, &dib, DIB_RGB_COLORS, NULL, NULL, 0);  
                if (hbm)  
                {  
                    HBITMAP hbmOld = (HBITMAP)SelectObject(hdcPaint, hbm);  
      
                    // Setup the theme drawing options.  
                    DTTOPTS DttOpts = { sizeof(DTTOPTS) };  
                    DttOpts.dwFlags = DTT_COMPOSITED | DTT_GLOWSIZE;  
                    DttOpts.iGlowSize = 15;  
      
                    // Select a font.  
                    LOGFONT lgFont;  
                    HFONT hFontOld = NULL;  
                    if (SUCCEEDED(GetThemeSysFont(hTheme, TMT_CAPTIONFONT, &lgFont)))  
                    {  
                        HFONT hFont = CreateFontIndirect(&lgFont);  
                        hFontOld = (HFONT)SelectObject(hdcPaint, hFont);  
                    }  
      
                    // Draw the title.  
                    RECT rcPaint = rcClient;  
                    rcPaint.top += 8;  
                    rcPaint.right -= 125;  
                    rcPaint.left += 8;  
                    rcPaint.bottom = 50;  
                    DrawThemeTextEx(hTheme,  
                        hdcPaint,  
                        0, 0,  
                        szTitle,  
                        -1,  
                        DT_LEFT | DT_WORD_ELLIPSIS,  
                        &rcPaint,  
                        &DttOpts);  
      
                    // Blit text to the frame.  
                    BitBlt(hdc, 0, 0, cx, cy, hdcPaint, 0, 0, SRCCOPY);  
      
                    SelectObject(hdcPaint, hbmOld);  
                    if (hFontOld)  
                    {  
                        SelectObject(hdcPaint, hFontOld);  
                    }  
                    DeleteObject(hbm);  
                }  
                DeleteDC(hdcPaint);  
            }  
            CloseThemeData(hTheme);  
        }  
    }  
      
      
      
    // Step 4: the Window Procedure.  
    LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)  
    {  
        switch (msg)  
        {  
        case WM_CLOSE:  
            DestroyWindow(hWnd);  
            TerminateProcess(GetCurrentProcess(), 0);  
            break;  
      
        case WM_DESTROY:  
        case WM_QUIT:  
            PostQuitMessage(0);  
            break;  
      
        case WM_PAINT:  
        {  
            HDC hdc;  
            {  
                PAINTSTRUCT ps;  
                hdc = BeginPaint(hWnd, &ps);  
                PaintCustomCaption(hWnd, hdc);  
                EndPaint(hWnd, &ps);  
            }  
      
            fCallDWP = true;  
            lRet = 0;  
            break;  
        }  
        default:  
            return DefWindowProc(hWnd, msg, wParam, lParam);  
        }  
      
        return DefWindowProc(hWnd, msg, wParam, lParam);  
      
    }  
      
    // Step 1-3 Creating a window procedure.  
    int Main()  
    {  
        WNDCLASSEX wc{};  
        MSG Msg;  
        LPCWSTR title = L"MyWindow";  
        HWND hWnd = nullptr;  
      
        //Step 1: Registering the Window Class  
        wc.cbSize = sizeof(WNDCLASSEX);  
        wc.style = 0;  
        wc.lpfnWndProc = WndProc;  
        wc.cbClsExtra = 0;  
        wc.cbWndExtra = 0;  
        wc.hInstance = 0;  
        wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);  
        wc.hCursor = LoadCursor(NULL, IDC_ARROW);  
        wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);  
        wc.lpszMenuName = NULL;  
        wc.lpszClassName = title;  
        wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);  
      
        if (!RegisterClassEx(&wc))  
        {  
            DWORD err = GetLastError();  
      
            std::wstring error = L"Window Registration Failed.\nError: " + std::to_wstring(int(err));  
      
            MessageBox(NULL, error.c_str(), L"Error!",  
                MB_ICONEXCLAMATION | MB_OK);  
            return 0;  
        }  
      
        // Step 2: Creating the Window  
        hWnd = CreateWindowW(  
            title,  
            title,  
            //WS_OVERLAPPEDWINDOW,  
            WS_OVERLAPPED | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU,  
            CW_USEDEFAULT, CW_USEDEFAULT, 600, 300, // X,Y,W,H  
            nullptr, nullptr, nullptr, nullptr);  
      
        DWORD err = GetLastError();  
      
        if (hWnd == NULL)  
        {  
            std::wstring error = L"Window creation failed.\nError: " + std::to_wstring(int(err));  
      
            MessageBox(NULL, error.c_str(), L"Error!",  
                MB_ICONEXCLAMATION | MB_OK);  
            return 0;  
        }  
      
        ShowWindow(hWnd, SW_SHOW);  
        UpdateWindow(hWnd);  
      
        // Step 3: The Message Loop  
        while (GetMessage(&Msg, NULL, 0, 0) > 0)  
        {  
            TranslateMessage(&Msg);  
            DispatchMessage(&Msg);  
        }  
        return 0; // Msg.wParam;  
    }