home *** CD-ROM | disk | FTP | other *** search
/ Beginning Direct3D Game Programming / Direct3D.iso / directx / dxf / samples / multimedia / directinput / diconfig / cbitmap.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-05  |  17.6 KB  |  714 lines

  1. //-----------------------------------------------------------------------------
  2. // File: Cbitmap.cpp
  3. //
  4. // Desc: CBitmap class is an object that wraps around a Windows bitmap.
  5. //
  6. // Copyright (C) 1999-2000 Microsoft Corporation. All Rights Reserved.
  7. //-----------------------------------------------------------------------------
  8.  
  9. #include "common.hpp"
  10. #include "id3dsurf.h"
  11.  
  12. BOOL DI_AlphaBlend(
  13.   HDC hdcDest,                 // handle to destination DC
  14.   int nXOriginDest,            // x-coord of upper-left corner
  15.   int nYOriginDest,            // y-coord of upper-left corner
  16.   int nWidthDest,              // destination width
  17.   int nHeightDest,             // destination height
  18.   HDC hdcSrc,                  // handle to source DC
  19.   int nXOriginSrc,             // x-coord of upper-left corner
  20.   int nYOriginSrc,             // y-coord of upper-left corner
  21.   int nWidthSrc,               // source width
  22.   int nHeightSrc              // source height
  23. )
  24. {
  25.     LPBYTE pbDestBits = NULL;
  26.     HBITMAP hTempDestDib = NULL;
  27.     int nXOriginDestLogical = nXOriginDest, nYOriginDestLogical = nYOriginDest;
  28.  
  29.     // Convert nXOriginDest and nYOriginDest from logical coord to device coord
  30.     POINT pt = {nXOriginDest, nYOriginDest};
  31.     LPtoDP(hdcDest, &pt, 1);
  32.     nXOriginDest = pt.x;
  33.     nYOriginDest = pt.y;
  34.     // Convert nXOriginSrc and nYOriginSrc from logical coord to device coord
  35.     pt.x = nXOriginSrc;
  36.     pt.y = nYOriginSrc;
  37.     LPtoDP(hdcSrc, &pt, 1);
  38.     nXOriginSrc = pt.x;
  39.     nYOriginSrc = pt.y;
  40.  
  41.     // Get the bits for both source and destination first
  42.     // Every BITMAP used in the UI is created with CreateDIBSection, so we know we can get the bits.
  43.     HBITMAP hSrcBmp, hDestBmp;
  44.     DIBSECTION SrcDibSec, DestDibSec;
  45.     hSrcBmp = (HBITMAP)GetCurrentObject(hdcSrc, OBJ_BITMAP);
  46.     GetObject(hSrcBmp, sizeof(DIBSECTION), &SrcDibSec);
  47.     hDestBmp = (HBITMAP)GetCurrentObject(hdcDest, OBJ_BITMAP);
  48.     GetObject(hDestBmp, sizeof(DIBSECTION), &DestDibSec);
  49.     if (!SrcDibSec.dsBm.bmBits) return FALSE;  // Not necessary, but to be absolutely safe.
  50.  
  51.     // Calculate the rectangle to perform the operation.
  52.     if (nXOriginSrc + nWidthSrc > SrcDibSec.dsBm.bmWidth) nWidthSrc = SrcDibSec.dsBm.bmWidth - nXOriginSrc;
  53.     if (nYOriginSrc + nHeightSrc > SrcDibSec.dsBm.bmHeight) nHeightSrc = SrcDibSec.dsBm.bmHeight - nYOriginSrc;
  54.     if (nXOriginDest + nWidthDest > DestDibSec.dsBm.bmWidth) nWidthDest = DestDibSec.dsBm.bmWidth - nXOriginDest;
  55.     if (nYOriginDest + nHeightDest > DestDibSec.dsBm.bmHeight) nHeightDest = DestDibSec.dsBm.bmHeight - nYOriginDest;
  56.  
  57.     if (nWidthDest > nWidthSrc) nWidthDest = nWidthSrc;
  58.     if (nHeightDest > nHeightSrc) nHeightDest = nHeightSrc;
  59.     if (nWidthSrc > nWidthDest) nWidthSrc = nWidthDest;
  60.     if (nHeightSrc > nHeightDest) nHeightSrc = nHeightDest;
  61.  
  62.     BITMAPINFO bmi;
  63.     ZeroMemory(&bmi.bmiHeader, sizeof(BITMAPINFOHEADER));
  64.     bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  65.     bmi.bmiHeader.biWidth = nWidthDest;
  66.     bmi.bmiHeader.biHeight = nHeightDest;
  67.     bmi.bmiHeader.biPlanes = 1;
  68.     bmi.bmiHeader.biBitCount = 32;
  69.     bmi.bmiHeader.biCompression = BI_RGB;
  70.  
  71.     // Bitmap will have the same width as the dest, but only lines covered in the subrect.
  72.     hTempDestDib = CreateDIBSection(hdcDest, &bmi, DIB_RGB_COLORS, (LPVOID*)&pbDestBits, NULL, NULL);
  73.     if (!hTempDestDib)
  74.         return FALSE;
  75.  
  76.     HDC hTempDC = CreateCompatibleDC(hdcDest);
  77.     if (!hTempDC)
  78.     {
  79.         DeleteObject(hTempDestDib);
  80.         return FALSE;
  81.     }
  82.     HBITMAP hOldTempBmp = (HBITMAP)SelectObject(hTempDC, hTempDestDib);
  83.     BOOL res = BitBlt(hTempDC, 0, 0, nWidthDest, nHeightDest, hdcDest, nXOriginDestLogical, nYOriginDestLogical, SRCCOPY);
  84.     SelectObject(hTempDC, hOldTempBmp);
  85.     DeleteDC(hTempDC);
  86.     if (!res)
  87.     {
  88.         DeleteObject(hTempDestDib);
  89.         return FALSE;
  90.     }
  91.  
  92.     // We have the bits. Now do the blend.
  93.     for (int j = 0; j < nHeightSrc; ++j)
  94.     {
  95.         assert(j >= 0 &&
  96.                j < nHeightDest);
  97.         LPBYTE pbDestRGB = (LPBYTE)&((DWORD*)pbDestBits)[j * nWidthDest];
  98.  
  99.         assert(nYOriginSrc+SrcDibSec.dsBm.bmHeight-nHeightSrc >= 0 &&
  100.                nYOriginSrc+SrcDibSec.dsBm.bmHeight-nHeightSrc < SrcDibSec.dsBm.bmHeight);
  101.         LPBYTE pbSrcRGBA = (LPBYTE)&((DWORD*)SrcDibSec.dsBm.bmBits)[(j+nYOriginSrc+SrcDibSec.dsBm.bmHeight-nHeightSrc)
  102.                                                                     * SrcDibSec.dsBm.bmWidth + nXOriginSrc];
  103.  
  104.         for (int i = 0; i < nWidthSrc; ++i)
  105.         {
  106.             // Blend
  107.             if (pbSrcRGBA[3] == 255)
  108.             {
  109.                 // Alpha is 255. straight copy.
  110.                 *(LPDWORD)pbDestRGB = *(LPDWORD)pbSrcRGBA;
  111.             } else
  112.             if (pbSrcRGBA[3])
  113.             {
  114.                 // Alpha is non-zero
  115.                 pbDestRGB[0] = pbSrcRGBA[0] + (((255-pbSrcRGBA[3]) * pbDestRGB[0]) >> 8);
  116.                 pbDestRGB[1] = pbSrcRGBA[1] + (((255-pbSrcRGBA[3]) * pbDestRGB[1]) >> 8);
  117.                 pbDestRGB[2] = pbSrcRGBA[2] + (((255-pbSrcRGBA[3]) * pbDestRGB[2]) >> 8);
  118.             }
  119.             pbDestRGB += sizeof(DWORD);
  120.             pbSrcRGBA += sizeof(DWORD);
  121.         }  // for
  122.     } // for
  123.  
  124.     HDC hdcTempDest = CreateCompatibleDC(hdcDest);
  125.     if (hdcTempDest)
  126.     {
  127.         HBITMAP hOldTempBmp = (HBITMAP)SelectObject(hdcTempDest, hTempDestDib);  // Select the temp dib for blitting
  128.         // Get logical coord for device coord of dest origin
  129.         POINT pt = {nXOriginDest, nYOriginDest};
  130.         DPtoLP(hdcDest, &pt, 1);
  131.         BitBlt(hdcDest, pt.x, pt.y, nWidthDest, nHeightDest,
  132.                hdcTempDest, 0, 0, SRCCOPY);
  133.         SelectObject(hdcTempDest, hOldTempBmp);
  134.         DeleteDC(hdcTempDest);
  135.     }
  136.  
  137.     DeleteObject(hTempDestDib);
  138.     return TRUE;
  139. }
  140.  
  141. CBitmap::~CBitmap()
  142. {
  143.     if (m_hbm != NULL)
  144.         DeleteObject(m_hbm);
  145.     m_hbm = NULL;
  146.     m_bSizeKnown = FALSE;
  147. }
  148.  
  149. HDC CreateAppropDC(HDC hDC)
  150. {
  151.     return CreateCompatibleDC(hDC);
  152. }
  153.  
  154. HBITMAP CreateAppropBitmap(HDC hDC, int cx, int cy)
  155. {
  156.     if (hDC != NULL)
  157.         return CreateCompatibleBitmap(hDC, cx, cy);
  158.     
  159.     HWND hWnd = GetDesktopWindow();
  160.     HDC hWDC = GetWindowDC(hWnd);
  161.     HBITMAP hbm = NULL;
  162.     if (hWDC != NULL)
  163.     {
  164.         hbm = CreateCompatibleBitmap(hWDC, cx, cy);
  165.         ReleaseDC(hWnd, hWDC);
  166.     }
  167.  
  168.     return hbm;
  169. }
  170.  
  171. CBitmap *CBitmap::CreateFromResource(HINSTANCE hInst, LPCTSTR tszName)
  172. {
  173.     return CreateViaLoadImage(hInst, tszName, IMAGE_BITMAP, 0, 0,
  174.         LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
  175. }
  176.  
  177. CBitmap *CBitmap::CreateFromFile(LPCTSTR tszFileName)
  178. {
  179.     return CreateViaD3DX(tszFileName);
  180. }
  181.  
  182. // Use D3DX API to load our surface with image content.
  183. CBitmap *CBitmap::CreateViaD3DX(LPCTSTR tszFileName, LPDIRECT3DSURFACE8 pUISurf)
  184. {
  185.     HRESULT hr;
  186.     LPDIRECT3D8 pD3D = NULL;
  187.     LPDIRECT3DDEVICE8 pD3DDev = NULL;
  188.     LPDIRECT3DTEXTURE8 pTex = NULL;
  189.     LPDIRECT3DSURFACE8 pSurf = NULL;
  190.     HBITMAP hDIB = NULL;
  191.  
  192.     __try
  193.     {
  194.  
  195.         // If the UI surface is NULL, create a new device.  Otherwise, use existing device.
  196.         if (!pUISurf)
  197.         {
  198.             pD3D = Direct3DCreate8(D3D_SDK_VERSION);
  199.             if (!pD3D)
  200.                 return NULL;
  201.             OutputDebugString(_T("D3D created\n"));
  202.             D3DDISPLAYMODE Mode;
  203.             pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &Mode);
  204.             D3DPRESENT_PARAMETERS d3dpp;
  205.             d3dpp.BackBufferWidth = 1;
  206.             d3dpp.BackBufferHeight = 1;
  207.             d3dpp.BackBufferFormat = Mode.Format;
  208.             d3dpp.BackBufferCount = 1;
  209.             d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
  210.             d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
  211.             d3dpp.hDeviceWindow = NULL;
  212.             d3dpp.Windowed = TRUE;
  213.             d3dpp.EnableAutoDepthStencil = FALSE;
  214.             d3dpp.FullScreen_RefreshRateInHz = 0;
  215.             d3dpp.FullScreen_PresentationInterval = 0;
  216.             d3dpp.Flags = 0;
  217.             hr = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, GetActiveWindow(), D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pD3DDev);
  218.             if (FAILED(hr))
  219.             {
  220.                 TCHAR tszMsg[MAX_PATH];
  221.  
  222.                 _stprintf(tszMsg, _T("CreateDevice returned 0x%X\n"), hr);
  223.                 OutputDebugString(tszMsg);
  224.                 return NULL;
  225.             }
  226.         } else
  227.         {
  228.             hr = pUISurf->GetDevice(&pD3DDev);
  229.             if (FAILED(hr))
  230.                 return NULL;
  231.         }
  232.  
  233.         OutputDebugString(_T("D3D device createed\n"));
  234.         hr = pD3DDev->CreateTexture(512, 512, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &pTex);
  235.         if (FAILED(hr))
  236.             return NULL;
  237.         OutputDebugString(_T("D3D texture createed\n"));
  238.         hr = pTex->GetSurfaceLevel(0, &pSurf);
  239.         if (FAILED(hr))
  240.             return NULL;
  241.         OutputDebugString(_T("Surface interface obtained\n"));
  242.  
  243.         D3DXIMAGE_INFO d3dii;
  244.         if (FAILED(D3DXLoadSurfaceFromFile(pSurf, NULL, NULL, tszFileName, NULL, D3DX_FILTER_NONE, 0, &d3dii)))
  245.             return NULL;
  246.  
  247.         // Create a bitmap and copy the texture content onto it.
  248.         int iDibWidth = d3dii.Width, iDibHeight = d3dii.Height;
  249.         if (iDibWidth > 430) iDibWidth = 430;
  250.         if (iDibHeight > 310) iDibHeight = 310;
  251.         LPBYTE pDIBBits;
  252.         BITMAPINFO bmi;
  253.         bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
  254.         bmi.bmiHeader.biWidth = iDibWidth;
  255.         bmi.bmiHeader.biHeight = iDibHeight;
  256.         bmi.bmiHeader.biPlanes = 1;
  257.         bmi.bmiHeader.biBitCount = 32;
  258.         bmi.bmiHeader.biCompression = BI_RGB;
  259.         bmi.bmiHeader.biSizeImage = 0;
  260.         bmi.bmiHeader.biXPelsPerMeter = 0;
  261.         bmi.bmiHeader.biYPelsPerMeter = 0;
  262.         bmi.bmiHeader.biClrUsed = 0;
  263.         bmi.bmiHeader.biClrImportant = 0;
  264.         hDIB = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (LPVOID*)&pDIBBits, NULL, 0);
  265.         if (!hDIB)
  266.             return NULL;
  267.  
  268.         // Pre-process the pixel data based on alpha for AlphaBlend()
  269.         D3DLOCKED_RECT lrc;
  270.         pSurf->LockRect(&lrc, NULL, NULL);
  271.         BYTE *pbData = (LPBYTE)lrc.pBits;
  272.         {
  273.             for (DWORD i = 0; i < 512 * 512; ++i)
  274.             {
  275.                 BYTE bAlpha = pbData[i * 4 + 3];
  276.                 pbData[i * 4] = pbData[i * 4] * bAlpha / 255;
  277.                 pbData[i * 4 + 1] = pbData[i * 4 + 1] * bAlpha / 255;
  278.                 pbData[i * 4 + 2] = pbData[i * 4 + 2] * bAlpha / 255;
  279.             }
  280.         }
  281.         pSurf->UnlockRect();
  282.  
  283.         // Lock the surface
  284.         D3DLOCKED_RECT D3DRect;
  285.         hr = pSurf->LockRect(&D3DRect, NULL, 0);
  286.         if (FAILED(hr))
  287.             return NULL;
  288.  
  289.         // Copy the bits
  290.         // Note that the image is reversed in Y direction, so we need to re-reverse it.
  291.         for (int y = 0; y < iDibHeight; ++y)
  292.             CopyMemory(pDIBBits + ((iDibHeight-1-y) * iDibWidth * 4), (LPBYTE)D3DRect.pBits + (y * D3DRect.Pitch), iDibWidth * 4);
  293.  
  294.         // Unlock
  295.         pSurf->UnlockRect();
  296.  
  297.         CBitmap *pbm = new CBitmap;
  298.         if (!pbm) return NULL;
  299.         pbm->m_hbm = hDIB;
  300.         hDIB = NULL;
  301.         pbm->FigureSize();
  302.  
  303.         return pbm;
  304.     }
  305.     __finally
  306.     {
  307.         if (hDIB) DeleteObject(hDIB);
  308.         if (pSurf) pSurf->Release();
  309.         if (pTex) pTex->Release();
  310.         if (pD3DDev) pD3DDev->Release();
  311.         if (pD3D) pD3D->Release();
  312.     }
  313.     return NULL;
  314. }
  315.  
  316. CBitmap *CBitmap::CreateViaLoadImage(HINSTANCE hInst, LPCTSTR tszName, UINT uType, int cx, int cy, UINT fuLoad)
  317. {
  318.     if (fuLoad & LR_SHARED)
  319.     {
  320.         assert(0);
  321.         return NULL;
  322.     }
  323.  
  324.     CBitmap *pbm = new CBitmap;
  325.     if (pbm == NULL)
  326.         return NULL;
  327.     
  328.     HANDLE handle = ::LoadImage(hInst, tszName, uType, cx, cy, fuLoad);
  329.     
  330.     if (handle == NULL)
  331.     {
  332.         delete pbm;
  333.         return NULL;
  334.     }
  335.  
  336.     pbm->m_hbm = (HBITMAP)handle;
  337.  
  338.     pbm->FigureSize();
  339.  
  340.     return pbm;
  341. }
  342.  
  343. BOOL CBitmap::FigureSize()
  344. {
  345.     BITMAP bm;
  346.  
  347.     if (0 == GetObject((HGDIOBJ)m_hbm, sizeof(BITMAP), (LPVOID)&bm))
  348.         return FALSE;
  349.  
  350.     m_size.cx = abs(bm.bmWidth);
  351.     m_size.cy = abs(bm.bmHeight);
  352.  
  353.     return m_bSizeKnown = TRUE;
  354. }
  355.  
  356. CBitmap *CBitmap::StealToCreate(HBITMAP &refbm)
  357. {
  358.     if (refbm == NULL)
  359.         return NULL;
  360.  
  361.     CBitmap *pbm = new CBitmap;
  362.     if (pbm == NULL)
  363.         return NULL;
  364.     
  365.     pbm->m_hbm = refbm;
  366.     refbm = NULL;
  367.  
  368.     pbm->FigureSize();
  369.  
  370.     return pbm;
  371. }
  372.  
  373. BOOL CBitmap::GetSize(SIZE *psize)
  374. {
  375.     if (m_hbm == NULL || !m_bSizeKnown || psize == NULL)
  376.         return FALSE;
  377.  
  378.     *psize = m_size;
  379.     return TRUE;
  380. }
  381.  
  382. void CBitmap::AssumeSize(SIZE size)
  383. {
  384.     m_size = size;
  385.     m_bSizeKnown = TRUE;  //m_hbm != NULL;
  386. }
  387.  
  388. CBitmap *CBitmap::CreateResizedTo(SIZE size, HDC hDC, int iStretchMode, BOOL bStretch)
  389. {
  390.     CBitmap *pbm = new CBitmap;
  391.     HDC hSrcDC = NULL;
  392.     HDC hDestDC = NULL;
  393.     HBITMAP hBitmap = NULL;
  394.     HGDIOBJ hOldSrcBitmap = NULL, hOldDestBitmap = NULL;
  395.     BOOL bRet = FALSE;
  396.     int oldsm = 0;
  397.     POINT brushorg;
  398.  
  399.     if (pbm == NULL || size.cx < 1 || size.cy < 1 || m_hbm == NULL || !m_bSizeKnown)
  400.         goto error;
  401.  
  402.     hSrcDC = CreateAppropDC(hDC);
  403.     hDestDC = CreateAppropDC(hDC);
  404.     if (hSrcDC == NULL || hDestDC == NULL)
  405.         goto error;
  406.  
  407.     hBitmap = CreateAppropBitmap(hDC, size.cx, size.cy);
  408.     if (hBitmap == NULL)
  409.         goto error;
  410.  
  411.     if (bStretch)
  412.     {
  413.         if (GetStretchBltMode(hDestDC) != iStretchMode)
  414.         {
  415.             if (iStretchMode == HALFTONE)
  416.                 GetBrushOrgEx(hDestDC, &brushorg);
  417.             oldsm = SetStretchBltMode(hDestDC, iStretchMode);
  418.             if (iStretchMode == HALFTONE)
  419.                 SetBrushOrgEx(hDestDC, brushorg.x, brushorg.y, NULL);
  420.         }
  421.     }
  422.  
  423.     hOldSrcBitmap = SelectObject(hSrcDC, m_hbm);
  424.     hOldDestBitmap = SelectObject(hDestDC, hBitmap);
  425.     if (bStretch)
  426.         bRet = StretchBlt(hDestDC, 0, 0, size.cx, size.cy, hSrcDC, 0, 0, m_size.cx, m_size.cy, SRCCOPY);
  427.     else
  428.         bRet = BitBlt(hDestDC, 0, 0, size.cx, size.cy, hSrcDC, 0, 0, SRCCOPY);
  429.     SelectObject(hDestDC, hOldDestBitmap);
  430.     SelectObject(hSrcDC, hOldSrcBitmap);
  431.  
  432.     if (bStretch)
  433.     {
  434.         if (oldsm != 0)
  435.         {
  436.             if (oldsm == HALFTONE)
  437.                 GetBrushOrgEx(hDestDC, &brushorg);
  438.             SetStretchBltMode(hDestDC, oldsm);
  439.             if (oldsm == HALFTONE)
  440.                 SetBrushOrgEx(hDestDC, brushorg.x, brushorg.y, NULL);
  441.         }
  442.     }
  443.  
  444.     if (!bRet)
  445.         goto error;
  446.  
  447.     pbm->m_hbm = hBitmap;
  448.     hBitmap = NULL;
  449.     pbm->AssumeSize(size);
  450.  
  451.     goto cleanup;
  452. error:
  453.     if (pbm != NULL)
  454.         delete pbm;
  455.     pbm = NULL;
  456. cleanup:
  457.     if (hBitmap != NULL)
  458.         DeleteObject(hBitmap);
  459.     if (hSrcDC != NULL)
  460.         DeleteDC(hSrcDC);
  461.     if (hDestDC != NULL)
  462.         DeleteDC(hDestDC);
  463.  
  464.     return pbm;
  465. }
  466.  
  467. HDC CBitmap::BeginPaintInto(HDC hCDC)
  468. {
  469.     if (m_hDCInto != NULL)
  470.     {
  471.         assert(0);
  472.         return NULL;
  473.     }
  474.  
  475.     m_hDCInto = CreateAppropDC(hCDC);
  476.     if (m_hDCInto == NULL)
  477.         return NULL;
  478.  
  479.     m_hOldBitmap = SelectObject(m_hDCInto, m_hbm);
  480.  
  481.     return m_hDCInto;
  482. }
  483.  
  484. void CBitmap::EndPaintInto(HDC &hDC)
  485. {
  486.     if (hDC == NULL || hDC != m_hDCInto)
  487.     {
  488.         assert(0);
  489.         return;
  490.     }
  491.  
  492.     SelectObject(m_hDCInto, m_hOldBitmap);
  493.     DeleteDC(m_hDCInto);
  494.     m_hDCInto = NULL;
  495.     hDC = NULL;
  496. }
  497.  
  498. void CBitmap::PopOut()
  499. {
  500.     if (m_hDCInto == NULL)
  501.     {
  502.         assert(0);
  503.         return;
  504.     }
  505.  
  506.     SelectObject(m_hDCInto, m_hOldBitmap);
  507. }
  508.  
  509. void CBitmap::PopIn()
  510. {
  511.     if (m_hDCInto == NULL)
  512.     {
  513.         assert(0);
  514.         return;
  515.     }
  516.  
  517.     m_hOldBitmap = SelectObject(m_hDCInto, m_hbm);
  518. }
  519.  
  520. BOOL CBitmap::Draw(HDC hDC, POINT origin, SIZE crop, BOOL bAll)
  521. {
  522.     if (hDC == NULL || m_hbm == NULL)
  523.         return FALSE;
  524.  
  525.     if (bAll && !m_bSizeKnown)
  526.         return FALSE;
  527.  
  528.     if (bAll)
  529.         crop = m_size;
  530.  
  531.     HDC hDCbm = CreateAppropDC(hDC);
  532.     if (hDCbm == NULL)
  533.         return FALSE;
  534.  
  535.     BOOL bPop = m_hDCInto != NULL;
  536.  
  537.     if (bPop)
  538.         PopOut();
  539.  
  540.     HGDIOBJ hOldBitmap = SelectObject(hDCbm, m_hbm);
  541.     BOOL bRet = BitBlt(hDC, origin.x, origin.y, crop.cx, crop.cy, hDCbm, 0, 0, SRCCOPY);
  542.     SelectObject(hDCbm, hOldBitmap);
  543.     DeleteDC(hDCbm);
  544.  
  545.     if (bPop)
  546.         PopIn();
  547.  
  548.     return bRet;
  549. }
  550.  
  551. BOOL CBitmap::Blend(HDC hDC, POINT origin, SIZE crop, BOOL bAll)
  552. {
  553.     if (hDC == NULL || m_hbm == NULL)
  554.         return FALSE;
  555.  
  556.     if (bAll && !m_bSizeKnown)
  557.         return FALSE;
  558.  
  559.     if (bAll)
  560.         crop = m_size;
  561.  
  562.     HDC hDCbm = CreateAppropDC(hDC);
  563.     if (hDCbm == NULL)
  564.         return FALSE;
  565.  
  566.     BOOL bPop = m_hDCInto != NULL;
  567.  
  568.     if (bPop)
  569.         PopOut();
  570.  
  571. #ifndef AC_SRC_ALPHA
  572. #define AC_SRC_ALPHA AC_SRC_NO_PREMULT_ALPHA
  573. #endif
  574.  
  575.     HGDIOBJ hOldBitmap = SelectObject(hDCbm, m_hbm);
  576.     BOOL bRet;
  577.  
  578.     bRet = DI_AlphaBlend(hDC, origin.x, origin.y, crop.cx, crop.cy, hDCbm, 0, 0, m_size.cx, m_size.cy);
  579.     SelectObject(hDCbm, hOldBitmap);
  580.     DeleteDC(hDCbm);
  581.  
  582.     if (bPop)
  583.         PopIn();
  584.  
  585.     return bRet;
  586. }
  587.  
  588. CBitmap *CBitmap::Dup()
  589. {    
  590.     SIZE t;
  591.     if (!GetSize(&t))
  592.         return NULL;
  593.     return CreateResizedTo(t, NULL, COLORONCOLOR, FALSE);
  594. }
  595.  
  596. CBitmap *CBitmap::Create(SIZE size, HDC hCDC)
  597. {
  598.     CBitmap *pbm = new CBitmap;
  599.     if (pbm == NULL)
  600.         return NULL;
  601.  
  602.     pbm->m_hbm = CreateAppropBitmap(hCDC, size.cx, size.cy);
  603.     if (pbm->m_hbm == NULL)
  604.     {
  605.         delete pbm;
  606.         return NULL;
  607.     }
  608.  
  609.     pbm->AssumeSize(size);
  610.  
  611.     return pbm;
  612. }
  613.  
  614. CBitmap *CBitmap::Create(SIZE size, COLORREF color, HDC hCDC)
  615. {
  616.     CBitmap *pbm = Create(size, hCDC);
  617.     if (pbm == NULL)
  618.         return NULL;
  619.  
  620.     HDC hDC = pbm->BeginPaintInto();
  621.     if (hDC == NULL)
  622.     {
  623.         delete pbm;
  624.         return NULL;
  625.     }
  626.     
  627.     HGDIOBJ hBrush = (HGDIOBJ)CreateSolidBrush(color),
  628.         hOldBrush = SelectObject(hDC, hBrush);
  629.     Rectangle(hDC, -1, -1, size.cx + 1, size.cy + 1);
  630.     SelectObject(hDC, hOldBrush);
  631.     DeleteObject(hBrush);
  632.  
  633.     pbm->EndPaintInto(hDC);
  634.  
  635.     return pbm;
  636. }
  637.  
  638. BOOL CBitmap::Get(HDC hDC, POINT point)
  639. {
  640.     if (!m_bSizeKnown)
  641.         return FALSE;
  642.     return Get(hDC, point, m_size);
  643. }
  644.  
  645. BOOL CBitmap::Get(HDC hDC, POINT point, SIZE size)
  646. {
  647.     if (m_hDCInto != NULL || hDC == NULL)
  648.         return FALSE;
  649.  
  650.     HDC hDCInto = BeginPaintInto(hDC);
  651.     if (hDCInto == NULL)
  652.         return FALSE;
  653.  
  654.     BOOL bRet = BitBlt(hDCInto, 0, 0, size.cx, size.cy, hDC, point.x, point.y, SRCCOPY);
  655.     
  656.     EndPaintInto(hDCInto);
  657.  
  658.     return bRet;
  659. }
  660.  
  661. CBitmap *CBitmap::CreateHorzGradient(const RECT &rect, COLORREF rgbLeft, COLORREF rgbRight)
  662. {
  663.     SIZE size = GetRectSize(rect);
  664.     COLORREF rgbMid = RGB(
  665.         (int(GetRValue(rgbLeft)) + int(GetRValue(rgbRight))) / 2,
  666.         (int(GetGValue(rgbLeft)) + int(GetGValue(rgbRight))) / 2,
  667.         (int(GetBValue(rgbLeft)) + int(GetBValue(rgbRight))) / 2);
  668.     return Create(size, rgbMid);
  669. }
  670.  
  671. BOOL CBitmap::MapToDC(HDC hDCTo, HDC hDCMapFrom)
  672. {
  673.     if (hDCTo == NULL || !m_bSizeKnown || m_hDCInto != NULL)
  674.         return FALSE;
  675.  
  676.     HBITMAP hbm = CreateAppropBitmap(hDCTo, m_size.cx, m_size.cy);
  677.     if (hbm == NULL)
  678.         return FALSE;
  679.  
  680.     HDC hDCFrom = NULL;
  681.     HDC hDCInto = NULL;
  682.     HGDIOBJ hOld = NULL;
  683.     BOOL bRet = FALSE;
  684.  
  685.     hDCFrom = BeginPaintInto(hDCMapFrom);
  686.     if (!hDCFrom)
  687.         goto cleanup;
  688.  
  689.     hDCInto = CreateCompatibleDC(hDCTo);
  690.     if (!hDCInto)
  691.         goto cleanup;
  692.  
  693.     hOld = SelectObject(hDCInto, (HGDIOBJ)hbm);
  694.     bRet = BitBlt(hDCInto, 0, 0, m_size.cx, m_size.cy, hDCFrom, 0, 0, SRCCOPY);
  695.     SelectObject(hDCInto, hOld);
  696.  
  697. cleanup:
  698.     if (hDCFrom)
  699.         EndPaintInto(hDCFrom);
  700.     if (hDCInto)
  701.         DeleteDC(hDCInto);
  702.     if (bRet)
  703.     {
  704.         if (m_hbm)
  705.             DeleteObject((HGDIOBJ)m_hbm);
  706.         m_hbm = hbm;
  707.         hbm = NULL;
  708.     }
  709.     if (hbm)
  710.         DeleteObject((HGDIOBJ)hbm);
  711.  
  712.     return bRet;
  713. }
  714.