现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

VC++颜色渐变实现的3种方法

2012-08-20 06:30 工业·编程 ⁄ 共 2178字 ⁄ 字号 暂无评论

    要实现窗口(如菜单、按钮、主背景等)背景颜色的多样化,有很多种实现方法,其中颜色渐变就是一种比较常见的方法。它简单实用,即改变了窗口背景颜色的单调,又实现简单。主要方法有很多种,各有各的算法和特点。我在此给大家介绍3种比较简单的方法,且是2种颜色之间的渐变。

1.自绘法:首先获取两种颜色的R、G、B分量的差值,然后获取显示区域的距离,用R、G、B值除以区域的距离获得每一个像素点R、G、B的变化值(即步长),将起始值颜色的R、G、B值+每个像素点的变化值就得到了当前位置的颜色值。程序如下:

void CDrawColorDlg::DrawGradientColor(COLORREF StartColor,COLORREF EndColor)
{
CRect rect;
GetClientRect(rect);//获取窗口的大小
//得到开始颜色值得R、G、B分量
BYTE r1 = GetRValue(StartColor);
BYTE g1 = GetGValue(StartColor);
BYTE b1 = GetBValue(StartColor);
//得到结束颜色值得R、G、B分量
BYTE r2 = GetRValue(EndColor);
BYTE g2 = GetGValue(EndColor);
BYTE b2 = GetBValue(EndColor);
计算两个颜色各个分量的差值
double r,g,b;
r = (double)(r2-r1)/rect.Width();
g = (double)(g2-g1)/rect.Width();
b = (double)(b2-b1)/rect.Width();
BYTE r3;
BYTE g3 ;
BYTE b3;
CDC* pDC = GetDC();//得到DC
//画背景
for (int i = 0 ; i<rect.Width();i++)
{
//计算当前位置的R、G、B分量
  r3 = r1+ i*r;
  g3 = g1+i*g;
  b3 = b1+i*b;
  CPen pen(PS_SOLID,1,RGB(r3,g3,b3));
  pDC->SelectObject(&pen);
  pDC->MoveTo(i,0);
  pDC->LineTo(i,rect.Height());
}
pDC->DeleteDC();
}
该方法的优点就是比较灵活。缺点就是当区域比较大时,绘制比较慢。

2.使用windows的提供的一个API函数GradientFill(): 可以绘制三角形或矩形区域。具体使用可以参考MSDN。具体代码为:
void CDrawColorDlg::DrawGradientColor(COLORREF StartColor,COLORREF EndColor)
{
CRect rect;
GetClientRect(rect);//获取窗口的大小
CDC* pDC = GetDC();//得到DC
//画背景
GradientFillRect(pDC->m_hDC,rect, GRADIENT_FILL_RECT_H, StartColor, EndColor);
pDC->DeleteDC();
}
该方法的优点是最简单有效,缺点是不灵活且该API函数已经快过时了。

3.直接加载外部图片:用第三方工具(特别多且非常强大)将背景做成一张BMP背景图,然后在程序中通过API函数加载显示到背景上。
 
void CDrawColorDlg::DrawGradientColor()
{
CRect rect;
GetClientRect(rect);//获取窗口的大小
CDC* pDC = GetDC();//得到DC
CDC memDC;
memDC.CreateCompatibleDC(pDC);
BITMAP bm;
HBITMAP hBitmap = (HBITMAP)::LoadImage(NULL, m_strBitmap, IMAGE_BITMAP, 0, 0,    LR_DEFAULTSIZE|LR_LOADFROMFILE);
ASSERT(hBitmap);
if (bitmap.m_hObject)
      bitmap.Detach();
bitmap.Attach(hBitmap);
bitmap.GetBitmap(&bm);
CBitmap *pOldBitmap = (CBitmap*)memDC.SelectObject(&bitmap);
//pDC->BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &memDC, 0, 0, SRCCOPY);
pDC->StretchBlt(0, 0, rect.Height(), rect.Width(),&memDC, 0, 0,bm.bmWidth,bm.bmHeight, SRCCOPY); 
pDC->SelectObject(pOldBitmap);
memDC.DeleteDC();
  pDC->DeleteDC();
}
该方法的优点是背景可以借助第三方工具做的非常漂亮,并可以动态改变,缺点是要出硬盘加载图片到内存,相对比较慢(也可以直接放在资源中加载)。

4.GDI+ 函数LinearGradientBrush:不但可以实现两种颜色的渐变,还可以实现3种颜色的渐变。该方法就不具体介绍了。具体可以参看GDI+的介绍。
本文提供了以上3种渐变方法的测试工程,检验证均能满足要求。

工程源码下载地址

给我留言

留言无头像?