修改GradientFill API的RGB参数以避免代码修改

时间:2014-04-10 12:04:38

标签: c++ winapi gradient gdi

引言及相关资料:

我使用GradientFill API绘制2个渐变三角形。

这是我写的辅助函数:

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);
}

问题:

我在Windows XP面临一个问题,当我将窗户移到最左边时,我会得到图形神器,所以它的一部分不在视线范围内。

为了重现该问题,以下是制作SSCCE的说明:

  1. 在Visual Studio中创建默认的Win32项目。

  2. 添加上述帮助函数。

  3. 添加以下WM_ERASEBKGND处理程序:

    案例WM_ERASEBKGND:     {         RECT r;         GetClientRect(hwnd,&amp; 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;
    
  4. 当程序启动时,你应该得到这个:

    enter image description here

    将窗口向左移动很远(因此它的一部分进入&#34;离开屏幕&#34;变得不可见)然后将其向后移动你应该得到这个:

    enter image description here

    我努力解决这个问题:

    按照my previous similar question的回答,我能够通过切换传递给辅助函数的坐标的顺序来解决工件的问题。

    尽管如此,底部三角形的颜色已经改变,我需要帮助来修改RGB参数以使其正确。

    以下是我的解决方法:

    // 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
    

    正如我所说,文物消失了,但结果颜色发生了变化:

    enter image description here

    问题:

    如何修改传递给辅助函数的RGB参数,以便获得正确的渐变颜色?

    谢谢。

    最好的问候。

2 个答案:

答案 0 :(得分:1)

制作类型COLORREF结构的四个全局变量。

您可以根据需要为其命名,但在您的情况下,相应的名称可以是“top1”“bottom1”,“top2”和“bottom2”。

在第一次调用GradientTriangle功能时,将顶部底部最后两个参数设置为 top1 的值和 bottom1 全局变量分别在第二次调用GradientTriangle函数时,将顶部底部最后两个参数设置为分别是 top2 bottom2 全局变量的值,而不是您执行的常量值:

RGB(0x0,0x0,0xFF),RGB(0xFF,0xFF,0x0),RGB(0xFF,0x0,0x0)和RGB(0x0,0xFF,0x0)。

您应该分别按照我上面提到的每个值设置每个全局变量,例如下面的代码示例:

// 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;
  

如何修改传递给我的辅助函数的RGB参数呢?   得到适当的渐变颜色?

您不修改RGB参数,但修改四个全局变量,即top1,bottom1,top2和bottom2。

修改后调用 InvalidateRect RedrawWindow UpdateWindow功能,如果你不喜欢看不到客户端窗口中的更改

毕竟你会发现渐变三角形的颜色会在客户端窗口中发生变化。

我认为所有这些都应该回答你的问题。

我希望它可以帮到你。

祝你好运!

答案 1 :(得分:0)

问题部分中,我了解您要删除图形工件,但在问题:部分,您要修改传递给的RGB参数您的助手功能,以便您可以获得正确的渐变颜色。

总之,您要求两个不同的内容,但实际上您只想实现其中一个

我只帮助你了解你真正不想要的那个。

您寻求一个解决问题的答案!

我也从您的评论中了解到您希望解决方案问题,而不是您的问题的答案,不同你的头衔:

  

修改GradientFill API的RGB参数以避免代码修改

,因为我已经回答了你的问题,但你的回答是告诉我:

  

不幸的是结果完全一样

您认为问题的答案是您的问题的解决方案,所以您等待答案,因为您在我的第一个答案之前不知道如何做您所问的,但您错误,在我看来,你的问题的答案是解决你的问题。

首先,我必须尝试解决您的问题,而不是回答您的问题,或者至少尝试两者

我认为您的问题的解决方案是将InvalidateRect调用移至WM_MOVE处理程序中的<{1}}处理程序,而不是,因为

  

当窗口移动到最左侧时,它的一部分就会离开   视线

在执行此操作时,WM_SIZE正在处理,或者换句话说,您在此处理程序中执行的代码正在执行,不是 WM_MOVE,因为您<强>移动窗口,调整大小或更改其大小。

您还可以尝试:WM_SIZEWM_MOVINGWM_WINDOWPOSCHANGED

使 计时器线程自动调用InvalidateRect。 使用WM_WINDOWPOSCHANGINGSetTimer函数初始化计时器或线程并启动其中一个。使用CreateThread功能延迟线程。

致电 Sleep KillTimer停止或完成计时器或线程。