Click here to Skip to main content
15,889,867 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
INTRODUCTION AND RELEVANT INFORMATION:

I want to create a static control with gradient background.

I want to do it the following way:

Create the gradient at the main window’s background, and then place transparent static control on top of that background.

To do that, I have created RECT variable in WM_PAINT handler that positions the gradient at the position where static control should be.

Also, I try to use double buffering to avoid flickering ( I have also handled WM_ERASEBKGND, removed flags CS_VREDRAW and CS_HREDRAW from window class ).

I have also handled WM_SIZE message to invalidate the window, and to reposition static control properly.

In my WM_CTLCOLORSTATIC handler, I have returned NULL_BRUSH.

I have made a demo application to illustrate this, via application wizard in Visual Studio.

I work on Windows XP, using pure Win32 API and C++.

Bellow I will submit the link to the demo project:

http://www.filedropper.com/gradientstaticcontrol[^]

PROBLEM:

When I use GradientFill API in WM_PAINT handler, I get a bigger rectangle on the screen than it should be.

Bellow picture illustrates this result:

http://pbrd.co/1cMWhip[^]

If I try to fill the same rectangle with some solid brush, everything works fine.

Bellow picture illustrates this result:

http://pbrd.co/1bjz7cT[^]

MY EFFORTS TO SOLVE PROBLEM:

I have placed breakpoints at the places where rectangle’s coordinates are set and have seen that there is no problem with setting the rectangles coordinates.

GradientFill returns TRUE, so there should be no problems.

QUESTION:

How to fix this?

Thank you in advance.

Regards.
Posted
Updated 10-Nov-13 17:18pm
v2

1 solution

There's just two changes you need to make. In each case, it's because you've forgotten that when drawing to the HDC of a control, the RECT always has the top and left members set to 0.

However, when drawing this rect onto the background of the dialog, the top and left members are no longer 0.

The changes you need to make are:

1.
WAS:
C++
vertexS[1].y     = ( rect.bottom - rect.top ) / 2; 


IS:
C++
vertexS[1].y     = rect.top + ( rect.bottom - rect.top ) / 2; 



2.
WAS:
C++
vertex1S[0].y     = ( rect.bottom - rect.top ) / 2;


IS:
C++
vertex1S[0].y     = rect.top + ( rect.bottom - rect.top ) / 2;




I strongly recommend that you use the functions I've mentioned in the past, repeated here for clarity.

C++
void GradientFillRect(HDC hdc, RECT fillMe, COLORREF colStart, COLORREF colEnd, bool isVertical)
{
    TRIVERTEX vertex[2];
    GRADIENT_RECT gRect;
    gRect.UpperLeft = 0;
    gRect.LowerRight = 1;
    vertex[0].x = fillMe.left;
    vertex[0].y = fillMe.top;
    vertex[0].Red = GetRValue(colStart) << 8;
    vertex[0].Green = GetGValue(colStart) << 8;
    vertex[0].Blue = GetBValue(colStart) << 8;
    vertex[0].Alpha = 255;

    vertex[1].x = fillMe.right;
    vertex[1].y = fillMe.bottom;
    vertex[1].Red = GetRValue(colEnd) << 8;
    vertex[1].Green = GetGValue(colEnd) << 8;
    vertex[1].Blue = GetBValue(colEnd) << 8;
    vertex[1].Alpha = 255;

    if (isVertical)
        GradientFill(hdc, vertex, 2, &gRect, 1, GRADIENT_FILL_RECT_V );
    else
        GradientFill(hdc, vertex, 2, &gRect, 1, GRADIENT_FILL_RECT_H );
}



C++
void drawBigBtn(HDC dst, RECT btnRect, wchar_t *wndText, HFONT btnFont)
{
    RECT topRect, botRect;
    topRect = botRect = btnRect;
    topRect.bottom = botRect.top = ((btnRect.bottom - btnRect.top)/2) + btnRect.top;
    GradientFillRect(dst, topRect, RGB(0x95,0xb3,0xd7), RGB(0x4f,0x8b,0xb0), true);
    GradientFillRect(dst, botRect, RGB(0x4f,0x8b,0xb0), RGB(0x95,0xb3,0xd7), true);

    HBRUSH blueBrush, oldBrush;
    blueBrush = CreateSolidBrush(RGB(79,129,189));
    oldBrush = (HBRUSH) SelectObject(dst, blueBrush);
    FrameRect(dst, &btnRect, blueBrush);
    SelectObject(dst, oldBrush);
    DeleteObject(blueBrush);


    RECT textRect = btnRect;
    textRect.top = textRect.bottom - 40;
    SetBkMode(dst, TRANSPARENT);

   int textLen = wcslen(wndText);
   HFONT oldFont;
   if (btnFont != NULL)
   {
        oldFont = (HFONT)SelectObject( dst, btnFont );
        DrawTextEx( dst, wndText, textLen, &textRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_WORDBREAK, 0 );
        SelectObject(dst, oldFont);
   }
   else
        DrawTextEx( dst, wndText, textLen, &textRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_WORDBREAK, 0 );
}
 
Share this answer
 
v2
Comments
AlwaysLearningNewStuff 11-Nov-13 11:24am    
Thank you!

My +5 :)

I am so embarrassed to miss that out, but fatigue does its job I guess...

I am working on using functions to simplify my code, as you have suggested :)

Until next time, best regards :)
enhzflep 11-Nov-13 11:44am    
My pleasure. Ah, it was an easily missed point.

Functions just reduce the number of times you need to be careful (and a bucket load of typing or copy/pasting) I'm good at making mistakes, so try to minimize the opportunity I get for making them. :laugh:

Till next time it is, cheers! :)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900