最近一直在做一个涉及到很多Windows Region区域处理的项目,在开展的过程中,另我想起了几年前看到的一篇讲制作桌面精灵的文章(
[url]http://www.vckbase.com/vckbase/vckbase12/vc/nonctrls/multimedia_22/1222001.htm[/url]),里面使用的技巧就是区域操作,但由于当时的水平不够,该文章的作者解释得又不是很详细,一直没有看懂,此番重读此代码,终于理解了,在这里记录下来。
那个代码(参见上面的连接)例子的主要部分如下:
首先要说明的是,桌面精灵图片是由中间一个人物和四周是白色象素的一个合成的矩形。这个也可以参见链接提供的源码中的资源文件。
void TransparentWnd::SetupRegion(CDC *pDC)
{
CDC memDC;
CBitmap &cBitmap=m_bmpDraw;
CBitmap* pOldMemBmp = NULL;
COLORREF col,colMask;
CRect cRect;
int x, y;
CRgn wndRgn, rgnTemp;
首先要说明的是,桌面精灵图片是由中间一个人物和四周是白色象素的一个合成的矩形。这个也可以参见链接提供的源码中的资源文件。
void TransparentWnd::SetupRegion(CDC *pDC)
{
CDC memDC;
CBitmap &cBitmap=m_bmpDraw;
CBitmap* pOldMemBmp = NULL;
COLORREF col,colMask;
CRect cRect;
int x, y;
CRgn wndRgn, rgnTemp;
GetWindowRect(&cRect);
CPoint ptOrg=cRect.TopLeft();
CPoint ptOrg=cRect.TopLeft();
BITMAP bmInfo;
cBitmap.GetObject(sizeof(bmInfo),&bmInfo);
CRect rcNewWnd=CRect(ptOrg,CSize(bmInfo.bmWidth,bmInfo.bmHeight));
cBitmap.GetObject(sizeof(bmInfo),&bmInfo);
CRect rcNewWnd=CRect(ptOrg,CSize(bmInfo.bmWidth,bmInfo.bmHeight));
memDC.CreateCompatibleDC(pDC);
pOldMemBmp = memDC.SelectObject(&cBitmap);
colMask=memDC.GetPixel(0,0);//这里取得左上角的象素,为白色。
pOldMemBmp = memDC.SelectObject(&cBitmap);
colMask=memDC.GetPixel(0,0);//这里取得左上角的象素,为白色。
wndRgn.CreateRectRgn(0, 0, rcNewWnd.Width(), rcNewWnd.Height());
for(x=0; x<=rcNewWnd.Width(); x++)
{
for(y=0; y<=rcNewWnd.Height(); y++)
{
//这里比较图片每一点上的象素,如果和左上角的象素相同,即也是白色,就做异或运算,结果为0,意即扣去了这一点,如此这般就扣去了整个矩形图片中所有白色的部分,剩余的部分就是精灵人物了。
col = memDC.GetPixel(x, y);
if(col == colMask)
{
rgnTemp.CreateRectRgn(x, y, x+1, y+1);
wndRgn.CombineRgn(&wndRgn, &rgnTemp, RGN_XOR);
rgnTemp.DeleteObject();
}
}
}
if (pOldMemBmp) memDC.SelectObject(pOldMemBmp);
SetWindowRgn((HRGN)wndRgn, TRUE);//这句话是将窗口的形状设置为剩余区域的大小。
MoveWindow(rcNewWnd);
}
//然后在重绘窗口函数中,调用位拷贝函数BitBlt来贴图。该重绘窗口函数由Invalidate()触发。
BOOL TransparentWnd::OnEraseBkgnd(CDC* pDC)
{
CRect rect;
GetWindowRect(&rect);
for(x=0; x<=rcNewWnd.Width(); x++)
{
for(y=0; y<=rcNewWnd.Height(); y++)
{
//这里比较图片每一点上的象素,如果和左上角的象素相同,即也是白色,就做异或运算,结果为0,意即扣去了这一点,如此这般就扣去了整个矩形图片中所有白色的部分,剩余的部分就是精灵人物了。
col = memDC.GetPixel(x, y);
if(col == colMask)
{
rgnTemp.CreateRectRgn(x, y, x+1, y+1);
wndRgn.CombineRgn(&wndRgn, &rgnTemp, RGN_XOR);
rgnTemp.DeleteObject();
}
}
}
if (pOldMemBmp) memDC.SelectObject(pOldMemBmp);
SetWindowRgn((HRGN)wndRgn, TRUE);//这句话是将窗口的形状设置为剩余区域的大小。
MoveWindow(rcNewWnd);
}
//然后在重绘窗口函数中,调用位拷贝函数BitBlt来贴图。该重绘窗口函数由Invalidate()触发。
BOOL TransparentWnd::OnEraseBkgnd(CDC* pDC)
{
CRect rect;
GetWindowRect(&rect);
CDC memDC;
CBitmap &cBitmap=m_bmpDraw;;
CBitmap* pOldMemBmp = NULL;
CFont* pOldMemFont=NULL;
CBitmap &cBitmap=m_bmpDraw;;
CBitmap* pOldMemBmp = NULL;
CFont* pOldMemFont=NULL;
memDC.CreateCompatibleDC(pDC);
pOldMemBmp = memDC.SelectObject(&cBitmap);
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);
pOldMemBmp = memDC.SelectObject(&cBitmap);
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);
if (pOldMemBmp) memDC.SelectObject( pOldMemBmp );
return TRUE;
// return CWnd::OnEraseBkgnd(pDC);
}
// return CWnd::OnEraseBkgnd(pDC);
}
本文转自 xchsp 51CTO博客,原文链接:http://blog.51cto.com/freebird/88476,如需转载请自行联系原作者