windows-nt/Source/XPSP1/NT/multimedia/directx/dinput/diconfig/cbitmap.cpp
2020-09-26 16:20:57 +08:00

748 lines
18 KiB
C++

//-----------------------------------------------------------------------------
// File: Cbitmap.cpp
//
// Desc: CBitmap class is an object that wraps around a Windows bitmap.
//
// Copyright (C) 1999-2000 Microsoft Corporation. All Rights Reserved.
//-----------------------------------------------------------------------------
#include "common.hpp"
#include "id3dsurf.h"
//@@BEGIN_MSINTERNAL
#ifdef DDKBUILD
//HMODULE g_MSImg32 = NULL;
//ALPHABLEND g_AlphaBlend = NULL;
#endif
//@@END_MSINTERNAL
BOOL DI_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
)
{
LPBYTE pbDestBits = NULL;
HBITMAP hTempDestDib = NULL;
int nXOriginDestLogical = nXOriginDest, nYOriginDestLogical = nYOriginDest;
// Convert nXOriginDest and nYOriginDest from logical coord to device coord
POINT pt = {nXOriginDest, nYOriginDest};
LPtoDP(hdcDest, &pt, 1);
nXOriginDest = pt.x;
nYOriginDest = pt.y;
// Convert nXOriginSrc and nYOriginSrc from logical coord to device coord
pt.x = nXOriginSrc;
pt.y = nYOriginSrc;
LPtoDP(hdcSrc, &pt, 1);
nXOriginSrc = pt.x;
nYOriginSrc = pt.y;
// Get the bits for both source and destination first
// Every BITMAP used in the UI is created with CreateDIBSection, so we know we can get the bits.
HBITMAP hSrcBmp, hDestBmp;
DIBSECTION SrcDibSec, DestDibSec;
hSrcBmp = (HBITMAP)GetCurrentObject(hdcSrc, OBJ_BITMAP);
GetObject(hSrcBmp, sizeof(DIBSECTION), &SrcDibSec);
hDestBmp = (HBITMAP)GetCurrentObject(hdcDest, OBJ_BITMAP);
GetObject(hDestBmp, sizeof(DIBSECTION), &DestDibSec);
if (!SrcDibSec.dsBm.bmBits) return FALSE; // Not necessary, but to be absolutely safe.
// Calculate the rectangle to perform the operation.
if (nXOriginSrc + nWidthSrc > SrcDibSec.dsBm.bmWidth) nWidthSrc = SrcDibSec.dsBm.bmWidth - nXOriginSrc;
if (nYOriginSrc + nHeightSrc > SrcDibSec.dsBm.bmHeight) nHeightSrc = SrcDibSec.dsBm.bmHeight - nYOriginSrc;
if (nXOriginDest + nWidthDest > DestDibSec.dsBm.bmWidth) nWidthDest = DestDibSec.dsBm.bmWidth - nXOriginDest;
if (nYOriginDest + nHeightDest > DestDibSec.dsBm.bmHeight) nHeightDest = DestDibSec.dsBm.bmHeight - nYOriginDest;
if (nWidthDest > nWidthSrc) nWidthDest = nWidthSrc;
if (nHeightDest > nHeightSrc) nHeightDest = nHeightSrc;
if (nWidthSrc > nWidthDest) nWidthSrc = nWidthDest;
if (nHeightSrc > nHeightDest) nHeightSrc = nHeightDest;
BITMAPINFO bmi;
ZeroMemory(&bmi.bmiHeader, sizeof(BITMAPINFOHEADER));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = nWidthDest;
bmi.bmiHeader.biHeight = nHeightDest;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
// Bitmap will have the same width as the dest, but only lines covered in the subrect.
hTempDestDib = CreateDIBSection(hdcDest, &bmi, DIB_RGB_COLORS, (LPVOID*)&pbDestBits, NULL, NULL);
if (!hTempDestDib)
return FALSE;
HDC hTempDC = CreateCompatibleDC(hdcDest);
if (!hTempDC)
{
DeleteObject(hTempDestDib);
return FALSE;
}
HBITMAP hOldTempBmp = (HBITMAP)SelectObject(hTempDC, hTempDestDib);
BOOL res = BitBlt(hTempDC, 0, 0, nWidthDest, nHeightDest, hdcDest, nXOriginDestLogical, nYOriginDestLogical, SRCCOPY);
SelectObject(hTempDC, hOldTempBmp);
DeleteDC(hTempDC);
if (!res)
{
DeleteObject(hTempDestDib);
return FALSE;
}
// We have the bits. Now do the blend.
for (int j = 0; j < nHeightSrc; ++j)
{
assert(j >= 0 &&
j < nHeightDest);
LPBYTE pbDestRGB = (LPBYTE)&((DWORD*)pbDestBits)[j * nWidthDest];
assert(nYOriginSrc+SrcDibSec.dsBm.bmHeight-nHeightSrc >= 0 &&
nYOriginSrc+SrcDibSec.dsBm.bmHeight-nHeightSrc < SrcDibSec.dsBm.bmHeight);
LPBYTE pbSrcRGBA = (LPBYTE)&((DWORD*)SrcDibSec.dsBm.bmBits)[(j+nYOriginSrc+SrcDibSec.dsBm.bmHeight-nHeightSrc)
* SrcDibSec.dsBm.bmWidth + nXOriginSrc];
for (int i = 0; i < nWidthSrc; ++i)
{
// Blend
if (pbSrcRGBA[3] == 255)
{
// Alpha is 255. straight copy.
*(LPDWORD)pbDestRGB = *(LPDWORD)pbSrcRGBA;
} else
if (pbSrcRGBA[3])
{
// Alpha is non-zero
pbDestRGB[0] = pbSrcRGBA[0] + (((255-pbSrcRGBA[3]) * pbDestRGB[0]) >> 8);
pbDestRGB[1] = pbSrcRGBA[1] + (((255-pbSrcRGBA[3]) * pbDestRGB[1]) >> 8);
pbDestRGB[2] = pbSrcRGBA[2] + (((255-pbSrcRGBA[3]) * pbDestRGB[2]) >> 8);
}
pbDestRGB += sizeof(DWORD);
pbSrcRGBA += sizeof(DWORD);
} // for
} // for
HDC hdcTempDest = CreateCompatibleDC(hdcDest);
if (hdcTempDest)
{
HBITMAP hOldTempBmp = (HBITMAP)SelectObject(hdcTempDest, hTempDestDib); // Select the temp dib for blitting
// Get logical coord for device coord of dest origin
POINT pt = {nXOriginDest, nYOriginDest};
DPtoLP(hdcDest, &pt, 1);
BitBlt(hdcDest, pt.x, pt.y, nWidthDest, nHeightDest,
hdcTempDest, 0, 0, SRCCOPY);
SelectObject(hdcTempDest, hOldTempBmp);
DeleteDC(hdcTempDest);
}
DeleteObject(hTempDestDib);
return TRUE;
}
CBitmap::~CBitmap()
{
if (m_hbm != NULL)
DeleteObject(m_hbm);
m_hbm = NULL;
m_bSizeKnown = FALSE;
}
HDC CreateAppropDC(HDC hDC)
{
return CreateCompatibleDC(hDC);
}
HBITMAP CreateAppropBitmap(HDC hDC, int cx, int cy)
{
if (hDC != NULL)
return CreateCompatibleBitmap(hDC, cx, cy);
HWND hWnd = GetDesktopWindow();
HDC hWDC = GetWindowDC(hWnd);
HBITMAP hbm = NULL;
if (hWDC != NULL)
{
hbm = CreateCompatibleBitmap(hWDC, cx, cy);
ReleaseDC(hWnd, hWDC);
}
return hbm;
}
CBitmap *CBitmap::CreateFromResource(HINSTANCE hInst, LPCTSTR tszName)
{
return CreateViaLoadImage(hInst, tszName, IMAGE_BITMAP, 0, 0,
LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
}
CBitmap *CBitmap::CreateFromFile(LPCTSTR tszFileName)
{
return CreateViaD3DX(tszFileName);
}
// Use D3DX API to load our surface with image content.
CBitmap *CBitmap::CreateViaD3DX(LPCTSTR tszFileName, LPDIRECT3DSURFACE8 pUISurf)
{
HRESULT hr;
LPDIRECT3D8 pD3D = NULL;
LPDIRECT3DDEVICE8 pD3DDev = NULL;
LPDIRECT3DTEXTURE8 pTex = NULL;
LPDIRECT3DSURFACE8 pSurf = NULL;
HBITMAP hDIB = NULL;
__try
{
//@@BEGIN_MSINTERNAL
pSurf = GetCloneSurface(512, 512); /*
//@@END_MSINTERNAL
// If the UI surface is NULL, create a new device. Otherwise, use existing device.
if (!pUISurf)
{
pD3D = Direct3DCreate8(D3D_SDK_VERSION);
if (!pD3D)
return NULL;
OutputDebugString(_T("D3D created\n"));
D3DDISPLAYMODE Mode;
pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &Mode);
D3DPRESENT_PARAMETERS d3dpp;
d3dpp.BackBufferWidth = 1;
d3dpp.BackBufferHeight = 1;
d3dpp.BackBufferFormat = Mode.Format;
d3dpp.BackBufferCount = 1;
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
d3dpp.hDeviceWindow = NULL;
d3dpp.Windowed = TRUE;
d3dpp.EnableAutoDepthStencil = FALSE;
d3dpp.FullScreen_RefreshRateInHz = 0;
d3dpp.FullScreen_PresentationInterval = 0;
d3dpp.Flags = 0;
hr = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, GetActiveWindow(), D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pD3DDev);
if (FAILED(hr))
{
TCHAR tszMsg[MAX_PATH];
_stprintf(tszMsg, _T("CreateDevice returned 0x%X\n"), hr);
OutputDebugString(tszMsg);
return NULL;
}
} else
{
hr = pUISurf->GetDevice(&pD3DDev);
if (FAILED(hr))
return NULL;
}
OutputDebugString(_T("D3D device createed\n"));
hr = pD3DDev->CreateTexture(512, 512, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &pTex);
if (FAILED(hr))
return NULL;
OutputDebugString(_T("D3D texture createed\n"));
hr = pTex->GetSurfaceLevel(0, &pSurf);
if (FAILED(hr))
return NULL;
OutputDebugString(_T("Surface interface obtained\n"));
//@@BEGIN_MSINTERNAL
*/
//@@END_MSINTERNAL
D3DXIMAGE_INFO d3dii;
if (FAILED(D3DXLoadSurfaceFromFile(pSurf, NULL, NULL, tszFileName, NULL, D3DX_FILTER_NONE, 0, &d3dii)))
return NULL;
// Create a bitmap and copy the texture content onto it.
int iDibWidth = d3dii.Width, iDibHeight = d3dii.Height;
if (iDibWidth > 430) iDibWidth = 430;
if (iDibHeight > 310) iDibHeight = 310;
LPBYTE pDIBBits;
BITMAPINFO bmi;
bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
bmi.bmiHeader.biWidth = iDibWidth;
bmi.bmiHeader.biHeight = iDibHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = 0;
bmi.bmiHeader.biXPelsPerMeter = 0;
bmi.bmiHeader.biYPelsPerMeter = 0;
bmi.bmiHeader.biClrUsed = 0;
bmi.bmiHeader.biClrImportant = 0;
hDIB = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (LPVOID*)&pDIBBits, NULL, 0);
if (!hDIB)
return NULL;
// Pre-process the pixel data based on alpha for AlphaBlend()
D3DLOCKED_RECT lrc;
pSurf->LockRect(&lrc, NULL, NULL);
BYTE *pbData = (LPBYTE)lrc.pBits;
{
for (DWORD i = 0; i < 512 * 512; ++i)
{
BYTE bAlpha = pbData[i * 4 + 3];
pbData[i * 4] = pbData[i * 4] * bAlpha / 255;
pbData[i * 4 + 1] = pbData[i * 4 + 1] * bAlpha / 255;
pbData[i * 4 + 2] = pbData[i * 4 + 2] * bAlpha / 255;
}
}
pSurf->UnlockRect();
// Lock the surface
D3DLOCKED_RECT D3DRect;
hr = pSurf->LockRect(&D3DRect, NULL, 0);
if (FAILED(hr))
return NULL;
// Copy the bits
// Note that the image is reversed in Y direction, so we need to re-reverse it.
for (int y = 0; y < iDibHeight; ++y)
CopyMemory(pDIBBits + ((iDibHeight-1-y) * iDibWidth * 4), (LPBYTE)D3DRect.pBits + (y * D3DRect.Pitch), iDibWidth * 4);
// Unlock
pSurf->UnlockRect();
CBitmap *pbm = new CBitmap;
if (!pbm) return NULL;
pbm->m_hbm = hDIB;
hDIB = NULL;
pbm->FigureSize();
return pbm;
}
__finally
{
if (hDIB) DeleteObject(hDIB);
if (pSurf) pSurf->Release();
if (pTex) pTex->Release();
if (pD3DDev) pD3DDev->Release();
if (pD3D) pD3D->Release();
}
//@@BEGIN_MSINTERNAL
/*
//@@END_MSINTERNAL
return NULL;
//@@BEGIN_MSINTERNAL
*/
//@@END_MSINTERNAL
}
CBitmap *CBitmap::CreateViaLoadImage(HINSTANCE hInst, LPCTSTR tszName, UINT uType, int cx, int cy, UINT fuLoad)
{
if (fuLoad & LR_SHARED)
{
assert(0);
return NULL;
}
CBitmap *pbm = new CBitmap;
if (pbm == NULL)
return NULL;
HANDLE handle = ::LoadImage(hInst, tszName, uType, cx, cy, fuLoad);
if (handle == NULL)
{
delete pbm;
return NULL;
}
pbm->m_hbm = (HBITMAP)handle;
pbm->FigureSize();
return pbm;
}
BOOL CBitmap::FigureSize()
{
BITMAP bm;
if (0 == GetObject((HGDIOBJ)m_hbm, sizeof(BITMAP), (LPVOID)&bm))
return FALSE;
m_size.cx = abs(bm.bmWidth);
m_size.cy = abs(bm.bmHeight);
return m_bSizeKnown = TRUE;
}
CBitmap *CBitmap::StealToCreate(HBITMAP &refbm)
{
if (refbm == NULL)
return NULL;
CBitmap *pbm = new CBitmap;
if (pbm == NULL)
return NULL;
pbm->m_hbm = refbm;
refbm = NULL;
pbm->FigureSize();
return pbm;
}
BOOL CBitmap::GetSize(SIZE *psize)
{
if (m_hbm == NULL || !m_bSizeKnown || psize == NULL)
return FALSE;
*psize = m_size;
return TRUE;
}
void CBitmap::AssumeSize(SIZE size)
{
m_size = size;
m_bSizeKnown = TRUE; //m_hbm != NULL;
}
CBitmap *CBitmap::CreateResizedTo(SIZE size, HDC hDC, int iStretchMode, BOOL bStretch)
{
CBitmap *pbm = new CBitmap;
HDC hSrcDC = NULL;
HDC hDestDC = NULL;
HBITMAP hBitmap = NULL;
HGDIOBJ hOldSrcBitmap = NULL, hOldDestBitmap = NULL;
BOOL bRet = FALSE;
int oldsm = 0;
POINT brushorg;
if (pbm == NULL || size.cx < 1 || size.cy < 1 || m_hbm == NULL || !m_bSizeKnown)
goto error;
hSrcDC = CreateAppropDC(hDC);
hDestDC = CreateAppropDC(hDC);
if (hSrcDC == NULL || hDestDC == NULL)
goto error;
hBitmap = CreateAppropBitmap(hDC, size.cx, size.cy);
if (hBitmap == NULL)
goto error;
if (bStretch)
{
if (GetStretchBltMode(hDestDC) != iStretchMode)
{
if (iStretchMode == HALFTONE)
GetBrushOrgEx(hDestDC, &brushorg);
oldsm = SetStretchBltMode(hDestDC, iStretchMode);
if (iStretchMode == HALFTONE)
SetBrushOrgEx(hDestDC, brushorg.x, brushorg.y, NULL);
}
}
hOldSrcBitmap = SelectObject(hSrcDC, m_hbm);
hOldDestBitmap = SelectObject(hDestDC, hBitmap);
if (bStretch)
bRet = StretchBlt(hDestDC, 0, 0, size.cx, size.cy, hSrcDC, 0, 0, m_size.cx, m_size.cy, SRCCOPY);
else
bRet = BitBlt(hDestDC, 0, 0, size.cx, size.cy, hSrcDC, 0, 0, SRCCOPY);
SelectObject(hDestDC, hOldDestBitmap);
SelectObject(hSrcDC, hOldSrcBitmap);
if (bStretch)
{
if (oldsm != 0)
{
if (oldsm == HALFTONE)
GetBrushOrgEx(hDestDC, &brushorg);
SetStretchBltMode(hDestDC, oldsm);
if (oldsm == HALFTONE)
SetBrushOrgEx(hDestDC, brushorg.x, brushorg.y, NULL);
}
}
if (!bRet)
goto error;
pbm->m_hbm = hBitmap;
hBitmap = NULL;
pbm->AssumeSize(size);
goto cleanup;
error:
if (pbm != NULL)
delete pbm;
pbm = NULL;
cleanup:
if (hBitmap != NULL)
DeleteObject(hBitmap);
if (hSrcDC != NULL)
DeleteDC(hSrcDC);
if (hDestDC != NULL)
DeleteDC(hDestDC);
return pbm;
}
HDC CBitmap::BeginPaintInto(HDC hCDC)
{
if (m_hDCInto != NULL)
{
assert(0);
return NULL;
}
m_hDCInto = CreateAppropDC(hCDC);
if (m_hDCInto == NULL)
return NULL;
m_hOldBitmap = SelectObject(m_hDCInto, m_hbm);
return m_hDCInto;
}
void CBitmap::EndPaintInto(HDC &hDC)
{
if (hDC == NULL || hDC != m_hDCInto)
{
assert(0);
return;
}
SelectObject(m_hDCInto, m_hOldBitmap);
DeleteDC(m_hDCInto);
m_hDCInto = NULL;
hDC = NULL;
}
void CBitmap::PopOut()
{
if (m_hDCInto == NULL)
{
assert(0);
return;
}
SelectObject(m_hDCInto, m_hOldBitmap);
}
void CBitmap::PopIn()
{
if (m_hDCInto == NULL)
{
assert(0);
return;
}
m_hOldBitmap = SelectObject(m_hDCInto, m_hbm);
}
BOOL CBitmap::Draw(HDC hDC, POINT origin, SIZE crop, BOOL bAll)
{
if (hDC == NULL || m_hbm == NULL)
return FALSE;
if (bAll && !m_bSizeKnown)
return FALSE;
if (bAll)
crop = m_size;
HDC hDCbm = CreateAppropDC(hDC);
if (hDCbm == NULL)
return FALSE;
BOOL bPop = m_hDCInto != NULL;
if (bPop)
PopOut();
HGDIOBJ hOldBitmap = SelectObject(hDCbm, m_hbm);
BOOL bRet = BitBlt(hDC, origin.x, origin.y, crop.cx, crop.cy, hDCbm, 0, 0, SRCCOPY);
SelectObject(hDCbm, hOldBitmap);
DeleteDC(hDCbm);
if (bPop)
PopIn();
return bRet;
}
BOOL CBitmap::Blend(HDC hDC, POINT origin, SIZE crop, BOOL bAll)
{
if (hDC == NULL || m_hbm == NULL)
return FALSE;
if (bAll && !m_bSizeKnown)
return FALSE;
if (bAll)
crop = m_size;
HDC hDCbm = CreateAppropDC(hDC);
if (hDCbm == NULL)
return FALSE;
BOOL bPop = m_hDCInto != NULL;
if (bPop)
PopOut();
#ifndef AC_SRC_ALPHA
#define AC_SRC_ALPHA AC_SRC_NO_PREMULT_ALPHA
#endif
HGDIOBJ hOldBitmap = SelectObject(hDCbm, m_hbm);
BOOL bRet;
//@@BEGIN_MSINTERNAL
/* if (!g_AlphaBlend) // If AlphaBlend is not available, use BitBlt instead.
{
bRet = BitBlt(hDC, origin.x, origin.y, crop.cx, crop.cy, hDCbm, 0, 0, SRCPAINT);
}
else
{
BLENDFUNCTION blendfn = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
bRet = g_AlphaBlend(hDC, origin.x, origin.y, crop.cx, crop.cy, hDCbm, 0, 0, m_size.cx, m_size.cy, blendfn);
}*/
//@@END_MSINTERNAL
bRet = DI_AlphaBlend(hDC, origin.x, origin.y, crop.cx, crop.cy, hDCbm, 0, 0, m_size.cx, m_size.cy);
SelectObject(hDCbm, hOldBitmap);
DeleteDC(hDCbm);
if (bPop)
PopIn();
return bRet;
}
CBitmap *CBitmap::Dup()
{
SIZE t;
if (!GetSize(&t))
return NULL;
return CreateResizedTo(t, NULL, COLORONCOLOR, FALSE);
}
CBitmap *CBitmap::Create(SIZE size, HDC hCDC)
{
CBitmap *pbm = new CBitmap;
if (pbm == NULL)
return NULL;
pbm->m_hbm = CreateAppropBitmap(hCDC, size.cx, size.cy);
if (pbm->m_hbm == NULL)
{
delete pbm;
return NULL;
}
pbm->AssumeSize(size);
return pbm;
}
CBitmap *CBitmap::Create(SIZE size, COLORREF color, HDC hCDC)
{
CBitmap *pbm = Create(size, hCDC);
if (pbm == NULL)
return NULL;
HDC hDC = pbm->BeginPaintInto();
if (hDC == NULL)
{
delete pbm;
return NULL;
}
HGDIOBJ hBrush = (HGDIOBJ)CreateSolidBrush(color), hOldBrush;
if (hBrush)
{
hOldBrush = SelectObject(hDC, hBrush);
Rectangle(hDC, -1, -1, size.cx + 1, size.cy + 1);
SelectObject(hDC, hOldBrush);
DeleteObject(hBrush);
}
pbm->EndPaintInto(hDC);
return pbm;
}
BOOL CBitmap::Get(HDC hDC, POINT point)
{
if (!m_bSizeKnown)
return FALSE;
return Get(hDC, point, m_size);
}
BOOL CBitmap::Get(HDC hDC, POINT point, SIZE size)
{
if (m_hDCInto != NULL || hDC == NULL)
return FALSE;
HDC hDCInto = BeginPaintInto(hDC);
if (hDCInto == NULL)
return FALSE;
BOOL bRet = BitBlt(hDCInto, 0, 0, size.cx, size.cy, hDC, point.x, point.y, SRCCOPY);
EndPaintInto(hDCInto);
return bRet;
}
CBitmap *CBitmap::CreateHorzGradient(const RECT &rect, COLORREF rgbLeft, COLORREF rgbRight)
{
SIZE size = GetRectSize(rect);
COLORREF rgbMid = RGB(
(int(GetRValue(rgbLeft)) + int(GetRValue(rgbRight))) / 2,
(int(GetGValue(rgbLeft)) + int(GetGValue(rgbRight))) / 2,
(int(GetBValue(rgbLeft)) + int(GetBValue(rgbRight))) / 2);
return Create(size, rgbMid);
}
BOOL CBitmap::MapToDC(HDC hDCTo, HDC hDCMapFrom)
{
if (hDCTo == NULL || !m_bSizeKnown || m_hDCInto != NULL)
return FALSE;
HBITMAP hbm = CreateAppropBitmap(hDCTo, m_size.cx, m_size.cy);
if (hbm == NULL)
return FALSE;
HDC hDCFrom = NULL;
HDC hDCInto = NULL;
HGDIOBJ hOld = NULL;
BOOL bRet = FALSE;
hDCFrom = BeginPaintInto(hDCMapFrom);
if (!hDCFrom)
goto cleanup;
hDCInto = CreateCompatibleDC(hDCTo);
if (!hDCInto)
goto cleanup;
hOld = SelectObject(hDCInto, (HGDIOBJ)hbm);
bRet = BitBlt(hDCInto, 0, 0, m_size.cx, m_size.cy, hDCFrom, 0, 0, SRCCOPY);
SelectObject(hDCInto, hOld);
cleanup:
if (hDCFrom)
EndPaintInto(hDCFrom);
if (hDCInto)
DeleteDC(hDCInto);
if (bRet)
{
if (m_hbm)
DeleteObject((HGDIOBJ)m_hbm);
m_hbm = hbm;
hbm = NULL;
}
if (hbm)
DeleteObject((HGDIOBJ)hbm);
return bRet;
}