zoukankan      html  css  js  c++  java
  • 如何实现掩码位图的透明显示

    位图的透明显示一般有两种机制,即透明色机制和掩码位图机制。透明色机制是把位图中的某种颜色设为透明,掩码位图机制是利用一个掩码位图来确定要透明的部分。本文只介绍掩码位图机制。

    首先来看一个函数:

    void DrawMaskBmp(CDC *pDC,int nX,int nY,CBitmap &bitmap,CBitmap &maskBitmap)
    {
    CDC bitmapDC;
    CBitmap *pOldBmp1;
    BITMAP bmp;
    bitmap.GetBitmap(&bmp);
    bitmapDC.CreateCompatibleDC(pDC);
    pOldBmp1 = bitmapDC.SelectObject(&bitmap);
    CDC maskDC;
    CBitmap *pOldBmp2;
    maskDC.CreateCompatibleDC(pDC);
    pOldBmp2 = maskDC.SelectObject(&maskBitmap);
    CDC bufDC;
    CBitmap bufBitmap,*pOldBmp3;
    bufBitmap.CreateCompatibleBitmap(pDC,bmp.bmWidth,bmp.bmHeight);
    bufDC.CreateCompatibleDC(pDC);
    pOldBmp3 = bufDC.SelectObject(&bufBitmap);
    bufDC.BitBlt(0,0,bmp.bmWidth,bmp.bmHeight,&bitmapDC,0,0,SRCCOPY);
    bufDC.BitBlt(0,0,bmp.bmWidth,bmp.bmHeight,&maskDC,0,0,SRCINVERT);
    bitmapDC.SelectObject(pOldBmp1);
    bitmapDC.DeleteDC();
    pDC->BitBlt(nX,nY,bmp.bmWidth,bmp.bmHeight,&maskDC,0,0,SRCAND);
    pDC->BitBlt(nX,nY,bmp.bmWidth,bmp.bmHeight,&bufDC,0,0,SRCPAINT);
    maskDC.SelectObject(pOldBmp2);
    maskDC.DeleteDC();
    bufDC.SelectObject(pOldBmp3);
    bufDC.DeleteDC();
    bufBitmap.DeleteObject();
    }

    该函数实现了把位图bitmap透明显示到pDC的nX、nY位置,maskBitmap是掩码位图。它的调用方法如下:

    void CMyDialog::MyDraw()
    {
    CBitmap bitmap,maskBitmap;
    bitmap.LoadBitmap(IDB_BITMAP);
    maskBitmap.LoadBitmap(IDB_BITMAP_MASK);
    CClientDC cdc(this);
    DrawMaskBmp(&cdc,85,250,bitmap,maskBitmap);
    bitmap.DeleteObject();
    maskBitmap.DeleteObject();
    }

    从函数DrawMaskBmp可以看到,要实现位图的透明显示,要经过如下几个步骤:

    1、创建一个要显示位图的掩码位图;

    要显示的位图:,掩码位图:。掩码位图是一个单色位图,它的黑色部分就是位图显示时要保留的部分,白色部分就是要透明的部分。

    2、创建一个和该位图大小一样的内存位图和DC(bufBitmap、bufDC),把该位图用SRCCOPY(拷贝)方式显示到这个DC中;

    3、把掩码位图用SRCINVERT(XOR)方式叠加到该内存DC中;

    原位图和掩码位图做了XOR操作后,内存DC中的位图如下所示:,即白色XOR白色=黑色(白色的RGB都是255,1^1=0),黑色XOR任何颜色=原颜色(0^0=0,0^1=1)。

    4、把掩码位图用SRCAND(AND)方式叠加到pDC中;

    and = ,即白色and任何颜色=原颜色(1&1=1,1&0=0),黑色and任何颜色=黑色(0&0=0,0&1=0)。

    5、把bufDC用SRCPAINT(or)方式叠加到pDC中。

    or =,即黑色or任何颜色=原颜色(0|1=1,0|0=0)。

    当然了,上文只是为了说明利用掩码位图进行透明显示的原理,实际应用中用MaskBlt函数更简单,它的原型如下:

    BOOL MaskBlt (
    int
    x,
    int
    y,
    int
    nWidth,
    int
    nHeight,
    CDC*
    pSrcDC,
    int
    xSrc,
    int
    ySrc,
    CBitmap&
    maskBitmap,
    int
    xMask,
    int
    yMask,
    DWORD
    dwRop );

    针对上述情况,pDC->MaskBlt(nX,nY,bmp.bmWidth,bmp.bmHeight,&bitmapDC,0,0,maskBitmap,0,0,0xccaa0000);就可以了。

    补充说明: 0xccaa0000的由来

    MaskBlt的最后一个参数是一个四元光栅操作码,可用MAKEROP4(fore,back)由两个三元光栅操作码生成,当maskBitmap中对应的位为1时,采用fore光栅操作码,否则采用back光栅操作码。此处fore为0x00AA0000(和目标相同),back为0x00CC0000(和源相同),即maskBitmap中黑色(0)对应部分采用pSrcDC中的图像,白色(1)对应部分不改变。三元光栅操作码请参考MSDN中的"Ternary Raster Operations"。

  • 相关阅读:
    SpringCloud学习笔记【七】:Eureka,Consul,Zookeeper注册中心异同点
    SpringCloud学习笔记【六】:Consul实现服务注册与发现
    Docker安装Consul
    SpringCloud学习笔记【五】:Zookeeper代替Eureka实现服务注册与发现
    Docker安装Zookeeper以及Zk常用命令
    SpringCloud学习笔记【四】:Eureka的自我保护机制
    教你如何使用docsify快速部署优美的在线文档
    SpringCloud学习笔记【三】:Actuator微服务信息完善+Discovery获取注册信息
    SpringCloud学习笔记【二】:Eureka服务注册与发现
    WPF应用中一种比较完美的权限控制设计方式
  • 原文地址:https://www.cnblogs.com/lzmfywz/p/2569975.html
Copyright © 2011-2022 走看看