How to Change the Background Color of a Button Winapi C++

How can I change the background color of a button WinAPI C++

Instead of a link I'll just post a copy from my other post using custom-drawing, similar to alwayslearningnewstuff example:

Nothing is selected
First button is selected and was pushed
Second button was pushed and the mouse is over it (notice the increse of brightness - cutom hilight)

First picture shows when nothing is selected, second shows when first button is selected and was pushed and the last one shows when second button was pushed and the mouse is over it (notice the increase of brightness - cutom hilight). In order to do this, you must catch NM_CUSTOMDRAW message and paint button yourself. And this is how you do it. Also added gradient brush function and some comments.

#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

#include <Windows.h>
#include <Commctrl.h>

#define IDC_EXIT_BUTTON 101
#define IDC_PUSHLIKE_BUTTON 102

HBRUSH CreateGradientBrush(COLORREF top, COLORREF bottom, LPNMCUSTOMDRAW item)
{
HBRUSH Brush = NULL;
HDC hdcmem = CreateCompatibleDC(item->hdc);
HBITMAP hbitmap = CreateCompatibleBitmap(item->hdc, item->rc.right-item->rc.left, item->rc.bottom-item->rc.top);
SelectObject(hdcmem, hbitmap);

int r1 = GetRValue(top), r2 = GetRValue(bottom), g1 = GetGValue(top), g2 = GetGValue(bottom), b1 = GetBValue(top), b2 = GetBValue(bottom);
for(int i = 0; i < item->rc.bottom-item->rc.top; i++)
{
RECT temp;
int r,g,b;
r = int(r1 + double(i * (r2-r1) / item->rc.bottom-item->rc.top));
g = int(g1 + double(i * (g2-g1) / item->rc.bottom-item->rc.top));
b = int(b1 + double(i * (b2-b1) / item->rc.bottom-item->rc.top));
Brush = CreateSolidBrush(RGB(r, g, b));
temp.left = 0;
temp.top = i;
temp.right = item->rc.right-item->rc.left;
temp.bottom = i + 1;
FillRect(hdcmem, &temp, Brush);
DeleteObject(Brush);
}
HBRUSH pattern = CreatePatternBrush(hbitmap);

DeleteDC(hdcmem);
DeleteObject(Brush);
DeleteObject(hbitmap);

return pattern;
}

