当前位置: 永利棋牌 > 儿童文学 > 正文

轻松消除贴图闪烁,画透明位图

时间:2019-10-01 13:19来源:儿童文学
画透明位图 mfc显示透明背景代码看不大懂 /*-----------------显示透明背景图片-------------------*/ //======================================================================== //TITLE: //    轻松消除贴图闪烁 /

画透明位图

mfc显示透明背景代码看不大懂
/*-----------------显示透明背景图片-------------------*/

//========================================================================
//TITLE:
//    轻松消除贴图闪烁
//AUTHOR:
//    norains
//DATE:
//    Thursday  25-December -2006
//Environment:
//  EVC4.0 + Standard SDK
//========================================================================
    有没有在程序中尝试过贴图?我们都有这么一个经验,如果直接往屏幕贴图,一张图我们觉得显示正常流畅;两张图,如果图片不大,并且速度也够快的话,我们也觉得没问题;但如果,有一张很大的位图,并且我们需要在位图上面输出文本,甚至在这张位图上面还要再贴另外的位图----可能是两张,也可能是十张,甚至是百张----那展现在我们面前的将是什么呢?我们将看到,屏幕上位图缓慢地一张一张出现,造成一种让人烦躁的闪烁效果.
    那有没有办法实现上面所需的功能,并且又不显得闪烁呢?方法当然有,并且也极为简单.一句话,就是把所有的数据往内存里写,然后再把内存的数据显示到屏幕上.
    好了,那现在让我们开始吧!
   
    首先,让我们获取一个屏幕的DC.这个DC嘛,就是显示给我们看的屏幕的设备.
    HDC hdc = GetDC(m_hWnd);
   
    如果代码是用来响应WM_PAINT,那么这个DC句柄的获得应该使用另外一个函数:
    HDC hdc = BeginPaint(m_hWnd,&ps);
   
    嗯,接下来我们要做的就是,创建一个和设备DC相符合的内存DC.换句话说,就是开辟一块内存空间,并且这空间的大小足以用来表示设备DC的数据.
    HDC hdcMem = CreateCompatibleDC(hdc);
   
    内存分配完毕之后,我们需要告诉程序这内存是用来干什么的,也就是说,这内存的格式是什么.这和变量声明比较像,不过却更为复杂.
  最初,我们需要创建一个符合目前设备DC的位图格式:
  HBITMAP hBitmap = CreateCompatibleBitmap(hdc,IMG_MAINWND_WIDTH,IMG_MAINWND_HEIGHT);
  
  最后就是把创建的这个位图和内存DC关联.
  HGDIOBJ hOldSel = SelectObject(hdcMem,hBitmap);
  
  好了,供贴图的内存已经准备好了,现在我们想干嘛就可以干嘛了.嗯,那我们还是赶快尝试一把吧.好,就先从位图绘制开始吧.
  由于位图的绘制比较复杂,并且其数据必须要和内存关联,然后才能读取位图的数据.所以我们第一步还是需要先建立一个适合设备DC的位图DC:
  HDC hdcBmp = CreateCompatibleDC(hdc);
  
  读取位图数据:
  HANDLE hBmp= LoadImage(m_hInst,MAKEINTRESOURCE(IDB_MAINWND),IMAGE_BITMAP,0,0,0);
  
  将位图数据和位图DC关联起来:
  HGDIOBJ hOldBmpSel = SelectObject(hdcBmp,hBmp);
  
  将位图数据复制到内存DC中:
  BitBlt(hdcMem,0,0,IMG_MAINWND_WIDTH,IMG_MAINWND_HEIGHT,hdcBmp,0,0,SRCCOPY);
  
  好了,现在位图已经绘制到内存去了,看起来也不是很复杂嘛!
  
  如果我们想在内存中输出文本,该怎么做呢?呵呵,这比绘制位图要简单多了:
  DrawText(hdcMem,TEXT("输出文本"),-1,&rc,DT_LEFT);
  
  嗯,就是这样,仅仅一条语句.如果还想让输出的文本背景透明,并且也想改变字体的颜色,在绘图前我们之需要添加以下语句即可:
  COLORREF oldColor;
  SetBkMode(hdcMem,TRANSPARENT);
  oldColor = SetTextColor(hdcMem,RGB(40,96,170));
  
  当然,绘制完毕之后,把原来的颜色还原是一个好习惯:
  SetTextColor(hdcMem,oldColor);
  
  做到现在,是不是已经迫不及待地想将成果显示到屏幕上了呢?好,那就让我们看看成果吧: 
  BitBlt(hdc,rc.left,rc.top,(rc.right - rc.left),(rc.bottom - rc.top),hdcMem,rc.left,rc.top,SRCCOPY);
  
  怎么样?是不是显示得非常流畅,完全没有闪烁的现象?
  
  做到这里,是不是非常高兴,就想着拿这段代码去应用了?等等,先别急,我们还需要清除一下我们狂欢后留下的垃圾,否则,系统这家伙就要生气,说不定就会来个蓝屏当机哦!
  SelectObject(hdcBmp,hOldBmpSel);
  SelectObject(hdcMem,hOldSel);
  DeleteObject(hBitmap);
  DeleteDC(hdcMem);
  ReleaseDC(m_hWnd,hdc); //如果是响应WM_PAINT消息,这里应改成:EndPaint(m_hWnd,&ps);
  
  如果我们想做得更完美一些,甚至可以不用响应WM_ERASEBKGND消息.因为WM_ERASEBKGND会占用一帧来绘制.所以我们需要做的是,只要检测到WM_ERASEBKGND消息,直接返回.
  
  附录1.
  无闪烁的完整代码(其中的一些未知变量,窗口句柄需根据实际情况更改):
  HDC hdc = GetDC(m_hWnd);
  //Create a DC that matches the device
  HBITMAP hBitmap = CreateCompatibleBitmap(hdc,IMG_MAINWND_WIDTH,IMG_MAINWND_HEIGHT);
  HDC hdcMem = CreateCompatibleDC(hdc);
  //Select the bitmap into to the compatible device context
  HGDIOBJ hOldSel = SelectObject(hdcMem,hBitmap);
  
  //Create a DC that matches the device
  HDC hdcBmp = CreateCompatibleDC(hdc);
  //Load the bitmap
  HANDLE hBmp= LoadImage(m_hInst,MAKEINTRESOURCE(IDB_MAINWND),IMAGE_BITMAP,0,0,0);
  //Select the bitmap into to the compatible device context
  HGDIOBJ hOldBmpSel = SelectObject(hdcBmp,hBmp);
  //Copy the bitmap image to the memory DC
  BitBlt(hdcMem,0,0,IMG_MAINWND_WIDTH,IMG_MAINWND_HEIGHT,hdcBmp,0,0,SRCCOPY);
 
  COLORREF oldColor;
  SetBkMode(hdcMem,TRANSPARENT);
  oldColor = SetTextColor(hdcMem,RGB(40,96,170));
  DrawText(hdcMem,lpcszText,-1,&m_rcInfoArea,DT_LEFT);
  SetTextColor(hdcMem,oldColor);
  
  BitBlt(hdc,m_rcInfoArea.left,m_rcInfoArea.top,(m_rcInfoArea.right - m_rcInfoArea.left),(m_rcInfoArea.bottom - m_rcInfoArea.top),hdcMem,m_rcInfoArea.left,m_rcInfoArea.top,SRCCOPY);
  //Restore original bitmap selection and destroy the memory DC
  SelectObject(hdcBmp,hOldBmpSel);
  SelectObject(hdcMem,hOldSel);
  DeleteObject(hBitmap);
  DeleteDC(hdcMem);
  ReleaseDC(m_hWnd,hdc);
  
  
  附录2
  会闪烁的代码
   InvalidateRect(m_hWnd,&m_rcInfoArea,TRUE);
   
   HDC hdc = GetDC(m_hWnd);
   //Create a DC that matches the device
   HDC hdcBmp = CreateCompatibleDC(hdc);
   //Load the bitmap
   HANDLE hBmp= LoadImage(m_hInst,MAKEINTRESOURCE(IDB_MAINWND),IMAGE_BITMAP,0,0,0);
   //Select the bitmap into to the compatible device context
   HGDIOBJ hOldSel = SelectObject(hdcBmp,hBmp);
   //Get the bitmap dimensions from the bitmap
   BITMAP bmp;
   GetObject(hBmp,sizeof(BITMAP),&bmp);
   //Copy the bitmap image from the memory DC to the screen DC
   BitBlt(hdc,m_rcInfoArea.left,m_rcInfoArea.top,(m_rcInfoArea.right

 

void CHIT_MOUSE::TransparentBitmap(HDC hdc, HBITMAP hBitmap, short xStart, short yStart, short xadd, short yadd, COLORREF cTransparentColor)
{
BITMAP m_bm;
COLORREF cColor;

  • m_rcInfoArea.left),(m_rcInfoArea.bottom - m_rcInfoArea.top),hdcBmp,m_rcInfoArea.left,m_rcInfoArea.top,SRCCOPY);
       //Restore original bitmap selection and destroy the memory DC
       SelectObject(hdcBmp,hOldSel); 
      
       COLORREF oldColor;
       SetBkMode(hdc,TRANSPARENT);
       oldColor = SetTextColor(hdc,RGB(40,96,170));
       DrawText(hdc,lpcszText,-1,&m_rcInfoArea,DT_LEFT);
       SetTextColor(hdc,oldColor);
       
       DeleteDC(hdcBmp);
       ReleaseDC(m_hWnd,hdc);

      我们在进行程序的界面设计时,常常希望将位图的关键部分,也既是图像的前景显示在界面上,而将位图的背景隐藏起来,将位图与界面很自然的融合在一起,本文介绍了透明位图的制作知识,并将透明位图在一个对话框中显示了出来。 

// 创建临时DC
HDC hMem, hBack, hObject, hTemp, hSave;
hBack = CreateCompatibleDC;
hObject = CreateCompatibleDC;
hMem = CreateCompatibleDC;
hSave = CreateCompatibleDC;

 

hTemp = CreateCompatibleDC;

 

// 选入位图
SelectObject(hTemp, hBitmap);

一、实现方法

  绘制"透明"位图是指绘制某一位图中除指定颜色外的其余部分,我们称这种颜色为"透明色"。通过将位图的背景色指定为"透明色",在绘制时,不绘制这部分背景,而仅绘制图像,这样就可以将位图中图像透明地绘制到窗口上。 

  绘制"透明"位图的关键是创建一个"掩码"位图(mask bitmap),"掩码"位图是一个单色位图,它是位图中图像的一个单色剪影。在Windows编程中,绘图都要用到设备描述表,我们需创建两个内存设备描述表:位图设备描述表(image DC)和"掩码"位图设备描述表(mask DC)。位图设备描述表用来装入位图,而"掩码"位图设备描述表用来装入"掩码"位图。在"掩码"位图设备描述表中制作"掩码"位图的方式是:先创建一个单色的Bitmap,装入mask DC,然后,以"SRCCOPY"的方式将装有位图的位图设备描述表绘制(BitBlt)到mask DC上。这样,mask DC的显示平面中的位图即是"掩码"位图。 

  一般情况下,绘制"透明"位图的实际操作步骤如下:

1、设置待显示位图的背景颜色,也就是设置我们希望透明显示的位图颜色;

2、位图设备描述表以"SRCINVERT"的方式绘制(BitBlt)到显示设备描述表上;

3、"掩码"位图设备描述表以"SRCAND"的方式绘制(BitBlt)到显示设备描述表上;

4、再将位图设备描述表以"SRCINVERT"的方式绘制(BitBlt)到显示设备描述表上。这样除"透明色"外的其余位图部分(图像部分)就被绘制到窗口上了。

  上述操作中需要用到的位图显示函数BitBlt()的原型和说明如下:

BOOL BitBlt( int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, 
int ySrc, DWORD dwRop );

  其中,参数int x表示贴到目的地的左上角X坐标;int y表示/贴到目的地的左上角Y坐标;int nWidth表示贴到目的地的区域宽度;int nHeight表示贴到目的地的区域高度;CDC* pSrcDC表示存储源位图的设备描述表;int xSrc表示源位图的左上角X坐标;int ySrc表示源位图的左上角Y坐标;DWORD dwRop为柵格运算标志(ROP),它明确定义了如何将源文件、目标文件和模式(由现在选出的刷子画笔定义)的位组合去形成一个目标文件。对于所有的设备类型,光栅操作(ROP)只简单地在表示位图颜色的每一个bit位上展开相关操作而不考虑他们的实际意义。微软为位图的光栅操作提供了多种方法,开发人员可以使用不同的组合得到想要的特殊效果。由于篇幅的限制,本文只讨论四种常用的光栅操作:

 

 

操作方式 

运算方式 

效果 

SRCCOPY  

src 

直接将源位图拷贝到目的设备上。 

SRCAND

src AND dest

将目标文件中对应于源文件黑色区域的部分变黑,将对应于白色区域的部分留着不动。

SRCINVERT

src XOR dest

将源插入到目标。二次使用时,将目标恢复到它原来的状态。在某种条件下可以代替SRCPAINT 操作。

SRCPAINT

src OR dest

将源文件中的白色区域刷到目标文件中。源中的黑色区域不转换到目标中。

 

  这里补充说明一点,显示位图的背景颜色可以通过PhotoShop等图像处理软件获取,当然,也可以通过读取位图上特殊位置上的像素点的颜色来获取,前者实现起来比较方便,后者稍微麻烦一些,这可以根据个人爱好自由选择。

 


GetObject(hBitmap, sizeof, &m_bm);

二、Delphi下的实现

procedure DrawTransBitmap(hdcDest: HDC;      // 目标DC
                    nXOriginDest,            // 目标X偏移
                    nYOriginDest,            // 目标Y偏移
                    nWidthDest,              // 目标宽度
                    nHeightDest: Integer;    // 目标高度
                    hdcSrc: HDC;             // 源DC
                    nXOriginSrc,             // 源X起点
                    nYOriginSrc: Integer;    // 源Y起点
                    crTransparent: TColor    // 透明色
                    );
var
  hOldImageBMP, hImageBMP, hOldMaskBMP, hMaskBMP: HBITMAP;
  hImageDC, hMaskDC: HDC;
begin
    hImageBMP := CreateCompatibleBitmap(hdcDest, nWidthDest, nHeightDest);    // 创建兼容位图
    hMaskBMP := CreateBitmap(nWidthDest, nHeightDest, 1, 1, NIL);            // 创建单色掩码位图
    hImageDC := CreateCompatibleDC(hdcDest);//临时DC
    hMaskDC := CreateCompatibleDC(hdcDest);//临时掩码DC
    hOldImageBMP := SelectObject(hImageDC, hImageBMP);
    hOldMaskBMP := SelectObject(hMaskDC, hMaskBMP);

    // 将源DC中的位图拷贝到临时DC中,源DC已经载入位图
    BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, SRCCOPY);

    // 设置临时DC的透明色
    SetBkColor(hImageDC, crTransparent);

    // 生成透明区域为白色,其它区域为黑色的临时掩码DC的掩码位图
    // 位图来自临时DC
    BitBlt(hMaskDC, 0, 0, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCCOPY);

    // 生成透明区域为黑色,其它区域保持不变的位图
    SetBkColor(hImageDC, RGB(0,0,0));
    SetTextColor(hImageDC, RGB(255,255,255));
    BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);

    // 透明部分保持屏幕不变,其它部分变成黑色
    SetBkColor(hdcDest,RGB(255,255,255));
    SetTextColor(hdcDest,RGB(0,0,0));
    BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);

    // "或"运算,生成最终效果
    BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCPAINT);

    // 清理、恢复
    SelectObject(hImageDC, hOldImageBMP);
    DeleteDC(hImageDC);
    SelectObject(hMaskDC, hOldMaskBMP);
    DeleteDC(hMaskDC);
    DeleteObject(hImageBMP);
    DeleteObject(hMaskBMP);
