【问题标题】:Modify RGB parameter of GradientFill API to avoid code modification修改 GradientFill API 的 RGB 参数,避免代码修改
【发布时间】:2014-04-10 12:04:37
【问题描述】:

简介及相关资料:

我正在使用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: { 矩形 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;
    

当程序启动时,你应该得到这个:

在您将窗口向左移动很远(因此它的一部分“离开屏幕”变得不可见)然后将其移回后,您应该会得到:

我为解决这个问题所做的努力:

按照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

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

问题:

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

谢谢。

最好的问候。

【问题讨论】:

  • 您似乎想为 WM_ERASEBKGND 返回一个非零值以忽略它,并首先在 WM_PAINT 中绘制背景。

标签: c++ winapi gradient gdi


【解决方案1】:

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

您可以随意命名它们,但在您的情况下,适当的名称可以是“top1”、“bottom1”、“top2”和“bottom2”。

在第一次调用 GradientTriangle 函数时,将 topbottom 最后两个参数设置为 top1 和 bottom1 全局变量,并在第二次调用 GradientTriangle 函数时,将 topbottom 最后两个参数设置为 top2 和 bottom2 全局变量,而不是您所做的 constant 值:

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。

修改后调用 either InvalidateRect or RedrawWindow or UpdateWindow 函数,如果你没有看到你的变化客户端窗口

毕竟您会注意到渐变三角形的颜色会在您的客户端窗口中发生变化。

我认为这一切都应该回答你的问题。

希望对你有帮助。

祝我的想法好运!

【讨论】:

  • 不幸的是结果完全一样。我的WM_SIZE 处理程序中有InvalidateRect 调用,但这没关系。这个问题在我在帖子中链接的问题的公认答案中得到了很好的描述。请参阅我的帖子中的我为解决这个问题所做的努力: 部分,并仔细阅读我提供的链接中接受的答案。感谢您的帮助。最好的问候!
【解决方案2】:

在您的 PROBLEM: 部分中,我知道您想要删除图形伪影,但在您的 QUESTION: 部分中,您想要修改传递给您的辅助函数,以便您可以获得正确的渐变颜色。

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

我只帮助了你关于你并不真正想要的那个。

您寻求的答案不是解决您的问题的方法!

我还从您的评论了解到,您想要解决方案解决您的问题,而不是您问题的答案,不像 你的头衔:

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

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

可惜结果一模一样

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

一开始,我不得不尝试解决你的问题,而不是回答你的问题,或者至少尝试两者

我认为解决您的问题的方法是将 InvalidateRect 调用移至WM_MOVE 处理程序,不是WM_SIZE 处理程序中,因为

当将窗口移到最左边时,它的一部分会离开 视线

当你这样做时,WM_MOVE 正在处理,或者换句话说,你放入这个处理程序的代码正在执行,不是 WM_SIZE,因为你在移动 窗口,调整它的大小,或改变它的大小。

您也可以尝试:WM_MOVINGWM_WINDOWPOSCHANGEDWM_WINDOWPOSCHANGING

使任一定时器线程自动调用InvalidateRect。 使用SetTimerCreateThread 函数来初始化计时器或线程并启动其中一个。使用Sleep函数延迟线程。

调用 either KillTimer SuspendThread 以停止或结束计时器或线程。

【讨论】:

  • 感谢您一直以来的支持,我会尽快尝试您的建议(目前我有其他优先职责)并将报告我的结果。最好的问候,直到问候。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-04
  • 1970-01-01
  • 2018-06-22
  • 2013-12-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多