AlwaysLearningNewStuff
AlwaysLearningNewStuff

Reputation: 3031

Modify RGB parameter of GradientFill API to avoid code modification

INTRODUCTION AND RELEVANT INFORMATION:

I am using GradientFill API to draw 2 gradient triangles.

Here is the helper function I wrote:

void GradientTriangle( HDC MemDC, 
    LONG x1, LONG y1, 
    LONG x2, LONG y2, 
    LONG x3, LONG y3, 
    COLORREF top, COLORREF bottom )
{
    TRIVERTEX vertex[3];

    vertex[0].x     = x1;
    vertex[0].y     = y1;
    vertex[0].Red   = GetRValue(bottom) << 8;
    vertex[0].Green = GetGValue(bottom) << 8;
    vertex[0].Blue  = GetBValue(bottom) << 8;
    vertex[0].Alpha = 0x0000;

    vertex[1].x     = x3;
    vertex[1].y     = y3; 
    vertex[1].Red   = GetRValue(bottom) << 8;
    vertex[1].Green = GetGValue(bottom) << 8;
    vertex[1].Blue  = GetBValue(bottom) << 8;
    vertex[1].Alpha = 0x0000;

    vertex[2].x     = x2;
    vertex[2].y     = y2;
    vertex[2].Red   = GetRValue(top) << 8;
    vertex[2].Green = GetGValue(top) << 8;
    vertex[2].Blue  = GetBValue(top) << 8;
    vertex[2].Alpha = 0x0000;

    // Create a GRADIENT_TRIANGLE structure that
    // references the TRIVERTEX vertices.

    GRADIENT_TRIANGLE gTriangle;

    gTriangle.Vertex1 = 0;
    gTriangle.Vertex2 = 1;
    gTriangle.Vertex3 = 2;

    // Draw a shaded triangle.

    GradientFill( MemDC, vertex, 3, &gTriangle, 1, GRADIENT_FILL_TRIANGLE);
}

PROBLEM:

I am facing a problem on Windows XP where I get graphic artifact when moving the window to the far left, so portion of it gets out of sight.

In order to reproduce the problem, here are the instructions for making a SSCCE :

  1. Make a default Win32 project in Visual studio.

  2. Add the above helper function.

  3. Add the following WM_ERASEBKGND handler:

    case WM_ERASEBKGND: { RECT r; GetClientRect( hwnd, &r );

        // bottom triangle --> need help with this one!!
        GradientTriangle( (HDC)wParam, 
            r.left, r.top, 
            r.left, r.bottom - r.top,
            r.right, r.bottom - r.top,
            RGB( 0x0, 0x0, 0xFF ), RGB( 0xFF, 0xFF, 0x0 ) );
    
        // top triangle --> this one is fine !
        GradientTriangle( (HDC)wParam, 
            r.right, r.bottom - r.top,
            r.right, r.top,
            r.left, r.top,  
            RGB( 0xFF, 0x0, 0x0 ), RGB( 0x0, 0xFF, 0x0 ) );
    }
    return 1L;
    

When program starts you should get this:

enter image description here

After you move the window far to the left ( so portion of it goes "out of the screen" becoming invisible ) and then move it back you should get this:

enter image description here

MY EFFORTS TO SOLVE THIS:

Following instructions from answer to my previous similar question I was able to solve the problem with the artifact by switching the order of the coordinates passed to the helper function.

Still, the color of the bottom triangle has changed and I need help to modify RGB parameters to get it right.

Here is my workaround:

// I have modified parametters for bottom triangle 
GradientTriangle( (HDC)wParam, 
    r.left, r.top,
    r.right, r.bottom - r.top,  //  switched places
    r.left, r.bottom - r.top,   //  of these two coordinates
    RGB( 0x0, 0x0, 0xFF ), RGB( 0xFF, 0xFF, 0x0 ) );  // but color has changed

As I have said, the artifacts disappeared but the resulting color has changed:

enter image description here

QUESTION:

How can I modify RGB parameters passed to my helper function so I can get the proper gradient color?