end;


看一下Delphi自己的封装

procedure TForm1.btn1Click(Sender: TObject);

var

  Bitmap : TBitMap;
begin
  Bitmap := TBitmap.Create;
  Bitmap.Width := 200;
  Bitmap.Height := 180;
  try
    with Bitmap do begin
      Bitmap.Canvas.Rectangle(0, 0,   Bitmap.Width, Bitmap.Height);
      Transparent := True;
      TransParentColor := clwhite;
      Form1.Canvas.Draw(0,0,BitMap);
    end;
  finally
    Bitmap.Free;

  end;


POINT ptSize;//显示位图宽高

三、VC下的实现

在开发界面及棋牌游戏过程中,需要很多镂空的图片,而且图片形式一般比较固定.
所以封装了几种常见的镂空方法.

  1. 用于没有掩码图,只有指定透明色,不进行伸缩
    void DrawTransBitmap( HDC hdcDest,             // 目标DC
                          int nXOriginDest,        // 目标X偏移
                          int nYOriginDest,        // 目标Y偏移
                          int nWidthDest,          // 目标宽度
                          int nHeightDest,         // 目标高度
                          HDC hdcSrc,              // 源DC
                          int nXOriginSrc,         // 源X起点
                          int nYOriginSrc,         // 源Y起点
                          COLORREF crTransparent   // 透明色,COLORREF类型
                        );
  1. 用于没有掩码图,只有指定透明色,可以进行伸缩
     void DrawTransBitmap( HDC hdcDest,       // 目标DC
                                                 int nXOriginDest,   // 目标X偏移
                                                 int nYOriginDest,   // 目标Y偏移
                                                 int nWidthDest,      // 目标宽度
                                                 int nHeightDest,    // 目标高度
                                                 HDC hdcSrc,          // 源DC
                                                 int nXOriginSrc,     // 源X起点
                                                 int nYOriginSrc,     // 源Y起点
                                                 int nWidthSrc,        // 源宽度
                                                 int nHeightSrc,      // 源高度
                                                 COLORREF crTransparent  // 透明色,COLORREF类型
          );

