仿苹果工具栏 完美解决图标毛边(黑边)

仿苹果工具栏 完美解决图标毛边(黑边)
预览:


工程下载

      这个是clayui界面库的一个最新的示例,是参照objectDock做的,主要的动态效果都比较完美的实现了,使用方法也一样,直接将桌面上的图标拖进去就可以了。

      先来说说图标毛边的问题吧,这个可能部分同学比较感兴趣。

      当使用Gdiplus::Bitmap::FromHICON载入一个图标对象时,Gdiplus会丢失掉图标的alpha信息,导致绘制时出现毛边(黑边),我个人觉得这应该是一个BUG,下面给出解决方案

      虽然Gdiplus::Bitmap::FromHICON有问题,但是Gdiplus::Bitmap::FromHBITMAP却可以正常工作,不会丢失alpha信息,那么可以先使用GetIconInfo得到图标的ICONINFO,在ICONINFO这个结构里包含有hbmColor,hbmMask这2个HBITMAP对象,hbmColor其实就是图标的图象了,hbmMask是遮罩,得到了这2个HBITMAP,那么就可以根据图标的绘制原理自己加上alpha信息了,具体代码如下:

        ICONINFO icInfo = { 0 };
        if (!::GetIconInfo(hicon, &icInfo))
            return ;

        BITMAP bitmap;
        GetObject(icInfo.hbmColor, sizeof(BITMAP), &bitmap);
        BITMAP bmmask;
        GetObject(icInfo.hbmMask, sizeof(BITMAP), &bmmask);

        //得到遮罩的图象缓存
        BYTE* maskbits = new BYTE[bmmask.bmWidthBytes * bmmask.bmHeight];
        ::GetBitmapBits(icInfo.hbmMask, bmmask.bmWidthBytes * bmmask.bmHeight, maskbits);

        //先从hbmColor创建出Bitmap对象
        Gdiplus::Bitmap *pIcon = Bitmap::FromHBITMAP(icInfo.hbmColor, NULL);

        BitmapData bmpData;
        Rect rect(0,0,pIcon->GetWidth(),pIcon->GetHeight());

        //得到Bitmap的图像缓存,这样就可以根据遮罩来自己加入alpha信息了
        pIcon->LockBits(&rect, ImageLockModeRead, pIcon->GetPixelFormat(), &bmpData);
        BYTE* temp = (bmpData.Stride>0)?((BYTE*)bmpData.Scan0):((BYTE*)bmpData.Scan0+bmpData.Stride*(bmpData.Height-1));
        
        int stride = abs(bmpData.Stride);

        //根据遮罩的图象缓存来还原图标原本的alpha信息
        for ( int i = 0; i < bmpData.Height; i++)
        {
            BYTE* Bits = temp + i * stride;
            
            unsigned char* MaskBits = maskbits + (bmpData.Height - 1 - i) * bmmask.bmWidthBytes;
            int bitoffset = 0;

            for ( int j = 0; j < bmpData.Width; j++ )
            {
                unsigned char Alpha = ( (*MaskBits << bitoffset ++) & 0x80 )?0:255;

                if(Alpha)
                {
                    if(!Bits[j * 4 + 3])
                        Bits[j * 4 + 3] = Alpha;
                }
                else
                    Bits[j * 4 + 3] = 0;

                if  ( ! (bitoffset % 8)  )
                {
                    bitoffset -= 8;
                    MaskBits++;
                }
            }
        }

        delete [] maskbits;

        Bitmap* tp = new Bitmap(pIcon->GetWidth(),pIcon->GetHeight(), abs(bmpData.Stride), PixelFormat32bppARGB, temp);

        pIcon->UnlockBits(&bmpData);

        delete pIcon;

        最后这个tp就是含有alpha信息的图标图象了。

        然后是动态效果,这个大家看工程里的代码吧,主要的实现方面的也就200多行,都在CIconFrame里,我简单说一下要点吧:

        1. 在CIconFrame::OnMM里,根据鼠标与窗口的间距计算窗口的大小,这个也就是窗口随着鼠标移动而改变大小的核心所在了

        2. 在CIconFrame::Update里,按照从左到右方式排列窗口,这样做窗口就会紧紧的靠在一起了

你可能感兴趣的:(仿苹果工具栏 完美解决图标毛边(黑边))