Thank you.

Best regards.

Upvotes: 2

Views: 674

Answers (2)

user2133061
user2133061

Reputation:

In your PROBLEM: section, I understand that you want to remove the graphic artifact, but in your QUESTION: section, you want to modify the RGB parameters passed to your helper function so you can get the proper gradient color.

In conclusion, you request two different things, but actually you want to achieve one of them only.

I only helped you about the one you didn't really want.

You seek to an answer which is not the solution to your problem!

I also understood from your comment that you want the solution to your problem, not the answer to your question, unlike your title:

Modify RGB parameter of GradientFill API to avoid code modification

, because I already answered your question, but your response is to tell me:

Unfortunately the result is exactly the same

You thought that the answer to your question is the solution to your problem, so you waited for the answer, because you didn't know before my first answer how to do what you asked, but you wrong, In my opinion, the answer to your question is not the solution to your problem.

At the beginning of first, I had to try to solve your problem, not to answer your question, or at least try the both.

I think that the solution to your problem is to move the InvalidateRect call to WM_MOVE handler, not in WM_SIZE handler, because

when moving the window to the far left, so portion of it gets out of sight

While you are doing this, WM_MOVE is handling, or in other words, the code you put in this handler is executing, not WM_SIZE, because you are moving the window, not resizing it, or changing its size.

You also can try: WM_MOVING, WM_WINDOWPOSCHANGED or WM_WINDOWPOSCHANGING

or make either timer or thread which will automaticly call InvalidateRect. Use either SetTimer or CreateThread function to initialize a timer or thread and start one of them. Use the Sleep function to delay the thread.

Call either KillTimer or SuspendThread to stop or finish with the timer or with the thread.

Upvotes: 0

user2133061
user2133061

Reputation:

Make four global variables of type COLORREF structure.

You can name them whatever you want, but in your case the appropriate names can be "top1" "bottom1", "top2" and "bottom2".

In the first call to your GradientTriangle function, set the top and bottom last two parameters to the values of top1 and bottom1 global variables respectively, and in the second call to your GradientTriangle function, set the top and bottom last two parameters to the values of top2 and bottom2 global variables respectively, instead of the constant values you did:

RGB( 0x0, 0x0, 0xFF ), RGB( 0xFF, 0xFF, 0x0 ), RGB( 0xFF, 0x0, 0x0 ), and RGB( 0x0, 0xFF, 0x0 ).

You should set each of your global variables by each of these values I mentioned above respectively, i.e. like the code example below:

// Global Variables:
COLORREF top1 = RGB( 0x0, 0x0, 0xFF )
COLORREF bottom1 = RGB( 0xFF, 0xFF, 0x0 )
COLORREF top2 = RGB( 0xFF, 0x0, 0x0 )
COLORREF bottom2 = RGB( 0x0, 0xFF, 0x0 )

// bottom triangle --> need help with this one!!
GradientTriangle( (HDC)wParam, 
    r.left, r.top, 
    r.left, r.bottom - r.top,
    r.right, r.bottom - r.top,
    top1, bottom1 ); //not RGB( 0x0, 0x0, 0xFF ), RGB( 0xFF, 0xFF, 0x0 ), unlike in the code you posted

// top triangle --> this one is fine !
GradientTriangle( (HDC)wParam, 
    r.right, r.bottom - r.top,
    r.right, r.top,
    r.left, r.top,  
    top2, bottom2 ); //not RGB( 0xFF, 0x0, 0x0 ), RGB( 0x0, 0xFF, 0x0 ), unlike in the code you posted
}
return 1L;

How can I modify RGB parameters passed to my helper function so I can get the proper gradient color?

You don't modify RGB parameters, but you modify the four global variables instead, i.e. top1, bottom1, top2 and bottom2.

After modification call either InvalidateRect or RedrawWindow or UpdateWindow function, if you don't see changes in your client window.

After all you will notice that the colors of your gradient triangles will change in your client window.

I think that all this should answer your question.

I hope it helps you.

Good luck with my idea!

Upvotes: 1

Related Questions