3.指定掩码图,和掩码图属于不同图片
 void DrawTransBitmap( HDC hdcDest,        // 目标DC
                                             int nXOriginDest,    // 目标X偏移
                                             int nYOriginDest,    // 目标Y偏移
                                             int nWidthDest,       // 目标宽度
                                             int nHeightDest,     // 目标高度
                                             HDC hdcSrc,          // 源DC
                                             HDC hdcMask,       //掩码DC
                                             int nXOriginSrc,     // 源X起点
                                             int nYOriginSrc,     // 源Y起点
                                            COLORREF crTransparent  // 透明色,COLORREF类型
                                          );

4.指定图片和掩码图同属于一张图片
void DrawTransBitmap(HDC hDC, 
                                           int nPosX, 
                                           int nPosY,
                                           int nCX, 
                                           int nCY, 
                                           HBITMAP hObj
                                           );

5.得到位图HRGN
   HRGN CreateBitmapRgn(int nWidth,int nHeight,HBITMAP hbmp,COLORREF cTrans);

以下是完整代码
//用于没有掩码图,只有指定透明色,不进行伸缩
//方法一:
void DrawTransBitmap( HDC hdcDest,      // 目标DC
                    int nXOriginDest,   // 目标X偏移
                    int nYOriginDest,   // 目标Y偏移
                    int nWidthDest,     // 目标宽度
                    int nHeightDest,    // 目标高度
                    HDC hdcSrc,         // 源DC
                    int nXOriginSrc,    // 源X起点
                    int nYOriginSrc,    // 源Y起点
                    COLORREF crTransparent  // 透明色,COLORREF类型
                    )
{
    HBITMAP hOldImageBMP, hImageBMP = CreateCompatibleBitmap(hdcDest, nWidthDest, nHeightDest);    // 创建兼容位图
    HBITMAP hOldMaskBMP, hMaskBMP = CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL);            // 创建单色掩码位图
    HDC        hImageDC = CreateCompatibleDC(hdcDest);//临时DC 
    HDC        hMaskDC = CreateCompatibleDC(hdcDest);//临时掩码DC 
    hOldImageBMP = (HBITMAP)SelectObject(hImageDC, hImageBMP);
    hOldMaskBMP = (HBITMAP)SelectObject(hMaskDC, hMaskBMP);

    // 将源DC中的位图拷贝到临时DC中,源DC已经载入位图
     BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, SRCCOPY);
 
    // 设置临时DC的透明色
    SetBkColor(hImageDC, crTransparent);

    // 生成透明区域为白色,其它区域为黑色的临时掩码DC的掩码位图
    // 位图来自临时DC
    BitBlt(hMaskDC, 0, 0, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCCOPY);

    // 生成透明区域为黑色,其它区域保持不变的位图
    SetBkColor(hImageDC, RGB(0,0,0));
    SetTextColor(hImageDC, RGB(255,255,255));
    BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);

    // 透明部分保持屏幕不变,其它部分变成黑色
    SetBkColor(hdcDest,RGB(255,255,255));
    SetTextColor(hdcDest,RGB(0,0,0));
     BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);

    // "或"运算,生成最终效果
    BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCPAINT);

    // 清理、恢复    
    SelectObject(hImageDC, hOldImageBMP);
    DeleteDC(hImageDC);
    SelectObject(hMaskDC, hOldMaskBMP);
    DeleteDC(hMaskDC);
    DeleteObject(hImageBMP);
    DeleteObject(hMaskBMP);
}

