162 lines
4 KiB
C++
162 lines
4 KiB
C++
|
// transbmp.cpp : implementation of the CTransBmp class
|
||
|
//
|
||
|
// support for transparent CBitmap objects. Used in the CUserList class.
|
||
|
// Based on a class from MSDN 7/95
|
||
|
#include "stdafx.h"
|
||
|
#include "transbmp.h"
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
#undef THIS_FILE
|
||
|
static char BASED_CODE THIS_FILE[] = __FILE__;
|
||
|
#endif
|
||
|
|
||
|
// Colors
|
||
|
#define rgbWhite RGB(255,255,255)
|
||
|
// Raster op codes
|
||
|
#define DSa 0x008800C6L
|
||
|
#define DSx 0x00660046L
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CTransBmp construction/destruction
|
||
|
|
||
|
CTransBmp::CTransBmp()
|
||
|
{
|
||
|
m_iWidth = 0;
|
||
|
m_iHeight = 0;
|
||
|
m_hbmMask = NULL;
|
||
|
}
|
||
|
|
||
|
CTransBmp::~CTransBmp()
|
||
|
{
|
||
|
if (m_hbmMask != NULL) delete m_hbmMask;
|
||
|
}
|
||
|
|
||
|
void CTransBmp::GetMetrics()
|
||
|
{
|
||
|
// Get the width and height
|
||
|
BITMAP bm;
|
||
|
GetObject(sizeof(bm), &bm);
|
||
|
m_iWidth = bm.bmWidth;
|
||
|
m_iHeight = bm.bmHeight;
|
||
|
}
|
||
|
|
||
|
|
||
|
int CTransBmp::GetWidth()
|
||
|
{
|
||
|
if ((m_iWidth == 0) || (m_iHeight == 0)){
|
||
|
GetMetrics();
|
||
|
}
|
||
|
return m_iWidth;
|
||
|
}
|
||
|
|
||
|
int CTransBmp::GetHeight()
|
||
|
{
|
||
|
if ((m_iWidth == 0) || (m_iHeight == 0)){
|
||
|
GetMetrics();
|
||
|
}
|
||
|
return m_iHeight;
|
||
|
}
|
||
|
|
||
|
|
||
|
void CTransBmp::CreateMask(CDC* pDC)
|
||
|
{
|
||
|
m_hbmMask = new CBitmap;
|
||
|
// Nuke any existing mask
|
||
|
if (m_hbmMask) m_hbmMask->DeleteObject();
|
||
|
|
||
|
// Create memory DCs to work with
|
||
|
CDC* hdcMask = new CDC;
|
||
|
CDC* hdcImage = new CDC;
|
||
|
|
||
|
hdcMask->CreateCompatibleDC(pDC);
|
||
|
hdcImage->CreateCompatibleDC(pDC);
|
||
|
|
||
|
// Create a monochrome bitmap for the mask
|
||
|
m_hbmMask->CreateBitmap(GetWidth(),
|
||
|
GetHeight(),
|
||
|
1,
|
||
|
1,
|
||
|
NULL);
|
||
|
// Select the mono bitmap into its DC
|
||
|
CBitmap* hbmOldMask = hdcMask->SelectObject(m_hbmMask);
|
||
|
// Select the image bitmap into its DC
|
||
|
CBitmap* hbmOldImage = hdcImage->SelectObject(CBitmap::FromHandle((HBITMAP)m_hObject));
|
||
|
|
||
|
// Set the transparency color to be the top-left pixel
|
||
|
hdcImage->SetBkColor(hdcImage->GetPixel(0, 0));
|
||
|
// Make the mask
|
||
|
hdcMask->BitBlt(0, 0,
|
||
|
GetWidth(), GetHeight(),
|
||
|
hdcImage,
|
||
|
0, 0,
|
||
|
SRCCOPY);
|
||
|
// clean up
|
||
|
hdcMask->SelectObject(hbmOldMask);
|
||
|
hdcImage->SelectObject(hbmOldImage);
|
||
|
delete hdcMask;
|
||
|
delete hdcImage;
|
||
|
}
|
||
|
|
||
|
// draw the transparent bitmap using the created mask
|
||
|
void CTransBmp::DrawTrans(CDC* pDC, int x, int y)
|
||
|
{
|
||
|
if (m_hbmMask == NULL) CreateMask(pDC);
|
||
|
|
||
|
int dx = GetWidth();
|
||
|
int dy = GetHeight();
|
||
|
|
||
|
// Create a memory DC to do the drawing to
|
||
|
CDC* hdcOffScr = new CDC;
|
||
|
hdcOffScr->CreateCompatibleDC(pDC);
|
||
|
|
||
|
// Create a bitmap for the off-screen DC that is really
|
||
|
// color compatible with the destination DC.
|
||
|
CBitmap hbmOffScr;
|
||
|
hbmOffScr.CreateBitmap(dx, dy,
|
||
|
pDC->GetDeviceCaps(PLANES),
|
||
|
pDC->GetDeviceCaps(BITSPIXEL),
|
||
|
NULL);
|
||
|
|
||
|
// Select the buffer bitmap into the off-screen DC
|
||
|
HBITMAP hbmOldOffScr = (HBITMAP)hdcOffScr->SelectObject(hbmOffScr);
|
||
|
|
||
|
// Copy the image of the destination rectangle to the
|
||
|
// off-screen buffer DC so we can play with it
|
||
|
hdcOffScr->BitBlt(0, 0, dx, dy, pDC, x, y, SRCCOPY);
|
||
|
|
||
|
// Create a memory DC for the source image
|
||
|
CDC* hdcImage = new CDC;
|
||
|
hdcImage->CreateCompatibleDC(pDC);
|
||
|
|
||
|
CBitmap* hbmOldImage = hdcImage->SelectObject(CBitmap::FromHandle((HBITMAP)m_hObject));
|
||
|
|
||
|
// Create a memory DC for the mask
|
||
|
CDC* hdcMask = new CDC;
|
||
|
hdcMask->CreateCompatibleDC(pDC);
|
||
|
|
||
|
CBitmap* hbmOldMask = hdcMask->SelectObject(m_hbmMask);
|
||
|
|
||
|
// XOR the image with the destination
|
||
|
hdcOffScr->SetBkColor(rgbWhite);
|
||
|
hdcOffScr->BitBlt(0, 0, dx, dy ,hdcImage, 0, 0, DSx);
|
||
|
// AND the destination with the mask
|
||
|
hdcOffScr->BitBlt(0, 0, dx, dy, hdcMask, 0,0, DSa);
|
||
|
// XOR the destination with the image again
|
||
|
hdcOffScr->BitBlt(0, 0, dx, dy, hdcImage, 0, 0, DSx);
|
||
|
|
||
|
// Copy the resultant image back to the screen DC
|
||
|
pDC->BitBlt(x, y, dx, dy, hdcOffScr, 0, 0, SRCCOPY);
|
||
|
|
||
|
// Tidy up
|
||
|
hdcOffScr->SelectObject(hbmOldOffScr);
|
||
|
hdcImage->SelectObject(hbmOldImage);
|
||
|
hdcMask->SelectObject(hbmOldMask);
|
||
|
|
||
|
delete hdcOffScr;
|
||
|
delete hdcImage;
|
||
|
delete hdcMask;
|
||
|
}
|
||
|
|
||
|
|