Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1465 lines
43 KiB

  1. /*************************************************************************/
  2. /* Copyright (C) 1999 Microsoft Corporation */
  3. /* File: CBitmap.cpp */
  4. /* Description: Bitmap control which supports drawing bitmaps for */
  5. /* buttons, images, etc. phillu 11/16/99 */
  6. /*************************************************************************/
  7. #include "stdafx.h"
  8. #include "CBitmap.h"
  9. // automatically generated list of bmp names and corresponding rect's.
  10. #include "bmplist.h"
  11. // initialization of static variables
  12. HBITMAP CBitmap::m_hMosaicBMP = NULL;
  13. HBITMAP CBitmap::m_hMosaicBMPOld = NULL;
  14. HPALETTE CBitmap::m_hMosaicPAL = NULL;
  15. HPALETTE CBitmap::m_hMosaicPALOld = NULL;
  16. HDC CBitmap::m_hMosaicDC = NULL;
  17. bool CBitmap::m_fLoadMosaic = true;
  18. long CBitmap::m_cBitsPerPixel = 0;
  19. long CBitmap::m_cxScreen = 0;
  20. long CBitmap::m_cyScreen = 0;
  21. // seems we need a DIB section for palettte handeling, but the Millenium one acts up
  22. #if 1
  23. #define DIB_FLAG LR_CREATEDIBSECTION
  24. #else
  25. #define DIB_FLAG 0
  26. #endif
  27. //#define USE_LOADIMAGE LoadImage does not seem to work on palette base devices
  28. #define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B')
  29. /*************************************************************************/
  30. /* Function: Init */
  31. /*************************************************************************/
  32. void CBitmap::Init(){
  33. m_hBitmap = NULL;
  34. m_hBitmapOld = NULL;
  35. m_hSrcDC = NULL;
  36. m_hPal = NULL;
  37. m_hPalOld = NULL;
  38. m_hMemDC = NULL;
  39. m_hMemBMP = NULL;
  40. m_hMemBMPOld = NULL;
  41. m_hMemPALOld = NULL;
  42. m_iMemDCWidth = 0;
  43. m_iMemDCHeight = 0;
  44. m_blitType = DISABLE;
  45. m_stretchType = NORMAL;
  46. m_fLoadPalette = false;
  47. ::SetRect(&m_rc, 0, 0, 0, 0);
  48. m_bUseMosaicBitmap = FALSE;
  49. m_hInstanceRes = NULL;
  50. }/* end of function Init */
  51. bool CBitmap::IsEmpty()
  52. {
  53. return (m_rc.top == m_rc.bottom && m_rc.left == m_rc.right);
  54. }
  55. /*************************************************************************/
  56. /* Function: CleanUp */
  57. /* Description: Destroys the objects. */
  58. /*************************************************************************/
  59. void CBitmap::CleanUp() {
  60. try {
  61. // cleanup the background image resources
  62. if (m_hBitmap){
  63. ::DeleteObject(m_hBitmap);
  64. m_hBitmap = NULL;
  65. }/* end of if statement */
  66. }
  67. catch(...){
  68. ATLASSERT(FALSE);
  69. }
  70. try {
  71. if (m_hSrcDC && !m_bUseMosaicBitmap){
  72. ::DeleteDC(m_hSrcDC);
  73. m_hSrcDC = NULL;
  74. }/* end of if statement */
  75. }
  76. catch(...){
  77. ATLASSERT(FALSE);
  78. }
  79. try {
  80. // cleanup the palette if applicable
  81. if (m_hPal){
  82. ::DeleteObject(m_hPal);
  83. m_hPal = NULL;
  84. }/* end of if statement */
  85. }
  86. catch(...){
  87. ATLASSERT(FALSE);
  88. }
  89. try {
  90. DeleteMemDC();
  91. }
  92. catch(...){
  93. ATLASSERT(FALSE);
  94. }
  95. bool fLoadPalette = m_fLoadPalette;
  96. Init();
  97. m_fLoadPalette = fLoadPalette;
  98. }/* end of function Cleanup */
  99. // this function is to clean up the mosaic bitmap
  100. // after all objects are destroyed.
  101. void CBitmap::FinalRelease()
  102. {
  103. try {
  104. if (m_hMosaicBMP){
  105. ::DeleteObject(m_hMosaicBMP);
  106. m_hMosaicBMP = NULL;
  107. }/* end of if statement */
  108. }
  109. catch(...){
  110. ATLASSERT(FALSE);
  111. }
  112. try {
  113. if (m_hMosaicDC){
  114. ::DeleteDC(m_hMosaicDC);
  115. m_hMosaicDC = NULL;
  116. }
  117. }
  118. catch(...){
  119. ATLASSERT(FALSE);
  120. }
  121. try {
  122. if (m_hMosaicPAL){
  123. ::DeleteObject(m_hMosaicPAL);
  124. m_hMosaicPAL = NULL;
  125. }
  126. }
  127. catch(...){
  128. ATLASSERT(FALSE);
  129. }
  130. return;
  131. }
  132. /*************************************************************/
  133. /* Name: CreateMemDC
  134. /* Description: Create a Mem DC
  135. /*************************************************************/
  136. BOOL CBitmap::CreateMemDC(HDC hDC, LPRECT lpDCRect)
  137. {
  138. LONG lWidth = RECTWIDTH(lpDCRect);
  139. LONG lHeight = RECTHEIGHT(lpDCRect);
  140. // clean up the old DC before we make a new one
  141. DeleteMemDC();
  142. m_hMemDC = ::CreateCompatibleDC(hDC);
  143. if(m_hMemDC == NULL)
  144. {
  145. return(FALSE);
  146. }
  147. m_iMemDCWidth = lWidth;
  148. m_iMemDCHeight = lHeight;
  149. m_hMemBMP = ::CreateCompatibleBitmap(hDC, m_iMemDCWidth, m_iMemDCHeight);
  150. if(m_hMemBMP == NULL)
  151. {
  152. ::DeleteDC(m_hMemDC);
  153. return(FALSE);
  154. }
  155. m_hMemBMPOld = (HBITMAP)::SelectObject(m_hMemDC, m_hMemBMP);
  156. HPALETTE hPal = GetPal();
  157. SelectRelizePalette(m_hMemDC, hPal, &m_hMemPALOld);
  158. // stretch and blit the src DC onto the Mem DC
  159. return TRUE;
  160. }
  161. /*************************************************************/
  162. /* Function: SelectRelizePalette */
  163. /* Description: Selects and relizes palette into a dc. */
  164. /*************************************************************/
  165. HRESULT CBitmap::SelectRelizePalette(HDC hdc, HPALETTE hPal, HPALETTE* hPalOld){
  166. if(NULL == hdc){
  167. return (E_INVALIDARG);
  168. }/* end of if statement */
  169. if(NULL == hPal){
  170. return (E_INVALIDARG);
  171. }/* end of if statement */
  172. if((::GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) == RC_PALETTE){
  173. HPALETTE hPalTmp = ::SelectPalette(hdc, hPal, FALSE);
  174. if (hPalOld) {
  175. *hPalOld = hPalTmp;
  176. }
  177. ::RealizePalette(hdc);
  178. }/* end of if statement */
  179. return S_OK;
  180. }/* end of function SelectRelizePalette */
  181. /*************************************************************/
  182. /* Name: DeleteMosaicDC
  183. /* Description:
  184. /*************************************************************/
  185. void CBitmap::DeleteMosaicDC(){
  186. try {
  187. if (m_hMosaicDC){
  188. if (m_hMosaicBMPOld)
  189. ::SelectObject(m_hMosaicDC, m_hMosaicBMPOld);
  190. if (m_hMosaicPALOld)
  191. ::SelectPalette(m_hMosaicDC, m_hMosaicPALOld, FALSE);
  192. }/* end of if statement */
  193. if (m_hMosaicBMP){
  194. ::DeleteObject(m_hMosaicBMP);
  195. m_hMosaicBMP = NULL;
  196. }/* end of if statement */
  197. if (m_hMosaicDC){
  198. ::DeleteDC(m_hMosaicDC);
  199. m_hMosaicDC = NULL;
  200. }/* end of if statement */
  201. }
  202. catch(...){
  203. ATLASSERT(FALSE);
  204. }
  205. }
  206. /*************************************************************/
  207. /* Name: OnDispChange
  208. /* Description:
  209. /*************************************************************/
  210. void CBitmap::OnDispChange(long cBitsPerPixel, long cxScreen, long cyScreen){
  211. try {
  212. if (cBitsPerPixel != m_cBitsPerPixel ||
  213. cxScreen != m_cxScreen ||
  214. cyScreen != m_cyScreen ) {
  215. m_cBitsPerPixel = cBitsPerPixel;
  216. m_cxScreen = cxScreen;
  217. m_cyScreen = cyScreen;
  218. DeleteMosaicDC();
  219. }
  220. if (m_bUseMosaicBitmap){
  221. m_hSrcDC = NULL;
  222. }
  223. else {
  224. if (m_hSrcDC) {
  225. if (NULL != m_hBitmapOld)
  226. ::SelectObject(m_hSrcDC, m_hBitmapOld);
  227. if (NULL != m_hPalOld)
  228. ::SelectPalette(m_hSrcDC, m_hPalOld, FALSE);
  229. }/* end of if statement */
  230. if (m_hBitmap) {
  231. ::DeleteObject(m_hBitmap);
  232. m_hBitmap = NULL;
  233. }/* end of if statement */
  234. if (m_hSrcDC) {
  235. ::DeleteDC(m_hSrcDC);
  236. m_hSrcDC = NULL;
  237. }/* end of if statement */
  238. } /* end of if statement */
  239. DeleteMemDC();
  240. }
  241. catch(...){
  242. ATLASSERT(FALSE);
  243. }
  244. }
  245. /*************************************************************/
  246. /* Name: DeleteMemDC
  247. /* Description:
  248. /*************************************************************/
  249. BOOL CBitmap::DeleteMemDC(){
  250. if (m_hMemDC) {
  251. if (m_hMemBMPOld)
  252. ::SelectObject(m_hMemDC, m_hMemBMPOld);
  253. if (m_hMemPALOld)
  254. ::SelectPalette(m_hMemDC, m_hMemPALOld, FALSE);
  255. } /* end of if statement */
  256. if (m_hMemBMP) {
  257. ::DeleteObject(m_hMemBMP);
  258. m_hMemBMP = NULL;
  259. } /* end of if statement */
  260. if (m_hMemDC) {
  261. ::DeleteDC(m_hMemDC);
  262. m_hMemDC = NULL;
  263. } /* end of if statement */
  264. m_iMemDCWidth = 0;
  265. m_iMemDCHeight = 0;
  266. return TRUE;
  267. }/* end of function DeleteMemDC */
  268. /*************************************************************************
  269. This is a special stretching method for stretching the backgound bitmap
  270. of container. The goal is to enlarge the bitmap without stretching, so as
  271. to maintain the border width of the container. This is accomplished
  272. by replicating portions of the bitmap on the 4 sides.
  273. ************************************************************************/
  274. BOOL CBitmap::CustomContainerStretch(HDC hDC, RECT* lpRect)
  275. {
  276. LONG lSectionWidth = (min(RECTWIDTH(lpRect), RECTWIDTH(&m_rc)) + 1)/2;
  277. LONG lSectionHeight = (min(RECTHEIGHT(lpRect), RECTHEIGHT(&m_rc)) + 1)/2;
  278. // copy upper left quadrant
  279. ::BitBlt(hDC,
  280. lpRect->left,
  281. lpRect->top,
  282. lSectionWidth,
  283. lSectionHeight,
  284. m_hSrcDC,
  285. m_rc.left,
  286. m_rc.top,
  287. SRCCOPY);
  288. // copy upper right quadrant
  289. ::BitBlt(hDC,
  290. lpRect->right - lSectionWidth,
  291. lpRect->top,
  292. lSectionWidth,
  293. lSectionHeight,
  294. m_hSrcDC,
  295. m_rc.right - lSectionWidth,
  296. m_rc.top,
  297. SRCCOPY);
  298. // copy lower left quadrant
  299. ::BitBlt(hDC,
  300. lpRect->left,
  301. lpRect->bottom - lSectionHeight,
  302. lSectionWidth,
  303. lSectionHeight,
  304. m_hSrcDC,
  305. m_rc.left,
  306. m_rc.bottom - lSectionHeight,
  307. SRCCOPY);
  308. // copy lower right quadrant
  309. ::BitBlt(hDC,
  310. lpRect->right - lSectionWidth,
  311. lpRect->bottom - lSectionHeight,
  312. lSectionWidth,
  313. lSectionHeight,
  314. m_hSrcDC,
  315. m_rc.right - lSectionWidth,
  316. m_rc.bottom - lSectionHeight,
  317. SRCCOPY);
  318. // fill in the middle section
  319. LONG lGapWidth = RECTWIDTH(lpRect) - 2*lSectionWidth;
  320. LONG lGapHeight = RECTHEIGHT(lpRect) - 2*lSectionHeight;
  321. LONG lHorizFillStart = lpRect->left + lSectionWidth;
  322. LONG lVertFillStart = lpRect->top + lSectionHeight;
  323. // define a chunk of bitmap that can be used to fill the gap
  324. const LONG lSrcXOffset = 60;
  325. const LONG lSrcYOffset = 60;
  326. const LONG lMaxHorizontalFill = RECTWIDTH(&m_rc) - 2*lSrcXOffset;
  327. const LONG lMaxVerticalFill = RECTHEIGHT(&m_rc) - 3*lSrcYOffset; // twice room at bottom
  328. while (lGapWidth > 0)
  329. {
  330. // upper middle section
  331. LONG lFillWidth = min(lGapWidth, lMaxHorizontalFill);
  332. ::BitBlt(hDC,
  333. lHorizFillStart,
  334. lpRect->top,
  335. lFillWidth,
  336. lSectionHeight,
  337. m_hSrcDC,
  338. m_rc.left + lSrcXOffset,
  339. m_rc.top,
  340. SRCCOPY);
  341. // bottom middle section
  342. ::BitBlt(hDC,
  343. lHorizFillStart,
  344. lpRect->bottom - lSectionHeight,
  345. lFillWidth,
  346. lSectionHeight,
  347. m_hSrcDC,
  348. m_rc.left + lSrcXOffset,
  349. m_rc.bottom - lSectionHeight,
  350. SRCCOPY);
  351. lGapWidth -= lFillWidth;
  352. lHorizFillStart += lFillWidth;
  353. }
  354. while (lGapHeight > 0)
  355. {
  356. // left middle section
  357. LONG lFillHeight = min(lGapHeight, lMaxVerticalFill);
  358. ::BitBlt(hDC,
  359. lpRect->left,
  360. lVertFillStart,
  361. lSectionWidth,
  362. lFillHeight,
  363. m_hSrcDC,
  364. m_rc.left,
  365. m_rc.top + lSrcYOffset,
  366. SRCCOPY);
  367. // right middle section
  368. ::BitBlt(hDC,
  369. lpRect->right - lSectionWidth,
  370. lVertFillStart,
  371. lSectionWidth,
  372. lFillHeight,
  373. m_hSrcDC,
  374. m_rc.right - lSectionWidth,
  375. m_rc.top + lSrcYOffset,
  376. SRCCOPY);
  377. lGapHeight -= lFillHeight;
  378. lVertFillStart += lFillHeight;
  379. }
  380. return TRUE;
  381. }/* end of function SpecialStretch */
  382. /*************************************************************************
  383. This stretching methods maintains the aspect ratio of the original bitmap.
  384. The unoccupied portion of the dest DC will be filled with BackColor.
  385. **************************************************************************/
  386. BOOL CBitmap::StretchKeepAspectRatio(HDC hDC, LPRECT lpRect)
  387. {
  388. BOOL bSuccess = TRUE;
  389. LONG lWidth = RECTWIDTH(lpRect);
  390. LONG lHeight = RECTHEIGHT(lpRect);
  391. LONG lWidthSrc = RECTWIDTH(&m_rc);
  392. LONG lHeightSrc = RECTHEIGHT(&m_rc);
  393. HBRUSH hbrBack = (HBRUSH)::GetStockObject(BLACK_BRUSH);
  394. if(NULL == hbrBack){
  395. return(FALSE);
  396. }/* end of if statement */
  397. ::FillRect(hDC, lpRect, hbrBack);
  398. ::DeleteObject(hbrBack);
  399. if (lWidth*lHeightSrc < lHeight*lWidthSrc)
  400. {
  401. LONG lStretchHeight = (LONG)((float)lHeightSrc*lWidth/lWidthSrc + 0.5f);
  402. LONG lGapHeight = (lHeight - lStretchHeight)/2;
  403. bSuccess = ::StretchBlt(hDC,
  404. lpRect->left, // DestX
  405. lpRect->top + lGapHeight, // DestY
  406. lWidth, // nDestWidth
  407. lStretchHeight, // nDestHeight
  408. m_hSrcDC,
  409. m_rc.left, // SrcX
  410. m_rc.top, // SrcY
  411. lWidthSrc, // nSrcWidth
  412. lHeightSrc, // nSrcHeight
  413. SRCCOPY
  414. );
  415. }
  416. else
  417. {
  418. LONG lStretchWidth = (LONG)((float)lWidthSrc*lHeight/lHeightSrc + 0.5f);
  419. LONG lGapWidth = (lWidth - lStretchWidth)/2;
  420. bSuccess = ::StretchBlt(hDC,
  421. lpRect->left + lGapWidth, // DestX
  422. lpRect->top, // DestY
  423. lStretchWidth, // nDestWidth
  424. lHeight, // nDestHeight
  425. m_hSrcDC,
  426. m_rc.left, // SrcX
  427. m_rc.top, // SrcY
  428. lWidthSrc, // nSrcWidth
  429. lHeightSrc, // nSrcHeight
  430. SRCCOPY
  431. );
  432. }
  433. return bSuccess;
  434. }
  435. /*************************************************************************
  436. This is the entry point to stretch paint the bitmap
  437. m_stretchType indicates the type of stretching method to use:
  438. NORMAL = 0 : normal stretching
  439. CUSTOM_CONTAINER = 1 : special stretching method for container
  440. MAINTAIN_ASPECT_RATIO =2 : stretching while maintaing aspect ratio
  441. **************************************************************************/
  442. BOOL CBitmap::StretchPaint(HDC hDC, LPRECT lpRect, COLORREF clrTrans)
  443. {
  444. BOOL bSuccess = TRUE;
  445. LONG lWidth = RECTWIDTH(lpRect);
  446. LONG lHeight = RECTHEIGHT(lpRect);
  447. LONG lWidthSrc = RECTWIDTH(&m_rc);
  448. LONG lHeightSrc = RECTHEIGHT(&m_rc);
  449. // special case, src and dest rects are the same, just copy it
  450. if (lWidth == lWidthSrc && lHeight == lHeightSrc)
  451. {
  452. bSuccess = ::BitBlt(hDC,
  453. lpRect->left, // DestX
  454. lpRect->top, // DestY
  455. lWidth, // nDestWidth
  456. lHeight, // nDestHeight
  457. m_hSrcDC,
  458. m_rc.left, // SrcX
  459. m_rc.top, // SrcY
  460. SRCCOPY
  461. );
  462. }
  463. else if (m_stretchType == CUSTOM_CONTAINER)
  464. {
  465. bSuccess = CustomContainerStretch(hDC, lpRect);
  466. }
  467. else if (m_stretchType == MAINTAIN_ASPECT_RATIO)
  468. {
  469. bSuccess = StretchKeepAspectRatio(hDC, lpRect);
  470. }
  471. else // normal stretch
  472. {
  473. #if 1
  474. // to ensure the transparent color is maintained, we first
  475. // fill the DC with the transparent color, and then do a
  476. // TransparentBlit. The resulting bitmap can be used for
  477. // transparent blting again.
  478. HBRUSH hbrTrans = ::CreateSolidBrush(clrTrans);
  479. if(NULL == hbrTrans){
  480. bSuccess = FALSE;
  481. return(bSuccess);
  482. }/* end of if statement */
  483. ::FillRect(hDC, lpRect, hbrTrans);
  484. ::DeleteObject(hbrTrans);
  485. #endif
  486. bSuccess = ::TransparentBlt(hDC,
  487. lpRect->left, // DestX
  488. lpRect->top, // DestY
  489. lWidth, // nDestWidth
  490. lHeight, // nDestHeight
  491. m_hSrcDC,
  492. m_rc.left, // SrcX
  493. m_rc.top, // SrcY
  494. lWidthSrc, // nSrcWidth
  495. lHeightSrc, // nSrcHeight
  496. clrTrans
  497. );
  498. }
  499. return bSuccess;
  500. }
  501. /*******************************************************************
  502. Create the Src DC if it has not been done so before.
  503. If the current object uses the mosaic, the src DC is just a copy
  504. of the mosaic DC.
  505. ********************************************************************/
  506. BOOL CBitmap::CreateSrcDC(HDC hDC)
  507. {
  508. // Src DC is already created from a previous call
  509. if (m_hSrcDC != NULL)
  510. {
  511. return TRUE;
  512. }
  513. if (m_bUseMosaicBitmap)
  514. {
  515. if (m_hMosaicDC == NULL)
  516. {
  517. if (m_hMosaicBMP == NULL)
  518. {
  519. HRESULT hr = InitilizeMosaic(m_hInstanceRes);
  520. if (FAILED(hr) || m_hMosaicBMP == NULL)
  521. return FALSE;
  522. }
  523. m_hMosaicDC = ::CreateCompatibleDC(hDC);
  524. if(NULL == m_hMosaicDC){
  525. return(FALSE);
  526. }/* end of if statement */
  527. m_hMosaicBMPOld = (HBITMAP)::SelectObject(m_hMosaicDC, m_hMosaicBMP);
  528. HPALETTE hPal = GetPal();
  529. SelectRelizePalette(m_hMosaicDC, hPal, &m_hMosaicPALOld);
  530. }
  531. m_hSrcDC = m_hMosaicDC;
  532. }
  533. else
  534. {
  535. if (m_hBitmap == NULL){
  536. HRESULT hr = LoadImageFromRes(m_strFileName, m_hInstanceRes);
  537. if (FAILED(hr) || m_hBitmap == NULL)
  538. return FALSE;
  539. }/* end of if statement */
  540. m_hSrcDC = ::CreateCompatibleDC(hDC);
  541. if(NULL == m_hSrcDC){
  542. return FALSE;
  543. }/* end of if statement */
  544. m_hBitmapOld = (HBITMAP)::SelectObject(m_hSrcDC, m_hBitmap);
  545. HPALETTE hPal = GetPal();
  546. SelectRelizePalette(m_hSrcDC, hPal, &m_hPalOld);
  547. }
  548. if (m_hSrcDC == NULL)
  549. {
  550. return FALSE;
  551. }
  552. return TRUE;
  553. }
  554. /*************************************************************************
  555. GetTransparentColor()
  556. **************************************************************************/
  557. COLORREF CBitmap::GetTransparentColor()
  558. {
  559. // retrieve transparent color according to type, default is magenta
  560. COLORREF clrTrans = RGB(255, 0, 255);
  561. if(TRANSPARENT_TOP_LEFT == m_blitType ||
  562. TOP_LEFT_WITH_BACKCOLOR == m_blitType ||
  563. TOP_LEFT_WINDOW_REGION == m_blitType )
  564. {
  565. clrTrans = ::GetPixel(m_hSrcDC, m_rc.left, m_rc.top);
  566. }
  567. else if(TRANSPARENT_BOTTOM_RIGHT == m_blitType ||
  568. BOTTOM_RIGHT_WITH_BACKCOLOR == m_blitType ||
  569. BOTTOM_RIGHT_WINDOW_REGION == m_blitType )
  570. {
  571. clrTrans = ::GetPixel(m_hSrcDC, m_rc.right-1, m_rc.bottom-1);
  572. }
  573. #if 0
  574. // in case we are pallete capable device find the color in our palette
  575. HPALETTE hPal = GetPal();
  576. if(hPal){
  577. HWND hwnd = ::GetDesktopWindow();
  578. HDC hdc = ::GetWindowDC(hwnd);
  579. if((::GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) == RC_PALETTE){
  580. UINT clrTmp = GetNearestPaletteIndex(hPal, clrTrans);
  581. if(CLR_INVALID != clrTmp){
  582. clrTrans = PALETTEINDEX(clrTmp);
  583. }/* end of if statement */
  584. }/* end of if statement */
  585. ::ReleaseDC(hwnd, hdc);
  586. }/* end of if statement */
  587. #endif
  588. return clrTrans;
  589. }
  590. /*************************************************************************
  591. PaintTransparentDIB is the main function call to draw the bitmap control.
  592. Before PaintTransparentDIB is called, the bitmap should have been loaded by
  593. PutImage(). Also the blitType and stretchType should have been set during
  594. the PutImage call.
  595. Input parameters:
  596. hDC is the DC to paint the bitmap to
  597. lpDCWRect is the rect of the entire control window. We should privide that
  598. for buttons as well as container.
  599. lpDCRect is the current rect to paint to. For container, it could be a sub
  600. region of the lpDCWRect. For buttons, it is probably the same as
  601. the lpDCWRect. (However this function does not rely on this assumption.)
  602. Important data structures:
  603. m_hSrcDC is the DC that contains the original bitmap (unstretched).
  604. If the current object uses the mosaic bitmap, m_hSrcDC is just a copy
  605. of the m_hMosaicDC while m_rc keeps the location of the bitmap within
  606. the mosaic.
  607. m_hMemDC caches a copy of the bitmap that is stretched to the window size.
  608. This is used for quickly refreshing display if only portion of the screen
  609. needs to be painted.
  610. ************************************************************************/
  611. BOOL CBitmap::PaintTransparentDIB(HDC hDC,
  612. LPRECT lpDCWRect,
  613. LPRECT lpDCRect)
  614. {
  615. BOOL bSuccess = TRUE;
  616. // create the src DC if we are first time here.
  617. // But we should already have the bitmap in memory
  618. if (!CreateSrcDC(hDC))
  619. {
  620. return FALSE;
  621. }
  622. // Color in the bitmap that indicates transparent pixel
  623. COLORREF clrTrans = GetTransparentColor();
  624. // check if we already have the stretched bitmap cached in mem DC
  625. // if not, create the MemDC and paint the stretched bitmap in it
  626. LONG lWidth = RECTWIDTH(lpDCWRect);
  627. LONG lHeight = RECTHEIGHT(lpDCWRect);
  628. RECT rc = {0, 0, lWidth, lHeight};
  629. if (!m_hMemDC || lWidth != m_iMemDCWidth || lHeight != m_iMemDCHeight)
  630. {
  631. if (!CreateMemDC(hDC, &rc))
  632. {
  633. return FALSE;
  634. }
  635. if (!StretchPaint(m_hMemDC, &rc, clrTrans))
  636. {
  637. return FALSE;
  638. }
  639. }
  640. // blit MemDC to screen DC with transparency.
  641. // Only the required DC Rect is painted (it could be a subregion of DCWRect)
  642. LONG lPaintWidth = RECTWIDTH(lpDCRect);
  643. LONG lPaintHeight = RECTHEIGHT(lpDCRect);
  644. if (m_blitType != DISABLE)
  645. {
  646. bSuccess = ::TransparentBlt(hDC,
  647. lpDCRect->left, // DestX
  648. lpDCRect->top, // DestY
  649. lPaintWidth, // nDestWidth
  650. lPaintHeight, // nDestHeight
  651. m_hMemDC,
  652. lpDCRect->left - lpDCWRect->left, // SrcX
  653. lpDCRect->top - lpDCWRect->top, // SrcY
  654. lPaintWidth, // nSrcWidth
  655. lPaintHeight, // nSrcHeight
  656. clrTrans // transparent color
  657. );
  658. }
  659. else // disabled, no transparency
  660. {
  661. bSuccess = ::BitBlt(hDC,
  662. lpDCRect->left, // DestX
  663. lpDCRect->top, // DestY
  664. lPaintWidth, // nDestWidth
  665. lPaintHeight, // nDestHeight
  666. m_hMemDC,
  667. lpDCRect->left - lpDCWRect->left, // SrcX
  668. lpDCRect->top - lpDCWRect->top, // SrcY
  669. SRCCOPY
  670. );
  671. }
  672. return bSuccess;
  673. }
  674. /*************************************************************************
  675. PutImage()
  676. If bFromMosaic is FALSE, it loads a bitmap from either a disk BMP file
  677. or from a BITMAP resource (depending on if hRes is NULL or not).
  678. If bFromMosaic is TRUE, it records a rect region of a mosaic bitmap as
  679. the bitmap for the current object. The mosaic bitmap itself can be loaded
  680. from a disk BMP file or from a BITMAP resource (depending on if hRes is
  681. NULL or not). But this mosaic bitmap is loaded only once for all the
  682. objects that are sharing the mosaic. Loading from file or resource must
  683. be consistent among all those objects.
  684. The resource tag name or file name of the mosaic bitmap is currently
  685. hard coded (as IDR_MOSAIC_BMP or mosaicbm.bmp).
  686. This call also record the blit type and stretch type which indicate how
  687. the bitmap is to be painted.
  688. blitType:
  689. DISABLE = 0 : Disabled, no transparency
  690. TRANSPARENT_TOP_LEFT = 1: use clr of top left pix as transparent color
  691. TRANSPARENT_BOTTOM_RIGHT = 2: use clr of bottom right as transparent color
  692. TOP_LEFT_WINDOW_REGION = 3: currently treated as the same as 1
  693. BOTTOM_RIGHT_WINDOW_REGION = 4: currently treated as the same as 2
  694. TOP_LEFT_WITH_BACKCOLOR = 5: currently treated as the same as 1
  695. BOTTOM_RIGHT_WITH_BACKCOLOR = 6: currently treated as the same as 2
  696. stretchType:
  697. NORMAL = 0 : normal stretching
  698. CUSTOM_CONTAINER = 1 : special stretching method for container
  699. MAINTAIN_ASPECT_RATIO : stretching while maintaing aspect ratio
  700. *************************************************************************/
  701. HRESULT CBitmap::PutImage(BSTR strFilename, HINSTANCE hRes,
  702. BOOL bFromMosaic, // the bitmap is in Mosaic bitmap
  703. TransparentBlitType blitType,
  704. StretchType stretchType
  705. )
  706. {
  707. USES_CONVERSION;
  708. HRESULT hr = S_OK;
  709. CleanUp();
  710. // save the blit and stretch types
  711. m_blitType = blitType;
  712. m_stretchType = stretchType;
  713. m_bUseMosaicBitmap = bFromMosaic;
  714. m_strFileName = strFilename;
  715. m_hInstanceRes = hRes;
  716. // initialize the mosaic file
  717. HRESULT hrTmp = InitilizeMosaic(hRes);
  718. if(FAILED(hrTmp)){
  719. // try to load up the file as a normal file or resource since mosaic load failed
  720. m_bUseMosaicBitmap = FALSE;
  721. }/* end of if statement */
  722. if (!LookupBitmapRect(OLE2T(strFilename), &m_rc))
  723. {
  724. // load individual bitmap from resource or file
  725. m_bUseMosaicBitmap = FALSE;
  726. }
  727. if (!m_bUseMosaicBitmap) {
  728. hr = LoadImageFromRes(m_strFileName, m_hInstanceRes);
  729. }
  730. return hr;
  731. }/* end of function PutImage */
  732. /*************************************************************/
  733. /* Name: LoadImageFromRes
  734. /* Description:
  735. /*************************************************************/
  736. HRESULT CBitmap::LoadImageFromRes(BSTR strFileName, HINSTANCE hRes) {
  737. USES_CONVERSION;
  738. HRESULT hr = S_OK;
  739. BITMAP bm;
  740. TCHAR* strTmpFileName = TEXT("");
  741. strTmpFileName = OLE2T(strFileName);
  742. m_hBitmap = (HBITMAP)LoadImage(hRes, strTmpFileName, IMAGE_BITMAP, 0, 0,
  743. DIB_FLAG | LR_DEFAULTSIZE | (hRes?0:LR_LOADFROMFILE));
  744. if(NULL == m_hBitmap)
  745. {
  746. hr = HRESULT_FROM_WIN32(::GetLastError());
  747. return hr;
  748. }
  749. ::GetObject(m_hBitmap, sizeof(BITMAP), (LPVOID) &bm);
  750. ::SetRect(&m_rc, 0, 0, bm.bmWidth, bm.bmHeight);
  751. return hr;
  752. }/* end of function LoadImageFromRes */
  753. /************************************************************************/
  754. /* Function: InitilizeMosaic */
  755. /* Description: Trys to load up the mosaic bitmap, which contains a */
  756. /* collection of bitmaps. */
  757. /************************************************************************/
  758. HRESULT CBitmap::InitilizeMosaic(HINSTANCE hRes){
  759. HRESULT hr = S_OK;
  760. TCHAR* strTmpFileName = TEXT("");
  761. // use a rectangular region of Mosaic bitmap
  762. // make sure the mosaic only loads once for all the objects
  763. if (m_hMosaicBMP == NULL){
  764. if(!m_fLoadMosaic){
  765. hr = E_FAIL; // we already failed before to load the mosaic file do not
  766. //try it again
  767. return(hr);
  768. }/* end of if statement */
  769. if (hRes)
  770. {
  771. // load mosaic bitmap
  772. strTmpFileName = TEXT("IDR_MOSAIC_BMP");
  773. hr = LoadPalette(strTmpFileName, hRes, &m_hMosaicPAL);
  774. if(FAILED(hr)){
  775. m_fLoadMosaic = false;
  776. return(hr);
  777. }/* end of if statement */
  778. m_hMosaicBMP = (HBITMAP)LoadImage(hRes, strTmpFileName, IMAGE_BITMAP, 0, 0,
  779. DIB_FLAG| LR_DEFAULTSIZE);
  780. }
  781. else
  782. {
  783. strTmpFileName = TEXT("mosaicbm.bmp");
  784. hr = LoadPalette(strTmpFileName, hRes, &m_hMosaicPAL);
  785. if(FAILED(hr)){
  786. m_fLoadMosaic = false;
  787. return(hr);
  788. }/* end of if statement */
  789. m_hMosaicBMP = (HBITMAP)LoadImage(hRes, strTmpFileName, IMAGE_BITMAP, 0, 0,
  790. DIB_FLAG| LR_LOADFROMFILE);
  791. }
  792. if(NULL == m_hMosaicBMP)
  793. {
  794. hr = HRESULT_FROM_WIN32(::GetLastError());
  795. m_fLoadMosaic = false; // do not attempt to reload the mosaic file
  796. return hr;
  797. }
  798. }/* end of if statement */
  799. return(hr);
  800. }/* function InitilizeMosaic */
  801. /************************************************************************/
  802. /* Function: LoadPalette */
  803. /* Description: Loads a palette from a bitmap. */
  804. /************************************************************************/
  805. HRESULT CBitmap::LoadPalette(TCHAR* strFilename, HINSTANCE hRes){
  806. return(LoadPalette(strFilename, hRes, &m_hPal));
  807. }/* end of function LoadPalette */
  808. /************************************************************************/
  809. /* Function: LoadPalette */
  810. /* Description: Loads a palette from a bitmap. */
  811. /************************************************************************/
  812. HRESULT CBitmap::LoadPalette(TCHAR* strFilename, HINSTANCE hInst, HPALETTE *phPal){
  813. HRESULT hr = S_OK;
  814. if(NULL == phPal){
  815. hr = E_POINTER;
  816. return(hr);
  817. }/* end of if statement */
  818. if (*phPal){
  819. ::DeleteObject(*phPal);
  820. *phPal = NULL;
  821. }/* end of if statement */
  822. #ifdef USE_LOADIMAGE
  823. BITMAP bm;
  824. // Use LoadImage() to get the image loaded into a DIBSection
  825. HBITMAP hBitmap = (HBITMAP) ::LoadImage( hInst, strFilename, IMAGE_BITMAP, 0, 0,
  826. LR_CREATEDIBSECTION| LR_DEFAULTSIZE | (hInst?LR_DEFAULTCOLOR:LR_LOADFROMFILE) );
  827. if( hBitmap == NULL ){
  828. hr = HRESULT_FROM_WIN32(::GetLastError());
  829. return hr;
  830. }/* end of if statement */
  831. // Get the color depth of the DIBSection
  832. ::GetObject(hBitmap, sizeof(BITMAP), &bm );
  833. // If the DIBSection is 256 color or less, it has a color table
  834. if( ( bm.bmBitsPixel * bm.bmPlanes ) <= 8 ){
  835. HDC hMemDC;
  836. HBITMAP hOldBitmap;
  837. RGBQUAD rgb[256];
  838. LPLOGPALETTE pLogPal;
  839. WORD i;
  840. // Create a memory DC and select the DIBSection into it
  841. hMemDC = ::CreateCompatibleDC( NULL );
  842. hOldBitmap = (HBITMAP)::SelectObject( hMemDC, hBitmap );
  843. // Get the DIBSection's color table
  844. UINT ulNumEntries =::GetDIBColorTable( hMemDC, 0, 256, rgb );
  845. // Create a palette from the color table
  846. LPLOGPALETTE pLogPal = (LPLOGPALETTE) new BYTE[( sizeof(LOGPALETTE) + (ncolors*sizeof(PALETTEENTRY)))];
  847. //pLogPal = (LPLOGPALETTE) malloc( sizeof(LOGPALETTE) + (ulNumEntries*sizeof(PALETTEENTRY)) );
  848. if(NULL == pLogPal){
  849. return(E_OUTOFMEMORY);
  850. }/* end of if statement */
  851. pLogPal->palVersion = 0x300;
  852. pLogPal->palNumEntries = (WORD) ulNumEntries;
  853. for(i=0;i<ulNumEntries;i++){
  854. pLogPal->palPalEntry[i].peRed = rgb[i].rgbRed;
  855. pLogPal->palPalEntry[i].peGreen = rgb[i].rgbGreen;
  856. pLogPal->palPalEntry[i].peBlue = rgb[i].rgbBlue;
  857. pLogPal->palPalEntry[i].peFlags = 0; /* PC_RESERVED */ /* 0 */
  858. }/* end of for loop */
  859. *phPal = ::CreatePalette( pLogPal );
  860. if( *phPal == NULL ){
  861. hr = HRESULT_FROM_WIN32(::GetLastError());
  862. }/* end of if statement */
  863. // Clean up
  864. delete[] pLogPal;
  865. ::SelectObject( hMemDC, hOldBitmap );
  866. ::DeleteObject(hBitmap);
  867. ::DeleteDC( hMemDC );
  868. }
  869. else // It has no color table, so use a halftone palette
  870. {
  871. hr = S_FALSE;
  872. }/* end of if statement */
  873. #else
  874. // use our internal load image so we do not duplicate the code
  875. LoadImage(hInst, strFilename, IMAGE_BITMAP, 0, 0, (hInst?LR_DEFAULTCOLOR:LR_LOADFROMFILE), phPal);
  876. if(NULL == *phPal){
  877. hr = E_FAIL;
  878. }/* end of if statement */
  879. #endif
  880. return(hr);
  881. }/* end of function LoadPalette */
  882. /************************************************************************
  883. Lookup the rectangle coordinates of a bitmap which is subregion of
  884. the mosaic. The list of coordinates and associated names are compiled
  885. at the same time as the mosaic bitmap.
  886. *************************************************************************/
  887. BOOL CBitmap::LookupBitmapRect(LPTSTR szName, LPRECT rect)
  888. {
  889. USES_CONVERSION;
  890. char *strIDR = T2A(szName);
  891. BmpRectRef *p = gBmpRectList;
  892. while (p->strIDR)
  893. {
  894. if (strcmp(p->strIDR, strIDR) == 0)
  895. {
  896. *rect = p->rect;
  897. return TRUE;
  898. }
  899. p++;
  900. }
  901. return FALSE;
  902. }
  903. /*************************************************************************/
  904. /* Function: LoadImage */
  905. /* Description: Either uses our load image or the OS LoadImage */
  906. /*************************************************************************/
  907. HANDLE CBitmap::LoadImage(HINSTANCE hInst, LPCTSTR lpszName, UINT uType,
  908. int cxDesired, int cyDesired, UINT fuLoad,
  909. HPALETTE *phPal){
  910. HANDLE hBitmap = NULL;
  911. HGLOBAL hBmpFile = NULL;
  912. HANDLE hFile = NULL;
  913. BYTE* lpCurrent = NULL;
  914. BYTE* lpDelete = NULL;
  915. try {
  916. #ifdef USE_LOADIMAGE
  917. hBitmap = ::LoadImage(hInst, lpszName, uType, cxDesired, cyDesired,
  918. fuLoad);
  919. #else
  920. bool fPaletteOnly = false;
  921. if(NULL != phPal){
  922. fPaletteOnly = true;
  923. *phPal = NULL;
  924. }/* end of if statement */
  925. UINT ncolors = 0;
  926. DWORD dwBitsSize = 0;
  927. DWORD dwOffset = 0;
  928. if(fuLoad & LR_LOADFROMFILE){
  929. hFile = ::CreateFile(
  930. lpszName, // pointer to name of the file
  931. GENERIC_READ, // access (read-write) mode
  932. FILE_SHARE_READ, // share mode
  933. NULL, // pointer to security descriptor
  934. OPEN_EXISTING, // how to create
  935. FILE_ATTRIBUTE_NORMAL, // file attributes
  936. NULL // handle to file with attributes to copy
  937. );
  938. if(hFile == INVALID_HANDLE_VALUE){
  939. #if _DEBUG
  940. if(!fPaletteOnly){
  941. TCHAR strBuffer[MAX_PATH + 25];
  942. wsprintf(strBuffer, TEXT("Failed to download %s"), lpszName);
  943. ::MessageBox(::GetFocus(), strBuffer, TEXT("Error"), MB_OK);
  944. }/* end of if statement */
  945. #endif
  946. throw (NULL);
  947. }/* end of if statement */
  948. dwBitsSize = GetFileSize(hFile,NULL);
  949. if(0 >= dwBitsSize){
  950. ATLASSERT(FALSE);
  951. throw (NULL);
  952. }/* end of if statement */
  953. BITMAPFILEHEADER bmfHeader;
  954. DWORD nBytesRead;
  955. if(! ReadFile(hFile, (LPSTR)&bmfHeader, sizeof(bmfHeader), &nBytesRead, NULL)){
  956. ATLASSERT(FALSE);
  957. throw (NULL);
  958. }/* end of if statement */
  959. if(sizeof(bmfHeader) != nBytesRead){
  960. ATLASSERT(FALSE);
  961. throw (NULL);
  962. }/* end of if statement */
  963. if (bmfHeader.bfType != DIB_HEADER_MARKER){
  964. ATLASSERT(FALSE);
  965. throw (NULL);
  966. }/* end of if statement */
  967. dwBitsSize -= sizeof(BITMAPFILEHEADER);
  968. lpCurrent = lpDelete = new BYTE[dwBitsSize];
  969. if(NULL == lpDelete){
  970. ATLASSERT(FALSE);
  971. throw(NULL);
  972. }/* end of if stament */
  973. if(!ReadFile(hFile, (LPSTR)lpCurrent, dwBitsSize, &nBytesRead, NULL)){
  974. ATLASSERT(FALSE);
  975. throw (NULL);
  976. }/* end of if statement */
  977. if(nBytesRead != dwBitsSize){
  978. ATLASSERT(FALSE);
  979. throw (NULL);
  980. }/* end of if statement */
  981. ::CloseHandle(hFile);
  982. hFile = NULL;
  983. }
  984. else {
  985. // loading from resources
  986. // Find the Bitmap
  987. HRSRC hRes = ::FindResource(hInst, lpszName, RT_BITMAP);
  988. if (!hRes){
  989. ATLASSERT(FALSE);
  990. throw (NULL);
  991. }/* end of if statement */
  992. // Load the BMP from the resource file.
  993. hBmpFile = ::LoadResource(hInst, hRes);
  994. if ((!hBmpFile)){
  995. ATLASSERT(FALSE);
  996. throw (NULL);
  997. }/* end of if statement */
  998. dwBitsSize = ::SizeofResource(hInst, hRes);
  999. // copy out the appropriate info from the bitmap
  1000. lpCurrent = (BYTE *)::LockResource(hBmpFile);
  1001. }/* end of if statement */
  1002. // The BITMAPFILEHEADER is striped for us, so we just start with a BITMAPINFOHEADER
  1003. BITMAPINFOHEADER* lpbmih = (BITMAPINFOHEADER *)lpCurrent;
  1004. lpCurrent += sizeof(BITMAPINFOHEADER);
  1005. dwOffset = sizeof(BITMAPINFOHEADER);
  1006. // Compute some usefull information from the bitmap
  1007. if (lpbmih->biPlanes != 1){
  1008. ATLASSERT(FALSE);
  1009. throw (NULL);
  1010. }/* end of if statement */
  1011. if ( lpbmih->biBitCount != 1
  1012. && lpbmih->biBitCount != 4
  1013. && lpbmih->biBitCount != 8
  1014. && lpbmih->biBitCount != 16
  1015. && lpbmih->biBitCount != 24
  1016. && lpbmih->biBitCount != 32){
  1017. ATLASSERT(FALSE);
  1018. throw (NULL);
  1019. }/* end of if statement */
  1020. if (lpbmih->biBitCount <= 8){
  1021. ncolors = 1 << lpbmih->biBitCount;
  1022. if (lpbmih->biClrUsed > 0 && lpbmih->biClrUsed < ncolors){
  1023. ncolors = lpbmih->biClrUsed;
  1024. }/* end of if statement */
  1025. }/* end of if statemet */
  1026. RGBQUAD* lprgb = NULL;
  1027. //HPALETTE m_hPal = NULL;
  1028. if (ncolors){
  1029. bool fLoadPalette = m_fLoadPalette || fPaletteOnly;
  1030. if(fLoadPalette){
  1031. WORD i;
  1032. LPLOGPALETTE pLogPal = (LPLOGPALETTE) new BYTE[( sizeof(LOGPALETTE) + (ncolors*sizeof(PALETTEENTRY)))];
  1033. if(NULL == pLogPal){
  1034. ATLASSERT(FALSE);
  1035. throw (NULL);
  1036. }/* end of if statement */
  1037. pLogPal->palVersion = 0x300;
  1038. pLogPal->palNumEntries = (WORD) ncolors;
  1039. lprgb = (RGBQUAD *)lpCurrent;
  1040. for(i=0;i<ncolors;i++){
  1041. pLogPal->palPalEntry[i].peRed = lprgb[i].rgbRed;
  1042. pLogPal->palPalEntry[i].peGreen = lprgb[i].rgbGreen;
  1043. pLogPal->palPalEntry[i].peBlue = lprgb[i].rgbBlue;
  1044. pLogPal->palPalEntry[i].peFlags = 0; /* PC_RESERVED */ /* 0 */
  1045. }/* end of for loop */
  1046. if(!fPaletteOnly){
  1047. m_hPal = ::CreatePalette( pLogPal );
  1048. }
  1049. else {
  1050. *phPal = ::CreatePalette( pLogPal );
  1051. }/* end of if statement */
  1052. // Clean up
  1053. delete[] pLogPal;
  1054. }/* end of if statement */
  1055. // here is the place to load up palette more eficiently
  1056. lpCurrent += ncolors * sizeof(RGBQUAD);
  1057. dwOffset += ncolors * sizeof(RGBQUAD);
  1058. }/* end of if statement */
  1059. if(!fPaletteOnly){
  1060. BYTE* pBits = NULL;
  1061. typedef struct tagBITMAPINFOMAX {
  1062. BITMAPINFOHEADER bmiHeader;
  1063. RGBQUAD bmiColors[256];
  1064. } BITMAPINFOMAX;
  1065. BITMAPINFOMAX bmi; // temporary bitmap info header so we can modify it a bit
  1066. ::CopyMemory(&bmi, lpbmih, sizeof(BITMAPINFOHEADER) + ncolors * sizeof(RGBQUAD));
  1067. DWORD dwCompression = lpbmih->biCompression;
  1068. bmi.bmiHeader.biCompression = BI_RGB; // DIB Section does not like RLE
  1069. //bmi.bmiHeader.biBitCount = 32;
  1070. // update to DIB_RGB_COLORS or DIB_PAL_COLORS Colors
  1071. HDC hdcScreen = ::GetDC(NULL);
  1072. hBitmap = ::CreateDIBSection(hdcScreen, (BITMAPINFO*)&bmi, DIB_RGB_COLORS, (LPVOID*) &pBits, NULL, 0);
  1073. //hBitmap = ::CreateDIBSection(hdc, (BITMAPINFO*)lpbmih, DIB_RGB_COLORS, (LPVOID*) &pBits, NULL, 0);
  1074. if(hBitmap){
  1075. // now use the orginal bmih
  1076. ::SetDIBits(hdcScreen, (HBITMAP) hBitmap, 0, lpbmih->biHeight, lpCurrent, (BITMAPINFO*)lpbmih, DIB_RGB_COLORS);
  1077. }
  1078. else {
  1079. DWORD dwError =::GetLastError();
  1080. ::ReleaseDC(NULL, hdcScreen);
  1081. ATLASSERT(FALSE);
  1082. throw (NULL);
  1083. }/* end of if statement */
  1084. ::ReleaseDC(NULL, hdcScreen);
  1085. }/* end of if statement */
  1086. if(lpDelete){
  1087. delete[] lpDelete; // cleanup the bits if we had to allocate them
  1088. lpDelete = NULL;
  1089. }/* end of if statement */
  1090. if(hBmpFile){
  1091. UnlockResource(hBmpFile);
  1092. ::FreeResource(hBmpFile);
  1093. hBmpFile = NULL;
  1094. }/* end of if statement */
  1095. }/* end of try statement */
  1096. #endif
  1097. catch(...){
  1098. if(hBmpFile){
  1099. UnlockResource(hBmpFile);
  1100. ::FreeResource(hBmpFile);
  1101. }/* end of if statement */
  1102. if(hFile){
  1103. ::CloseHandle(hFile);
  1104. hFile = NULL;
  1105. }/* end of if statement */
  1106. if(lpDelete){
  1107. delete[] lpDelete; // cleanup the bits if we had to allocate them
  1108. lpDelete = NULL;
  1109. }/* end of if statement */
  1110. hBitmap = NULL;
  1111. }/* end of catch statement */
  1112. return(hBitmap);
  1113. }/* end of function LoadImage */