//用于没有掩码图,只有指定透明色,不进行伸缩
//方法二:
void DrawTransBitmap( HDC hdcDest,      // 目标DC
                    int nXOriginDest,   // 目标X偏移
                    int nYOriginDest,   // 目标Y偏移
                    int nWidthDest,     // 目标宽度
                    int nHeightDest,    // 目标高度
                    HDC hdcSrc,         // 源DC
                    int nXOriginSrc,    // 源X起点
                    int nYOriginSrc,    // 源Y起点
                    COLORREF crTransparent  // 透明色,COLORREF类型
                    )
{
    HBITMAP hOldImageBMP, hImageBMP = CreateCompatibleBitmap(hdcDest, nWidthDest, nHeightDest);    // 创建兼容位图
    HBITMAP hOldMaskBMP, hMaskBMP = CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL);            // 创建单色掩码位图
    HDC        hImageDC = CreateCompatibleDC(hdcDest);//临时DC 
    HDC        hMaskDC = CreateCompatibleDC(hdcDest);//临时掩码DC 
    hOldImageBMP = (HBITMAP)SelectObject(hImageDC, hImageBMP);
    hOldMaskBMP = (HBITMAP)SelectObject(hMaskDC, hMaskBMP);

    // 将源DC中的位图拷贝到临时DC中,源DC已经载入位图
     BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, SRCCOPY);
 
    // 设置临时DC的透明色
    SetBkColor(hImageDC, crTransparent);

    // 生成透明区域为白色,其它区域为黑色的临时掩码DC的掩码位图
    // 位图来自临时DC
    BitBlt(hMaskDC, 0, 0, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCCOPY);

            
    BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCINVERT);
         
    BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);

    BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCINVERT);
    // 清理、恢复    
    SelectObject(hImageDC, hOldImageBMP);
    DeleteDC(hImageDC);
    SelectObject(hMaskDC, hOldMaskBMP);
    DeleteDC(hMaskDC);
    DeleteObject(hImageBMP);
    DeleteObject(hMaskBMP);
}

