为了实现更加逼真的立体边框效果,制作一个相册框,我们可以实现一个立体边框,然后在中间贴图即可。纯GDI代码实现的立体效果,不依赖其他图形库。
下面是效果图:
1.立体边框特效
2.发光的立体边框特效
3.这个效果不知道如何描述,自己看着办吧。
4.这个是巨款的相册框,立体感十足。
立体边框的原理的基础还是渐变色。从内到中间,然后从外到中间,从暗到亮颜色的渐变就是一般的立体框效果,如果从亮到暗的渐变,就是发光的立体框了。
了解了这个基本原理后,就可以分分钟实现立体框了。不过我写好了函数,只需要简单调用函数就可以实现这些效果了。
下面是函数声明:
void GradientLinearCenterBorder(CDC* pDC,CRect rt,COLORREF clr1,COLORREF clr2,int len,bool swap)
函数参数的用法,请参考《GDI矩形立体渐变、矩形放射渐变和矩形平面放射渐变原理以及代码实现》。
函数的使用示例代码:
CDC *pDC = GetDC();
CRect rtClient(50,50,400,300);
GradientLinearCenterBorder(pDC,rtClient,RGB(255,255,10),RGB(0,0,255),70,true);
函数的实现代码:
void GradientLinearCenterBorder(CDC* pDC,CRect rt,COLORREF clr1,COLORREF clr2,int len,bool swap)
{
//使用内存DC来加速绘制,防止闪烁
CDC dcMem;
dcMem.CreateCompatibleDC(pDC);
CBitmap bmp;
bmp.CreateCompatibleBitmap(pDC,rt.Width(),rt.Height());
dcMem.SelectObject(&bmp);
//开始内存绘制
//rtTmp用于绘制,rt用于画布
CRect rtTmp(0,0,rt.Width(),rt.Height());
rtTmp.left += len;
rtTmp.top += len;
rtTmp.right -= len;
rtTmp.bottom -= len;
int width = rtTmp.Width();
int height = rtTmp.Height();
if (swap)
{
COLORREF clrTmp = clr1;
clr1 = clr2;
clr2 = clrTmp;
}
int r1 = GetRValue(clr1);
int r2 = GetRValue(clr2);
int g1 = GetGValue(clr1);
int g2 = GetGValue(clr2);
int b1 = GetBValue(clr1);
int b2 = GetBValue(clr2);
int rSpan = r2 - r1;
int gSpan = g2 - g1;
int bSpan = b2 - b1;
int len_clr=0;
CFont font;
font.CreatePointFont(100,_T("微软雅黑"));
dcMem.SelectObject(&font);
dcMem.SetBkMode(TRANSPARENT);
dcMem.SetTextColor(RGB(255,255,255));
dcMem.DrawText(_T("欢迎来到C++技术网。\r\n网址:www.cjjjs.com\r\n一起来探索奇妙的编程世界吧!\r\n放下作业,放下背诵,自由的舞动代码吧。\r\n关注微信公众号:cpp_coder"),&rtTmp,DT_LEFT);
for (int i=0;i<len/2;i++)
{
COLORREF clr = RGB(r1+(i*rSpan)/len,g1+(i*gSpan)/len,b1+(i*bSpan)/len);
CBrush brush(clr);
rtTmp.InflateRect(1,1,1,1);
dcMem.FrameRect(&rtTmp,&brush);
}
rSpan = r1 - r2;
gSpan = g1 - g2;
bSpan = b1 - b2;
for (int i=len/2;i<len;i++)
{
COLORREF clr = RGB(r2+(i*rSpan)/len,g2+(i*gSpan)/len,b2+(i*bSpan)/len);
CBrush brush(clr);
rtTmp.InflateRect(1,1,1,1);
dcMem.FrameRect(&rtTmp,&brush);
}
//将内存的数据一次性贴到设备DC中
pDC->BitBlt(rt.left,rt.top,rt.Width(),rt.Height(),&dcMem,0,0,SRCCOPY);
bmp.DeleteObject();
dcMem.DeleteDC();
}
函数实现的思路,和前面几个代码相似,也就不多说了。