CClientDC dc(this);
                  CDC memDC;
                  CBitmap bmp;
  
CRect rcDlg;
GetClientRect(&rcDlg);
memDC.CreateCompatibleDC(&dc);
                  bmp.CreateCompatibleBitmap(&dc,rcDlg.Width(),rcDlg.Height());
CBitmap * pOldBitmap=memDC.SelectObject(&bmp);
 memDC.MoveTo(CPoint(100,100));
 memDC.LineTo(CPoint(0,50));dc.BitBlt(0,0,rcDlg.Width(),rcDlg.Height(),&memDC,0,0,SRCCOPY);
memDC.SelectObject(pOldBitmap);
如上面的代码,当将bmp复制到窗体上时,bmp的背景色是黑的,如果我要实现透明(就像透明窗体一样)的改怎么办?也就是说当BMP覆盖掉窗体上原来的线条时,不破坏原来的线条。而在BMP上画的线条可以在窗体上存在。

解决方案 »

  1.   

    class CBmpRgn  
    {
    public:
    CBmpRgn();
    virtual ~CBmpRgn();public:
    HRGN GenerateRegion(HBITMAP hBitmap, BYTE red, BYTE green, BYTE blue);
    protected:
    BYTE* Get24BitPixels(HBITMAP pBitmap, WORD *pwWidth, WORD *pwHeight);};
      

  2.   

    CBmpRgn::CBmpRgn()
    {}CBmpRgn::~CBmpRgn()
    {}
    //返回24位位图实际的多边形区域,将透明颜色指定为(red,green,blue),将其删除,以获取实际位图的
    //HRGN,GOOD!!
    HRGN CBmpRgn::GenerateRegion(HBITMAP hBitmap, BYTE red, BYTE green, BYTE blue)
    {
    WORD wBmpWidth,wBmpHeight;
    HRGN hRgn, hTmpRgn; //返回指向位图实际象素的首地址指针,并得到位图的宽度和高度,分别保存在wBmpWidth和wBmpHeight中
    BYTE *pPixels = Get24BitPixels(hBitmap, &wBmpWidth, &wBmpHeight);
    if (!pPixels) 
    return NULL; //根据位图的宽度和高度创建一个矩形
    hRgn = CreateRectRgn(0,0,wBmpWidth,wBmpHeight);
    if (!hRgn)
    {
    delete pPixels; 
    return NULL;
    } DWORD p=0;
    for (WORD y=0; y<wBmpHeight; y++)
    {
    for (WORD x=0; x<wBmpWidth; x++)
    {
    BYTE jRed   = pPixels[p+2];//每个位图象素点为3字节,R,G,B各站一字节(8位)
    BYTE jGreen = pPixels[p+1];
    BYTE jBlue  = pPixels[p+0]; if (jRed==red && jGreen==green && jBlue==blue)
    {
    //从区域中删除透明的颜色(red,green,blue), 
    hTmpRgn = CreateRectRgn(x,y,x+1,y+1);
    CombineRgn(hRgn, hRgn, hTmpRgn, RGN_XOR);//从hRgn中删除hTmpRgn
    DeleteObject(hTmpRgn);
    } //下一个象素
    p+=3;
    }
    }
    delete pPixels;
    return hRgn;
    }//函数返回一个指向将hBitmap象素拷贝到一段内存的首地址的指针
    BYTE* CBmpRgn::Get24BitPixels(HBITMAP hBitmap, WORD *pwWidth, WORD *pwHeight)
    {
    BITMAP bmpBmp;
    LPBITMAPINFO pbmiInfo;
    BITMAPINFO bmiInfo;
    WORD wBmpWidth, wBmpHeight; GetObject(hBitmap, sizeof(bmpBmp),&bmpBmp);
    pbmiInfo   = (LPBITMAPINFO)&bmpBmp; wBmpWidth  = (WORD)pbmiInfo->bmiHeader.biWidth;//得到位图的实际宽度
    wBmpWidth -= (wBmpWidth%4);//得到位图在内存中的宽度(必须是4的倍数)
    wBmpHeight = (WORD)pbmiInfo->bmiHeader.biHeight;//得到位图的高度 *pwWidth  = wBmpWidth;//将内存中位图的宽度和高度返回给调用者
    *pwHeight = wBmpHeight;

    BYTE *pPixels = new BYTE[wBmpWidth*wBmpHeight*3];//分配存储位图实际象素值的内存区,每象素占3字节
    if (!pPixels) //内存分配失败、或空位图
    return NULL; HDC hDC =::GetWindowDC(NULL);//得到窗口设备句柄,包括菜单、状态条、工具栏、滚动条,可在上面作图 //填充位图信息头
    bmiInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmiInfo.bmiHeader.biWidth = wBmpWidth;
    bmiInfo.bmiHeader.biHeight = -wBmpHeight;
    bmiInfo.bmiHeader.biPlanes = 1;
    bmiInfo.bmiHeader.biBitCount = 24;
    bmiInfo.bmiHeader.biCompression = BI_RGB;
    bmiInfo.bmiHeader.biSizeImage = wBmpWidth*wBmpHeight*3;
    bmiInfo.bmiHeader.biXPelsPerMeter = 0;
    bmiInfo.bmiHeader.biYPelsPerMeter = 0;
    bmiInfo.bmiHeader.biClrUsed = 0;
    bmiInfo.bmiHeader.biClrImportant = 0; // 将位图象素拷贝到以pPixels指向的内存存储区
    int iRes = GetDIBits(hDC,hBitmap,0,wBmpHeight,(LPVOID)pPixels,&bmiInfo,DIB_RGB_COLORS); ::ReleaseDC(NULL,hDC); if (!iRes)
    {
    delete pPixels;
    return NULL;
    }; return pPixels;
    }
      

  3.   

    思路:
    先将目的DC的内容拷贝到你的内存DC中,然后在里面进行操作,最后再将内存DC拷贝回原来显示DC的位置即可。我这里有一段显示透明GIF图片的代码,你自己看看:
    //显示图象,其中:iDLeft,iDTop,iDWidth,iDHeight表示目标区域,
    //                iSLeft,iSTop,iSWidth,iSHeight表示源区域,
    //                =-1表示用图象的原来尺寸.
    BOOL CGif89a::Show(HDC hDC,int iDLeft,int iDTop,int iDWidth,int iDHeight,
              int iSLeft,int iSTop,int iSWidth,int iSHeight)
    {
    if( m_hBitmap == NULL ) return FALSE; HDC hMemDC,hMemDC1;
    HBITMAP hOldBitmap,hOldBitmap1;//,hBitmap;
    int iWidthD,iHeightD;
    int iWidthS,iHeightS; m_hDC = hDC;
    iWidthD  = iDWidth  == -1 ? m_iGifWidth  : iDWidth;
    iHeightD = iDHeight == -1 ? m_iGifHeight : iDHeight; iWidthS  = iSWidth  == -1 ? m_iGifWidth  : iSWidth;
    iHeightS = iSHeight == -1 ? m_iGifHeight : iSHeight; iWidthS  = iWidthS  > iWidthD  ? iWidthD  : iWidthS;
    iHeightS = iHeightS > iHeightD ? iHeightD : iHeightS; hMemDC=CreateCompatibleDC(m_hDC);
    hOldBitmap=(HBITMAP)SelectObject(hMemDC,m_hBitmap); if(m_bTransparent)  //透明显示,着重看这里
    {
    HBITMAP    bmAndBack, bmAndObject,hPicBitmap;
    HBITMAP    bmBackOld, bmObjectOld,hPicBmOld;
    HDC        hdcBack, hdcObject,hPicDC;
    COLORREF   cColor; if( m_hRedrawBitmap != NULL )
    {
    DeleteObject( m_hRedrawBitmap );
    m_hRedrawBitmap = NULL;
    } m_hRedrawBitmap = CreateCompatibleBitmap(m_hDC,iWidthS,iHeightS); hMemDC1=CreateCompatibleDC(m_hDC);
    hOldBitmap1=(HBITMAP)SelectObject(hMemDC1,m_hRedrawBitmap);
    BitBlt(hMemDC1,0,0,iWidthS,iHeightS,m_hDC,m_iLeftD+iDLeft,m_iTopD+iDTop,SRCCOPY);

    hPicDC      = CreateCompatibleDC(m_hDC);
    hdcBack     = CreateCompatibleDC(m_hDC);
    hdcObject   = CreateCompatibleDC(m_hDC);
    bmAndBack   = CreateBitmap(iWidthS,iHeightS,1,1,NULL);
    bmAndObject = CreateBitmap(iWidthS,iHeightS,1,1,NULL);
    hPicBitmap  = CreateCompatibleBitmap(m_hDC,m_iGifWidth,m_iGifHeight);
    bmBackOld   = (HBITMAP)SelectObject(hdcBack,bmAndBack);
    bmObjectOld = (HBITMAP)SelectObject(hdcObject,bmAndObject);
    hPicBmOld   = (HBITMAP)SelectObject(hPicDC,hPicBitmap); BitBlt(hPicDC,0,0,m_iGifWidth,m_iGifHeight,hMemDC,0,0,SRCCOPY);
    cColor=SetBkColor(hPicDC,m_TransparentColor); BitBlt(hdcObject,0,0,iWidthS,iHeightS,hPicDC,iSLeft,iSTop,SRCCOPY); SetBkColor(hPicDC,cColor);
    BitBlt(hdcBack,0,0,iWidthS,iHeightS,hdcObject,0,0,NOTSRCCOPY);
    BitBlt(hMemDC1,0,0,iWidthS,iHeightS,hdcObject,0,0,SRCAND);
    BitBlt(hPicDC,iSLeft,iSTop,iWidthS,iHeightS,hdcBack,0,0,SRCAND);
    BitBlt(hMemDC1,0,0,iWidthS,iHeightS,hPicDC,iSLeft,iSTop,SRCPAINT);
    DeleteObject(SelectObject(hPicDC,hPicBmOld));
    DeleteObject(SelectObject(hdcBack,bmBackOld));
    DeleteObject(SelectObject(hdcObject,bmObjectOld));
    DeleteDC(hPicDC);
    DeleteDC(hdcBack);
    DeleteDC(hdcObject); BitBlt(m_hDC,m_iLeftD+iDLeft,m_iTopD+iDTop,iWidthD,iHeightD,hMemDC1,0,0,SRCCOPY);
    SelectObject(hMemDC1,hOldBitmap1);
    DeleteDC(hMemDC1); if( m_hRedrawBitmap != NULL ) 
    {
    DeleteObject( m_hRedrawBitmap );
    m_hRedrawBitmap = NULL;
    }
    }
    else
    {
    BitBlt(m_hDC,m_iLeftD+iDLeft,m_iTopD+iDTop,iWidthD,iHeightD,hMemDC,iSLeft,iSTop,SRCCOPY);
    }
    SelectObject(hMemDC,hOldBitmap);
    DeleteDC(hMemDC);
    return TRUE;
    }