//用于没有掩码图,只有指定透明色,可以进行伸缩
//方法一:
void DrawTransBitmap( HDC hdcDest,      // 目标DC
                     int nXOriginDest,   // 目标X偏移
                     int nYOriginDest,   // 目标Y偏移
                     int nWidthDest,     // 目标宽度
                     int nHeightDest,    // 目标高度
                     HDC hdcSrc,         // 源DC
                     int nXOriginSrc,    // 源X起点
                     int nYOriginSrc,    // 源Y起点
                     int nWidthSrc,      // 源宽度
                     int nHeightSrc,     // 源高度
                     COLORREF crTransparent  // 透明色,COLORREF类型
                     )
{
    HBITMAP hOldImageBMP, hImageBMP = CreateCompatibleBitmap(hdcDest, nWidthDest, nHeightDest);    // 创建兼容位图
    HBITMAP hOldMaskBMP, hMaskBMP = CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL);            // 创建单色掩码位图
    HDC        hImageDC = CreateCompatibleDC(hdcDest);
    HDC        hMaskDC = CreateCompatibleDC(hdcDest);
    hOldImageBMP = (HBITMAP)SelectObject(hImageDC, hImageBMP);
    hOldMaskBMP = (HBITMAP)SelectObject(hMaskDC, hMaskBMP);
    
    // 将源DC中的位图拷贝到临时DC中
    if (nWidthDest == nWidthSrc && nHeightDest == nHeightSrc)
    {
        BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, SRCCOPY);
    }
    else
    {
        StretchBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, 
        hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, SRCCOPY);
    }
    
    // 设置透明色
    SetBkColor(hImageDC, crTransparent);

    // 生成透明区域为白色,其它区域为黑色的掩码位图
    BitBlt(hMaskDC, 0, 0, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCCOPY);
    
    // 生成透明区域为黑色,其它区域保持不变的位图
    SetBkColor(hImageDC, RGB(0,0,0));
    SetTextColor(hImageDC, RGB(255,255,255));
    BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);

    // 透明部分保持屏幕不变,其它部分变成黑色
    SetBkColor(hdcDest,RGB(0xff,0xff,0xff));
    SetTextColor(hdcDest,RGB(0,0,0));
    BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);
    
    // "或"运算,生成最终效果
    BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCPAINT);
    
    SelectObject(hImageDC, hOldImageBMP);
    DeleteDC(hImageDC);
    SelectObject(hMaskDC, hOldMaskBMP);
    DeleteDC(hMaskDC);
    DeleteObject(hImageBMP);
    DeleteObject(hMaskBMP);
    
}

