Changing Background color by using button (Win32 API)
Question
Tuesday, June 12, 2012 8:51 AM
i have tried a lot of time by using WM_ERASEBKGND,
and found that SetBkColor is only for rectangle???
i have learnt C++ before but i have not learnt any coding of window application interface.
i hope that someone can help me with present of code.
my code is below:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
TCHAR helloWorld[] = _T(
"Hello World!");
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
SetBkColor(hdc, windowBackgroundColor);
TextOut(hdc, 360, 250, helloWorld, _tcslen(helloWorld));
EndPaint(hWnd, &ps);
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case BTN_MYBUTTON_ID:
// Your code here.
WM_ERASEBKGND;
WNDCLASSEX wcex;
windowBackgroundColor = RGB(0xff, 0xff, 0x00);
windowBackgroundBrush = CreateSolidBrush(windowBackgroundColor);
wcex.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
MessageBox(hWnd, L
"Background color was changed!", L"Message", MB_OK);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);//This function ensures that every message is processed
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
:
All replies (8)
Tuesday, June 12, 2012 10:39 AM ✅Answered | 3 votes
If you want to change the background color you must handle the WM_ERASEBKGND message. In the example I posted here I will change the background color when I select the menu item with the ID_TEST:
// ColorBkGnd.cpp : Defines the entry point for the application.//#include "stdafx.h"#include "ColorBkGnd.h"#define MAX_LOADSTRING 100// Global Variables:HINSTANCE hInst; // current instanceTCHAR szTitle[MAX_LOADSTRING]; // The title bar textTCHAR szWindowClass[MAX_LOADSTRING]; // the main window class nameCOLORREF bkgndcolor;// Forward declarations of functions included in this code module:ATOM MyRegisterClass(HINSTANCE hInstance);BOOL InitInstance(HINSTANCE, int);LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow){ UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: Place code here. MSG msg; HACCEL hAccelTable; // Initialize global strings LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_COLORBKGND, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_COLORBKGND)); // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam;}//// FUNCTION: MyRegisterClass()//// PURPOSE: Registers the window class.//// COMMENTS://// This function and its usage are only necessary if you want this code// to be compatible with Win32 systems prior to the 'RegisterClassEx'// function that was added to Windows 95. It is important to call this function// so that the application will get 'well formed' small icons associated// with it.//ATOM MyRegisterClass(HINSTANCE hInstance){ WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_COLORBKGND)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = MAKEINTRESOURCE(IDC_COLORBKGND); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassEx(&wcex);}//// FUNCTION: InitInstance(HINSTANCE, int)//// PURPOSE: Saves instance handle and creates main window//// COMMENTS://// In this function, we save the instance handle in a global variable and// create and display the main program window.//BOOL InitInstance(HINSTANCE hInstance, int nCmdShow){ HWND hWnd; hInst = hInstance; // Store instance handle in our global variable bkgndcolor=0x00FFFFFF; hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE;}void ChangeBkGnd(HWND hWnd){ bkgndcolor=0x00FF00FF; InvalidateRect(hWnd,NULL, TRUE);}//// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)//// PURPOSE: Processes messages for the main window.//// WM_COMMAND - process the application menu// WM_PAINT - Paint the main window// WM_DESTROY - post a quit message and return////LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){ int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Parse the menu selections: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; case ID_TEST: ChangeBkGnd(hWnd); default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_ERASEBKGND: HPEN pen; HBRUSH brush; RECT rect; pen=CreatePen(PS_SOLID, 1, bkgndcolor); brush=CreateSolidBrush(bkgndcolor); SelectObject((HDC)wParam, pen); SelectObject((HDC)wParam, brush); GetClientRect(hWnd, &rect); Rectangle((HDC)wParam, rect.left, rect.top, rect.right, rect.bottom); break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: Add any drawing code here... EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0;}// Message handler for about box.INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam){ UNREFERENCED_PARAMETER(lParam); switch (message) { case WM_INITDIALOG: return (INT_PTR)TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; } break; } return (INT_PTR)FALSE;}
I force the change of the background color in changing the default background color variable bkgndcolor I use in WM_ERASEBKGND.
Thursday, June 14, 2012 4:49 AM ✅Answered
In my very first post in the code I posted in the post there you also see a "case WM_PAINT:". This is the correct location for checking the WM_PAINT message. In your example you include the code for painting your "hello world" text at this location.
WM_PAINT has nothing to do with WM_COMMAND and therefore it does not make sense to check for a WM_PAINT in the WM_COMMAND switch construct.
Have you checked the links of the thread I posted? From the questions you are asking the problem you have sees to be very basic. What tutorial are you using or how are you trying to learn windows porgramming? A good beginner tutorial .
Here a nice begin with a lot explanations:
http://www.winprog.org/tutorial/simple_window.html
Also nice is this one:
http://winapi.foosyerdoos.org.uk/info/user_cntrls.php#SimpleWnd
http://www.functionx.com/win32/index.htm
Wednesday, June 13, 2012 3:13 AM
thank you very much. i can change the background color successfully. but i discover that i have a problem of the text background color. i have set it to my defauly setting color and after i click my button , the background color can be changed to RGB(0xff,0xff,0x00), but the text background color still not ben changed.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
TCHAR helloWorld[] = _T(
"Hello World!"); //added by jay
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
SetBkColor(hdc, windowBackgroundColor);
//added by jay , for word block bk color
TextOut(hdc, 300, 350, helloWorld, _tcslen(helloWorld));
//added by jay
EndPaint(hWnd, &ps);
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case BTN_MYBUTTON_ID://added by jay
{
// Your code here.
windowBackgroundBrush = CreateSolidBrush(RGB(0xff,0xff,0x00));
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
SetBkColor(hdc, RGB(0xff,0xff,0x00));
//added by jay , for word block bk color
TextOut(hdc, 300, 350, helloWorld, _tcslen(helloWorld));
//added by jay
EndPaint(hWnd, &ps);
ChangeBkGnd(hWnd);
MessageBox(hWnd, L
"Background color was changed!", L"Message", MB_OK);
break;
}
case BTN_MYRADIOBUTTON_ID: //added by jay
MessageBox(hWnd, L
"Warning!", L"Message", MB_OK|MB_ICONEXCLAMATION);
break;
case BTN_MYRADIOBUTTON_ID2: //added by jay
MessageBox(hWnd, L
"You have clicked a radio button!", L"Message", MB_OK|MB_ICONASTERISK);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);//This function ensures that every message is processed
}
break;
case WM_ERASEBKGND:
HPEN pen;
HBRUSH brush;
RECT rect;
pen=CreatePen(PS_SOLID, 1, bkgndcolor);
brush=CreateSolidBrush(bkgndcolor);
SelectObject((HDC)wParam, pen);
SelectObject((HDC)wParam, brush);
GetClientRect(hWnd, &rect);
Rectangle((HDC)wParam, rect.left, rect.top, rect.right, rect.bottom);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Wednesday, June 13, 2012 5:01 AM | 1 vote
thank you very much. i can change the background color successfully. but i discover that i have a problem of the text background color. i have set it to my defauly setting color and after i click my button , the background color can be changed to RGB(0xff,0xff,0x00), but the text background color still not ben changed.
I'm not really sure what your problem is. If you want to change the background color for your text output you can do it with "SetBkcolor": (Note the variable names may differ from your code!)
case WM_PAINT: hdc = BeginPaint(hWnd, &ps); SetBkColor(hdc, bkgndcolor); TextOut(hdc, 300, 350, helloWorld, _tcslen(helloWorld)); EndPaint(hWnd, &ps);break;
You already did this is your code when I check your WM_PAINT code part. The strange thing is the nested WM_PAINT in your "case BTN_MYBUTTON_ID:".
You can also use
SetBkMode(hdc, TRANSPARENT) ;
to have an transparent background.
Wednesday, June 13, 2012 5:55 AM
yes i have already do this part before because i want my text bg color same as my bg color/
after that, i want to change my bg color but the text color does not be changed. I discover that there is some problem in nested WM_PAINT in your "case BTN_MYBUTTON_ID:". It is because i dont know where i need to put the code in. I just start to learn those function before 2 days.
Wednesday, June 13, 2012 6:45 AM | 1 vote
It is because i dont know where i need to put the code in. I just start to learn those function before 2 days.
That you are new in window programming is ok. We all started at this point. :-)
Here you can find useful sources for beginners. This thread is a few days old.
http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/3a485143-d4fa-410c-8dd4-17215cc6e5c9
Thursday, June 14, 2012 3:59 AM
but i really dont understand which region i need to put the "change text background color" code in.
Is it wrong that i don't need to write case WM_PAINT. it is because i want it to be happened by clicking the button. Is it wrong that i put it in to case case BTN_MYBUTTON_ID?
Friday, June 15, 2012 2:20 AM
thank you very much..
But unfortunately i need to learn MFC now. i just start to learn it in http://www.functionx.com/visualc/index.htm
Your link is very useful.