现在的位置: 首页 > 综合 > 正文

Win32 使HBITMAP显示成透明效果2

2013年12月12日 ⁄ 综合 ⁄ 共 2136字 ⁄ 字号 评论关闭

我之前写了一篇文章,关于如果将HBITMA(如Excel文件的图标)显示在界面上。

Win32 使HBITMAP显示成透明效果

由于有的HBITMAP有透明色,如果直接把这个HBITMAP画在界面上,透明的地方就会显示成黑色(也不一定是黑色)。当时我用的方法是把这个HBITMAP通过转换成GDI+的Image里面,然后把这个Image画在界面上,这样就可以去掉黑色。最近又发现了一个新的方法,主要的API就是AlphaBlend函数。

先看看效果图:


图一:直接用BitBlt把HBITMAP画到DC上面



图二:通过AlphaBlend将HBITMAP画到DC上面


关于AlphaBlend,MSDN上面的解释是:

The AlphaBlend function
displays bitmaps that have transparent or semitransparent pixels.

BOOL AlphaBlend( 
    HDC hdcDest,  // handle to destination DC
    int nXOriginDest,          // x-coord of upper-left corner
    int nYOriginDest,          // y-coord of upper-left corner
    int nWidthDest,            // destination width 
    int nHeightDest,           // destination height 
    HDC hdcSrc,                // handle to source DC 
    int nXOriginSrc,           // x-coord of upper-left corner 
    int nYOriginSrc,           // y-coord of upper-left corner 
    int nWidthSrc,             // source width
    int nHeightSrc,            // source height 
    BLENDFUNCTION blendFunction  // alpha-blending function 
);

这里最关键的就是设置这个BLENDFUNCTION 函数了,它告诉了API如何混合Alpha。关于Alpha是怎么混合的,MSDN上面有详细说明

我写的代码如下:
case WM_PAINT:
    {
        RECT rc = { 0 };
        GetClientRect(hWnd, &rc);
        int x = (rc.right - 256) / 2;   // 画的图片在窗体中间
        int y = (rc.bottom - 256) / 2;  // 画的图片在窗体中间

        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd, &ps);
        HDC hMemDC = CreateCompatibleDC(NULL);               // 创建一个兼容内存DC
        HGDIOBJ hOldObj = SelectObject(hMemDC, g_hBitmap);   // 将g_bitmap选入到这个内存DC

        // 如果用这句话的话,就会得到图一的效果
        //BitBlt(hdc, x, y, ICON_WIDTH, ICON_HEIGHT, hMemDC, 0, 0, SRCCOPY);

        BLENDFUNCTION ftn = { 0 };
        ftn.BlendOp = AC_SRC_OVER;                           // 目前只能设置这个值
        ftn.AlphaFormat = AC_SRC_ALPHA;                      // 也只能设置这个值
        ftn.BlendFlags = 0;                                  // 必须为0
        ftn.SourceConstantAlpha = 255;                       // 指定源图片的alpha

        // 调用这个函数来进行Alpha混合
        AlphaBlend(hdc, x, y, 256, 256, hMemDC, 0, 0, 256, 256, ftn);

        SelectObject(hMemDC, hOldObj);
        DeleteObject(hMemDC);
        EndPaint(hWnd, &ps);
    }
    break;

如果把BLENDFUNCTION 的 SourceConstantAlpha 不设置为255,那么源HBITMAP是有一个透明度的,比如我把这个值设置为128后,得到的效果图如下:


图三:SourceConstantAlpha设置为128的效果

==================================================================

上面提取的图标的大小是256 * 256。
关于如何提取一个文件的图标,方法如下:

HBITMAP ExtractFileIcon(LPCTSTR pszPath, UINT nWidth, UINT nHeight)
{
    HBITMAP hBitmpa = NULL;
    if ( (NULL != pszPath) && (nWidth > 0.0) && (nHeight > 0.0) )
    {
        IShellItemImageFactory *psif = NULL;
        SIZE size = { nWidth, nHeight };
        HRESULT hr = ::SHCreateItemFromParsingName(pszPath, NULL, IID_PPV_ARGS(&psif));
        if ( SUCCEEDED(hr) && (NULL != psif) )
        {
            psif->GetImage(size, SIIGBF_ICONONLY, &hBitmpa);
        }
        SAFE_RELEASE(psif);
    }

    return hBitmpa;
}


抱歉!评论已关闭.