//用于没有掩码图,只有指定透明色,可以进行伸缩
  //方法二:
void DrawTransBitmap( HDC hdcDest,      // 目标DC
                     int nXOriginDest,   // 目标X偏移
                     int nYOriginDest,   // 目标Y偏移
                     int nWidthDest,     // 目标宽度
                     int nHeightDest,    // 目标高度
                     HDC hdcSrc,         // 源DC
                     int nXOriginSrc,    // 源X起点
                     int nYOriginSrc,    // 源Y起点
                     int nWidthSrc,      // 源宽度
                     int nHeightSrc,     // 源高度
                     COLORREF crTransparent  // 透明色,COLORREF类型
                     )
{
  
      if (nWidthDest < 1) return false;
      if (nWidthSrc < 1) return false;
      if (nHeightDest < 1) return false;
      if (nHeightSrc < 1) return false;
      HDC dc = CreateCompatibleDC(NULL);
      HBITMAP bitmap = CreateBitmap(nWidthSrc, nHeightSrc, 1, GetDeviceCaps(dc,
      BITSPIXEL), NULL);
      if (bitmap == NULL)
       {
                DeleteDC(dc);    
                return false;
        }
     
    HBITMAP oldBitmap = (HBITMAP)SelectObject(dc, bitmap);
    if (!BitBlt(dc, 0, 0, nWidthSrc, nHeightSrc, dcSrc, nXOriginSrc,
                     nYOriginSrc, SRCCOPY))
    {
               SelectObject(dc, oldBitmap); 
               DeleteObject(bitmap);        
         DeleteDC(dc);                
         return false;
    }
       
    HDC maskDC = CreateCompatibleDC(NULL);
     HBITMAP maskBitmap = CreateBitmap(nWidthSrc, nHeightSrc, 1, 1, NULL);
 if (maskBitmap == NULL)
      {
          SelectObject(dc, oldBitmap); 
           DeleteObject(bitmap);        
           DeleteDC(dc);                
           DeleteDC(maskDC);            
           return false;
       }
       HBITMAP oldMask =  (HBITMAP)SelectObject(maskDC, maskBitmap);
       SetBkColor(maskDC, RGB(0,0,0));
       SetTextColor(maskDC, RGB(255,255,255));
  if (!BitBlt(maskDC, 0,0,nWidthSrc,nHeightSrc,NULL,0,0,BLACKNESS))
       {
              SelectObject(maskDC, oldMask); 
              DeleteObject(maskBitmap);      
              DeleteDC(maskDC);              
              SelectObject(dc, oldBitmap);   
              DeleteObject(bitmap);          
              DeleteDC(dc);                  
              return false;
       }
       SetBkColor(dc, crTransparent);
       BitBlt(maskDC, 0,0,nWidthSrc,nHeightSrc,dc,0,0,SRCINVERT);
      SetBkColor(dc, RGB(0,0,0));
       SetTextColor(dc, RGB(255,255,255));
       BitBlt(dc, 0,0,nWidthSrc,nHeightSrc,maskDC,0,0,SRCAND);
       HDC newMaskDC = CreateCompatibleDC(NULL);
       HBITMAP newMask;
       newMask = CreateBitmap(nWidthDest, nHeightDest, 1,
                                                  GetDeviceCaps(newMaskDC, BITSPIXEL), NULL);
  if (newMask == NULL)
       {
              SelectObject(dc, oldBitmap);
              DeleteDC(dc);
              SelectObject(maskDC, oldMask);
              DeleteDC(maskDC);
              DeleteDC(newMaskDC);
              DeleteObject(bitmap);     
              DeleteObject(maskBitmap); 
              return false;
       }
       SetStretchBltMode(newMaskDC, COLORONCOLOR);
       HBITMAP oldNewMask = (HBITMAP) SelectObject(newMaskDC, newMask);
       StretchBlt(newMaskDC, 0, 0, nWidthDest, nHeightDest, maskDC, 0, 0,
                    nWidthSrc, nHeightSrc, SRCCOPY);
       SelectObject(maskDC, oldMask);
       DeleteDC(maskDC);
       DeleteObject(maskBitmap); 
       HDC newImageDC = CreateCompatibleDC(NULL);
       HBITMAP newImage = CreateBitmap(nWidthDest, nHeightDest, 1,
        GetDeviceCaps(newMaskDC, BITSPIXEL), NULL);
  if (newImage == NULL)
       {
              SelectObject(dc, oldBitmap);
              DeleteDC(dc);
              DeleteDC(newMaskDC);
              DeleteObject(bitmap);     
              return false;
       }
       HBITMAP oldNewImage = (HBITMAP)SelectObject(newImageDC, newImage);
       StretchBlt(newImageDC, 0, 0, nWidthDest, nHeightDest, dc, 0, 0, nWidthSrc,
              nHeightSrc, SRCCOPY);
       SelectObject(dc, oldBitmap);
       DeleteDC(dc);
       DeleteObject(bitmap);     
       BitBlt( dcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
                          newMaskDC, 0, 0, SRCAND);
       BitBlt( dcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
                       newImageDC, 0, 0, SRCPAINT);
       SelectObject(newImageDC, oldNewImage);
       DeleteDC(newImageDC);
       SelectObject(newMaskDC, oldNewMask);
       DeleteDC(newMaskDC);
       DeleteObject(newImage);   
       DeleteObject(newMask);    
       return true;
}

