Click to See Complete Forum and Search --> : Changing background color of Static Control


mmscg
October 17th, 2004, 10:20 PM
Here is my code to display a Static Control with a white background on a form.

It appears to work, but only while the MessageBox is displayed.
As soon as the MessageBox is closed, the white background disappears.

What confuses me also, is that I need some code in the WM_PAINT
event for it to work.

Can anyone spot my error?


#define STRICT
#define WIN32_LEAN_AND_MEAN

#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

const char g_szClassName[] = "myWindowClass";
#define IDS_PIC 100

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;

wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE+1;
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

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

hwnd = CreateWindowEx(
NULL,
g_szClassName,
"Window Title",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 400, 300,
NULL, NULL, hInstance, NULL);

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

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

while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return static_cast<int>(Msg.wParam);
}


LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
HWND hPic01;
hPic01 = CreateWindow("static","",SS_BLACKFRAME|SS_WHITERECT |WS_CHILD|WS_VISIBLE,
125,10,250,250,hwnd,(HMENU)IDS_PIC,GetModuleHandle(NULL),NULL);
break;
case WM_CTLCOLORSTATIC:
MessageBox(NULL, "Background is all white as I want! but ONLY while MessageBox is displayed", "Message", MB_OK);
return 0;
//break;
case WM_PAINT:
HDC hdc;
PAINTSTRUCT ps;
hdc = BeginPaint(hwnd , &ps);
SelectObject(hdc , GetStockObject(WHITE_BRUSH));
Rectangle(hdc , 130 , 15 , 370 , 255);
EndPaint(hwnd , &ps);
return 0;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}

bigBA
October 17th, 2004, 11:37 PM
error is in handling of WM_CTLCOLORSTATIC msg.
look at its parameters:

LRESULT CALLBACK WindowProc(
HWND hwnd, // handle to window
UINT uMsg, // WM_CTLCOLORSTATIC
WPARAM wParam, // handle to DC (HDC)
LPARAM lParam // handle to static control (HWND)
);

and have a look at the return values section:

Return Values
If an application processes this message, the return value is a handle to a brush that the system uses to paint the background of the static control.


so... you can set the color of the text in the DC like this:

::SetTextColor((HDC)wParam, RGB(255,0,0));


and you have to return a handle to a HBRUSH with the desired background color, and not 0:

return ::CreateSolidBrush(RGB(255,255,255)); //create a white brush and return it

// or to use a system brush:
return ::GetSysColorBrush(COLOR_3DHILIGHT); //or something else

j0nas
October 17th, 2004, 11:44 PM
WM_PAINT isn't needed.

The problem is that you don't follow the docs when processing the WM_CTLCOLORSTATIC message:
If an application processes this message, the return value is a handle to a brush that the system uses to paint the background of the static control.
While reading about this on the net and found this: http://www.winprog.org/tutorial/dlgfaq.html

I've changed your code to use the information from above link:
#define STRICT
#define WIN32_LEAN_AND_MEAN

#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

const char g_szClassName[] = "myWindowClass";
#define IDS_PIC 100

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;

wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE+1;
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

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

hwnd = CreateWindowEx(
NULL,
g_szClassName,
"Window Title",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 400, 300,
NULL, NULL, hInstance, NULL);

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

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

while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return static_cast<int>(Msg.wParam);
}




LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static HBRUSH hbrBackground;

switch(msg)
{
case WM_CREATE:
HWND hPic01;
hPic01 = CreateWindow("static","",SS_WHITERECT|WS_CHILD|WS_VISIBLE,
125,10,250,250,hwnd,(HMENU)IDS_PIC,GetModuleHandle(NULL),NULL);
hbrBackground = CreateSolidBrush(RGB(255, 255, 255));
break;
case WM_CTLCOLORDLG:
return (LONG)hbrBackground;
case WM_CTLCOLORSTATIC:
{
HDC hdcStatic = (HDC)wParam;
SetBkMode(hdcStatic, TRANSPARENT);
return (LONG)hbrBackground;
}
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}

j0nas
October 17th, 2004, 11:45 PM
Oops... my reply came a bit late :blush:

kawasaki056
October 18th, 2004, 12:33 AM
Isn't is easier as,

WM_CTLCOLORSTATIC :
// if( GetDlgCtrlID( (WHND)lParam ) == IDS_PIC ) ... // if you like
// SetTextColor((HDC)wParam, RGB(80,80,220) ) ; // if you like

SetBkColor((HDC)wParam, RGB(255,255,255) ) ;
return (LONG)GetStockObject(WHITE_BRUSH) ;

// break ;

removing MessageBox() ;

and you are missing selecting pen , for rectangle.

add as,

SelectObject( hdc , GetStockObject( PS_DASH ) ) ; //


... tell me how to use tags..

bigBA
October 18th, 2004, 01:24 AM
nope, because the color selected with SetBkColor is just the background color for the text.
but the static can be bigger than the text being drawed on it.

mmscg
October 18th, 2004, 05:12 PM
OK guys, thanks!

I now have a Static Control with a white background,
however the black border is not there.

I tried adding SS_BLACKFRAME to the following line but that did not work.

hPic01 = CreateWindow("static","",SS_WHITERECT|WS_CHILD|WS_VISIBLE,
125,10,250,250,hwnd,(HMENU)IDS_PIC,GetModuleHandle(NULL),NULL);


Also, I tried changing the RGB color values in this line:

hbrBackground = CreateSolidBrush(RGB(255, 255, 255));

but that had no effect on the displayed background color.

I must not be understanding something... any more info would be apprecited! :)


kawasaki056:

... tell me how to use tags..

code: enclose code in [] at beginning of code and /code in [] at end of code
quote: enclose quote in [] at beginning of quote and /quote in [] at end of quote
bold: enclose b in [] at beginning of text and /b in [] at end of text
etc.

j0nas
October 18th, 2004, 05:27 PM
Remove SS_WHITERECT. Actually, don't specify any SS_xxxxFRAME/RECT at all.

I was able to use any color in the RGB-statement after removing SS_WHITERECT.

mmscg
October 18th, 2004, 05:51 PM
Yes, I tried as you instructed and am able to change to any color. :D

Might there be another way to add the border around it?

bigBA
October 19th, 2004, 01:39 AM
WS_BORDER style? :rolleyes:

mmscg
October 19th, 2004, 06:59 AM
OK, thanks! :D

I was so busy trying to fugure out how to get SS_BLACKFRAME to work,
I did not realize there was another flag for this purpose.

Curios then, what is SS_BLACKFRAME for?