LRESULT CALLBACK MainWindow(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static HBRUSH defaultbrush = NULL;
static HBRUSH hotbrush = NULL;
static HBRUSH selectbrush = NULL;
static HBRUSH push_uncheckedbrush = NULL;
static HBRUSH push_checkedbrush = NULL;
static HBRUSH push_hotbrush1 = NULL;
static HBRUSH push_hotbrush2 = NULL;
switch (msg)
{
case WM_CREATE:
{
HWND Exit_Button = CreateWindowEx(NULL, L"BUTTON", L"EXIT",
WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
50, 50, 100, 100, hwnd, (HMENU)IDC_EXIT_BUTTON, NULL, NULL);
if(Exit_Button == NULL)
{
MessageBox(NULL, L"Button Creation Failed!", L"Error!", MB_ICONEXCLAMATION);
exit(EXIT_FAILURE);
}

HWND Pushlike_Button = CreateWindowEx(NULL, L"BUTTON", L"PUSH ME!",
WS_VISIBLE | WS_CHILD | BS_AUTOCHECKBOX | BS_PUSHLIKE,
200, 50, 100, 100, hwnd, (HMENU)IDC_PUSHLIKE_BUTTON, NULL, NULL);
if(Pushlike_Button == NULL)
{
MessageBox(NULL, L"Button Creation Failed!", L"Error!", MB_ICONEXCLAMATION);
exit(EXIT_FAILURE);
}
}
break;
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case IDC_EXIT_BUTTON:
{
SendMessage(hwnd, WM_CLOSE, 0, 0);
}
break;
}
}
break;
case WM_NOTIFY:
{
LPNMHDR some_item = (LPNMHDR)lParam;

if (some_item->idFrom == IDC_EXIT_BUTTON && some_item->code == NM_CUSTOMDRAW)
{
LPNMCUSTOMDRAW item = (LPNMCUSTOMDRAW)some_item;

if (item->uItemState & CDIS_SELECTED)
{
//Select our color when the button is selected
if (selectbrush == NULL)
selectbrush = CreateGradientBrush(RGB(180, 0, 0), RGB(255, 180, 0), item);

//Create pen for button border
HPEN pen = CreatePen(PS_INSIDEFRAME, 0, RGB(0, 0, 0));

//Select our brush into hDC
HGDIOBJ old_pen = SelectObject(item->hdc, pen);
HGDIOBJ old_brush = SelectObject(item->hdc, selectbrush);

//If you want rounded button, then use this, otherwise use FillRect().
RoundRect(item->hdc, item->rc.left, item->rc.top, item->rc.right, item->rc.bottom, 5, 5);

//Clean up
SelectObject(item->hdc, old_pen);
SelectObject(item->hdc, old_brush);
DeleteObject(pen);

//Now, I don't want to do anything else myself (draw text) so I use this value for return:
return CDRF_DODEFAULT;
//Let's say I wanted to draw text and stuff, then I would have to do it before return with
//DrawText() or other function and return CDRF_SKIPDEFAULT
}
else
{
if (item->uItemState & CDIS_HOT) //Our mouse is over the button
{
//Select our color when the mouse hovers our button
if (hotbrush == NULL)
hotbrush = CreateGradientBrush(RGB(255, 230, 0), RGB(245, 0, 0), item);

HPEN pen = CreatePen(PS_INSIDEFRAME, 0, RGB(0, 0, 0));

HGDIOBJ old_pen = SelectObject(item->hdc, pen);
HGDIOBJ old_brush = SelectObject(item->hdc, hotbrush);

RoundRect(item->hdc, item->rc.left, item->rc.top, item->rc.right, item->rc.bottom, 5, 5);

SelectObject(item->hdc, old_pen);
SelectObject(item->hdc, old_brush);
DeleteObject(pen);

return CDRF_DODEFAULT;
}

//Select our color when our button is doing nothing
if (defaultbrush == NULL)
defaultbrush = CreateGradientBrush(RGB(255, 180, 0), RGB(180, 0, 0), item);

HPEN pen = CreatePen(PS_INSIDEFRAME, 0, RGB(0, 0, 0));

HGDIOBJ old_pen = SelectObject(item->hdc, pen);
HGDIOBJ old_brush = SelectObject(item->hdc, defaultbrush);

RoundRect(item->hdc, item->rc.left, item->rc.top, item->rc.right, item->rc.bottom, 5, 5);

SelectObject(item->hdc, old_pen);
SelectObject(item->hdc, old_brush);
DeleteObject(pen);

return CDRF_DODEFAULT;
}
}
else if (some_item->idFrom == IDC_PUSHLIKE_BUTTON && some_item->code == NM_CUSTOMDRAW)
{
LPNMCUSTOMDRAW item = (LPNMCUSTOMDRAW)some_item;

if (IsDlgButtonChecked(hwnd, some_item->idFrom))
{
if (item->uItemState & CDIS_HOT)
{

if (push_hotbrush1 == NULL)
push_hotbrush1 = CreateGradientBrush(RGB(0, 0, 245), RGB(0, 230, 255), item);

HPEN pen = CreatePen(PS_INSIDEFRAME, 0, RGB(0, 0, 0));

HGDIOBJ old_pen = SelectObject(item->hdc, pen);
HGDIOBJ old_brush = SelectObject(item->hdc, push_hotbrush1);

RoundRect(item->hdc, item->rc.left, item->rc.top, item->rc.right, item->rc.bottom, 10, 10);

SelectObject(item->hdc, old_pen);
SelectObject(item->hdc, old_brush);
DeleteObject(pen);

return CDRF_DODEFAULT;
}

if (push_checkedbrush == NULL)
push_checkedbrush = CreateGradientBrush(RGB(0, 0, 180), RGB(0, 222, 200), item);

HPEN pen = CreatePen(PS_INSIDEFRAME, 0, RGB(0, 0, 0));

HGDIOBJ old_pen = SelectObject(item->hdc, pen);
HGDIOBJ old_brush = SelectObject(item->hdc, push_checkedbrush);

RoundRect(item->hdc, item->rc.left, item->rc.top, item->rc.right, item->rc.bottom, 10, 10);

SelectObject(item->hdc, old_pen);
SelectObject(item->hdc, old_brush);
DeleteObject(pen);

return CDRF_DODEFAULT;
}
else
{
if (item->uItemState & CDIS_HOT)
{
if (push_hotbrush2 == NULL)
push_hotbrush2 = CreateGradientBrush(RGB(255, 230, 0), RGB(245, 0, 0), item);

HPEN pen = CreatePen(PS_INSIDEFRAME, 0, RGB(0, 0, 0));

HGDIOBJ old_pen = SelectObject(item->hdc, pen);
HGDIOBJ old_brush = SelectObject(item->hdc, push_hotbrush2);

RoundRect(item->hdc, item->rc.left, item->rc.top, item->rc.right, item->rc.bottom, 10, 10);

SelectObject(item->hdc, old_pen);
SelectObject(item->hdc, old_brush);
DeleteObject(pen);

return CDRF_DODEFAULT;
}

if (push_uncheckedbrush == NULL)
push_uncheckedbrush = CreateGradientBrush(RGB(255, 180, 0), RGB(180, 0, 0), item);

HPEN pen = CreatePen(PS_INSIDEFRAME, 0, RGB(0, 0, 0));

HGDIOBJ old_pen = SelectObject(item->hdc, pen);
HGDIOBJ old_brush = SelectObject(item->hdc, defaultbrush);

RoundRect(item->hdc, item->rc.left, item->rc.top, item->rc.right, item->rc.bottom, 10, 10);

SelectObject(item->hdc, old_pen);
SelectObject(item->hdc, old_brush);
DeleteObject(pen);

return CDRF_DODEFAULT;
}
}
return CDRF_DODEFAULT;
}
break;
case WM_CTLCOLORBTN: //In order to make those edges invisble when we use RoundRect(),
{ //we make the color of our button's background match window's background
return (LRESULT)GetSysColorBrush(COLOR_WINDOW+1);
}
break;
case WM_CLOSE:
{
DestroyWindow(hwnd);
return 0;
}
break;
case WM_DESTROY:
{
DeleteObject(defaultbrush);
DeleteObject(selectbrush);
DeleteObject(hotbrush);
DeleteObject(push_checkedbrush);
DeleteObject(push_hotbrush1);
DeleteObject(push_hotbrush2);
DeleteObject(push_uncheckedbrush);
PostQuitMessage(0);
return 0;
}
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG msg;
const wchar_t ClassName[] = L"Main_Window";

wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = MainWindow;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = ClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

if(!RegisterClassEx(&wc))
{
MessageBox(NULL, L"Window Registration Failed!", L"Error", MB_ICONEXCLAMATION | MB_OK);
exit(EXIT_FAILURE);
}

hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, ClassName, L"Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 368, 248, NULL, NULL, hInstance, NULL);

if(hwnd == NULL)
{
MessageBox(NULL, L"Window Creation Failed!", L"Error!", MB_ICONEXCLAMATION | MB_OK);
exit(EXIT_FAILURE);
}

ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);

while(GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return msg.message;
}

how to set win32 api c++ button background color and text color?

You can't, or at least you can't do so simply. If you want a coloured button then you need to set the owner-draw style and draw it yourself. Plain old buttons don't have customisable colours.

Change window's background color with button using winapi

BeginPaint/EndPaint should be used in response to WM_PAINT only.

You can use GetDC(hwnd)/ReleaseDC(hwnd, hdc) to obtain hdc for painting on device context outside of WM_PAINT, but this will be temporary. The next refresh message causes the window to be erased and repainted according to what's in WM_PAINT

SetDCBrushColor can be used if the goal is to avoid creating brush handle.

static COLORREF bkcolor = RGB(255,255,255);
switch(message)
{
case WM_COMMAND:
if(LOWORD(wparam) == BUTTON_ID)
{
bkcolor = RGB(255, 0, 0);
InvalidateRect(hwnd, NULL, TRUE);
}
break;

case WM_PAINT:
{
PAINTSTRUCT ps;
RECT rc;
HDC hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rc);
SetDCBrushColor(hdc, bkcolor);
FillRect(hdc, &rc, (HBRUSH)GetStockObject(DC_BRUSH));

//or use ps.rcPaint to repaint only the section which requires update
//FillRect(hdc, &ps.rcPaint, (HBRUSH)GetStockObject(DC_BRUSH));

EndPaint(hwnd, &ps);
return 0;
}