指定掩码图,和掩码图属于不同图片
void DrawTransBitmap( HDC hdcDest,      // 目标DC
                    int nXOriginDest,   // 目标X偏移
                    int nYOriginDest,   // 目标Y偏移
                    int nWidthDest,     // 目标宽度
                    int nHeightDest,    // 目标高度
                    HDC hdcSrc,         // 源DC
                    HDC hdcMask,
                    int nXOriginSrc,    // 源X起点
                    int nYOriginSrc,    // 源Y起点
                    COLORREF crTransparent  // 透明色,COLORREF类型
                    )
{

    HBITMAP hOldImageBMP, hImageBMP = CreateCompatibleBitmap(hdcDest, nWidthDest, nHeightDest);    // 创建兼容位图
     HDC        hImageDC = CreateCompatibleDC(hdcDest);//临时DC 
     hOldImageBMP = (HBITMAP)SelectObject(hImageDC, hImageBMP);
 
    // 将源DC中的位图拷贝到临时DC中,源DC已经载入位图
     BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, SRCCOPY);
     // 设置临时DC的透明色
    SetBkColor(hImageDC, crTransparent);
    // 生成透明区域为黑色,其它区域保持不变的位图
    SetBkColor(hImageDC, RGB(0,0,0));
    SetTextColor(hImageDC, RGB(255,255,255));
    BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hdcMask, 0, 0, SRCAND);
    // 透明部分保持屏幕不变,其它部分变成黑色
    SetBkColor(hdcDest,RGB(255,255,255));
    SetTextColor(hdcDest,RGB(0,0,0));
     BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hdcMask, 0, 0, SRCAND);
     // "或"运算,生成最终效果
    BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCPAINT);
    // 清理、恢复    
    SelectObject(hImageDC, hOldImageBMP);
    DeleteDC(hImageDC);
    DeleteObject(hImageBMP);
}

