首页 > 代码库 > VC++玩转炫酷悬浮窗2---不规则窗体的实现(常规)

VC++玩转炫酷悬浮窗2---不规则窗体的实现(常规)

??

目标
不规则窗体也称为异型窗体,像迅雷的飞鸟型窗体就是啦。这篇文章就是要实现这样的窗体。
计划&方案
根据上一篇文章继续扩展。我们有几种方案实现不规则窗体。迅雷就是用一张图片作为窗体的形状,那

么图片的类型我们也要考虑进来。现在是png图片的天下,自带背景透明;对于bmp图片,需要程序处理

一下。
对于常规图形如圆形,只需要SetWindowRgn就可以搞定。对于复杂图形,需要用一点技巧来做。下面用

例子来演示圆形和复杂图形的不规则窗体。
关于SetWindowRgn,参见官方文档。

实践
一、 圆形窗体
这里还要借助另一个类CRgn,它作为SetWindowRgn的主要参数,通过CreateEllipticRgn方法初始化

出圆形区域。具体代码如:

    CRgn rgn;
    rgn. CreateEllipticRgn(0,0,96,96);
    SetWindowRgn(rgn,TRUE);

接下来封装一个方法来加载png图片:

void ShowPicture()
{
    CImage img;    
    HRESULT result = img.Load(_T("prime.png")); 
    //加强透明化
    for(int i = 0; i < img.GetWidth(); i++)  
    {  
        for(int j = 0; j < img.GetHeight(); j++)  
        {  
            unsigned char* pucColor = reinterpret_cast<unsigned char *>

(img.GetPixelAddress(i , j));  
            pucColor[0] = pucColor[0] * pucColor[3] / 255;  
            pucColor[1] = pucColor[1] * pucColor[3] / 255;  
            pucColor[2] = pucColor[2] * pucColor[3] / 255;  
        }  
    }     
    CDC *pDC = GetWindowDC();
    int nX = img.GetWidth();
    int nY = img.GetHeight();

    img.Draw( pDC->m_hDC,0,0); 
    ReleaseDC( pDC );
}

二、 复杂图形窗体
引用vckbase的文章《Windows 中不规则窗体的编程实现》中“根据图像创建region”一节。

技巧:选一种图片中没有的颜色作为背景色(文章中用蓝色),程序将扫描图片的每一个像素,如果不是

背景色,那么就在此位置创建此像素的region,然后把所有这样的region合并起来构成图片,就好像

去掉了背景色一样,成为背景透明。
这里又用到一个合并region的api  CombineRgn:

int CombineRgn( 
   CRgn* pRgn1, 
   CRgn* pRgn2, 
   int nCombineMode  
);

合并的模式我们选择完全合并:
RGN_OR   Combines both regions in their entirety (union).
例子如下:

void CAfoatWindowMessageDlg::SetupRegion(
    CDC *pDC, //DC of this window
    CBitmap &cBitmap, 
    COLORREF TransColor //the color need remove
    )
{    CDC memDC;
    //temporary DC
    memDC.CreateCompatibleDC(pDC);

    CBitmap *pOldMemBmp=NULL;
    //Load bmp file
    pOldMemBmp=memDC.SelectObject(&cBitmap);
   
    CRgn wndRgn; // window region
    //window region init
    wndRgn.CreateRectRgn(0,0,0,0);
 
    BITMAP bit;   
    cBitmap.GetBitmap (&bit);//get the value of bmp file    
   
    int y;
    for(y=0;y<=bit.bmHeight  ;y++)
    {
	    CRgn rgnTemp; //temporary region            
        int iX = 0;
        do
        {
            //skip TransColor
            while (iX <= bit.bmWidth  && memDC.GetPixel(iX, y) == TransColor)
                iX++;

            //record this point
            int iLeftX = iX;

            //Skip none transColor
            while (iX <= bit.bmWidth  && memDC.GetPixel(iX, y) != TransColor)
                ++iX;

            //create temporary “region”
            rgnTemp.CreateRectRgn(iLeftX, y, iX, y+1);

            //combine "region".
            wndRgn.CombineRgn(&wndRgn, &rgnTemp, RGN_OR);
                
		    //delete temporary "region"
            rgnTemp.DeleteObject();
        }while(iX <bit.bmWidth );
        iX = 0;
    }

    if(pOldMemBmp)
        memDC.SelectObject(pOldMemBmp);
    
    CWnd * pWnd = pDC->GetWindow();
    pWnd->SetWindowRgn(wndRgn,TRUE);    
    pWnd->SetForegroundWindow();    
}


源码在此!
通过对比,用常规方法都会产生锯齿,如何消除锯齿?引出我的下文,用GDI+实现完美不规则窗体。









VC++玩转炫酷悬浮窗2---不规则窗体的实现(常规)