case WM_ERASEBKGND:
//return 0 means WM_PAINT handles the background
return 0;

Alternatively, use SetClassLongPtr to replace the background brush:

static HBRUSH bkbrush = NULL;
switch(message)
{
case WM_COMMAND:
if(LOWORD(wparam) == BUTTON_ID)
{
COLORREF bkcolor = RGB(rand() % 256, rand() % 256, rand() % 256);
if(bkbrush)
DeleteObject(bkbrush);
bkbrush = CreateSolidBrush(bkcolor);
SetClassLongPtr(hwnd, GCL_HBRBACKGROUND, (LONG)bkbrush);
InvalidateRect(hwnd, NULL, TRUE);
}
break;

Set button text color in Win32 API using custom drawing

You just need to set the text color using the SetTextColor function, somewhere before your call to DrawText():

    //...
SetTextColor(item->hdc, RGB(0,255,0)); // For green text, but use any COLORREF value.
DrawTextA(item->hdc, "Click Me", -1, &item->rc, DT_CENTER | DT_VCENTER);
return CDRF_SKIPDEFAULT;

You may also need to set the background mode to TRANSPARENT, in order to keep the color previously painted:

    SetBkMode(item-hdc, TRANSPARENT);

How do I set the text and background color of an single static control c++?

When responding to WM_CTLCOLORSTATIC, check lParam which holds the handle of the control.

CreateSolidBrush creates a GDI object. It should be deleted with DeleteObject otherwise it causes a resource leak. You can declare the brush as static and delete it at the end. Example:

LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HBRUSH hbrush = NULL;
switch(message)
{
case WM_DESTROY:
if (hbrush) DeleteObject(hbrush);
hbrush = NULL;
PostQuitMessage(0);
break;
case WM_CREATE:
staticTextField = CreateWindow("STATIC", "static 1", WS_VISIBLE
| WS_CHILD, 20, 20, 300, 25, hwnd, NULL, NULL, NULL);
staticTextFieldTwo = CreateWindow("STATIC", "static2", WS_VISIBLE |
WS_CHILD | WS_BORDER, 100, 200, 300, 20, hwnd, NULL, NULL, NULL);
break;
case WM_CTLCOLORSTATIC:
{
HDC hdcStatic = (HDC)wParam;
if(lParam == (LPARAM)staticTextFieldTwo)
{
SetTextColor(hdcStatic, RGB(0, 255, 0));
SetBkColor(hdcStatic, RGB(0, 255, 255));
if (!hbrush)
hbrush = CreateSolidBrush(RGB(0, 255, 255));
return (LRESULT)hbrush;
}
break;
}
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}


Related Topics



Leave a reply



Submit