指定图片和掩码图同属于一张图片
void DrawTransBitmap(HDC hDC, int nPosX, int nPosY, int nCX, int nCY, HBITMAP hObj)
{
    HDC hMemDC= CreateCompatibleDC(hDC);
    HBITMAP hOldBMP=(HBITMAP)::SelectObject(hMemDC,hObj);
      BitBlt(hDC,nPosX,nPosY,nCX,nCY,    hMemDC,nCX,0,SRCAND);
    BitBlt(hDC,nPosX,nPosY,nCX,nCY,    hMemDC,0,0,SRCPAINT);
    SelectObject(hMemDC,hOldBMP);
    DeleteDC(hMemDC);

HRGN CreateBitmapRgn(int nWidth,int nHeight,HBITMAP hbmp, COLORREF TransColor)
{
        HDC  hmemDC;
        //创建与传入DC兼容的临时DC
        hmemDC = ::CreateCompatibleDC(NULL);        
        HBITMAP hOldBmp = (HBITMAP)::SelectObject(hmemDC,hbmp);
                
        //创建总的窗体区域,初始region为0
        HRGN hrgn;
        hrgn = ::CreateRectRgn(0,0,0,0);           
        
        int y;
        for(y=0;y<nHeight ;y++)
        {
            HRGN rgnTemp; //保存临时region
            
            int iX = 0;
            do
            {
                //跳过透明色找到下一个非透明色的点.
                while (iX < nWidth  && ::GetPixel(hmemDC,iX, y) == TransColor)
                    iX++;
                
                //记住这个起始点
                int iLeftX = iX;
                
                //寻找下个透明色的点
                while (iX < nWidth  && ::GetPixel(hmemDC,iX, y) != TransColor)
                    ++iX;
                
                //创建一个包含起点与重点间高为1像素的临时“region”
                rgnTemp=::CreateRectRgn(iLeftX, y, iX, y+1);
                
                //合并到主"region".
                CombineRgn( hrgn,hrgn,rgnTemp, RGN_OR);
                
                //删除临时"region",否则下次创建时和出错
                ::DeleteObject(rgnTemp);
            }while(iX <nWidth );
            iX = 0;
        }
        ::SelectObject(hmemDC,hOldBmp);

ptSize.x = m_bm.bmWidth; // 取得位图的宽度

ptSize.y = m_bm.bmHeight; // 取得位图的该度

DPtoLP(hTemp, &ptSize, 1); // 转换为逻辑点值

编辑:儿童文学 本文来源:轻松消除贴图闪烁,画透明位图

关键词:

  • 上一篇:没有了
  • 下一篇:没有了