IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

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

    lincyang发表于 2014-08-22 10:47:56
    love 0
    

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

    么图片的类型我们也要考虑进来。现在是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+实现完美不规则窗体。











沪ICP备19023445号-2号
友情链接