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.

798 lines
22 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1996-1999 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // Bitmap.cpp
  7. //
  8. // Abstract:
  9. // Implementation of the CMyBitmap class.
  10. //
  11. // Author:
  12. // David Potter (davidp) June 12, 1996
  13. //
  14. // Revision History:
  15. //
  16. /////////////////////////////////////////////////////////////////////////////
  17. #include "stdafx.h"
  18. #include "Bitmap.h"
  19. #include "TraceTag.h"
  20. #include "ExcOper.h"
  21. #ifdef _DEBUG
  22. #define new DEBUG_NEW
  23. #undef THIS_FILE
  24. static char BASED_CODE THIS_FILE[] = __FILE__;
  25. #endif
  26. /////////////////////////////////////////////////////////////////////////////
  27. // Global Variables
  28. /////////////////////////////////////////////////////////////////////////////
  29. #ifdef _DEBUG
  30. CTraceTag g_tagBitmap(_T("Bitmap"), _T("Bitmap"));
  31. CTraceTag g_tagLoadBitmapResource(_T("Bitmap"), _T("LoadBitmapResource"));
  32. #endif
  33. /////////////////////////////////////////////////////////////////////////////
  34. // CMyBitmap
  35. /////////////////////////////////////////////////////////////////////////////
  36. // Array used for restoring the System Palette when a using a Custom Palette Bitmap.
  37. PALETTEENTRY CMyBitmap::s_rgpeSavedSystemPalette[nMaxSavedSystemPaletteEntries];
  38. /////////////////////////////////////////////////////////////////////////////
  39. //++
  40. //
  41. // CMyBitmap::CMyBitmap
  42. //
  43. // Routine Description:
  44. // Default constructor.
  45. //
  46. // Arguments:
  47. // None.
  48. //
  49. // Return Value:
  50. // None.
  51. //
  52. // Exceptions Thrown:
  53. // None.
  54. //--
  55. /////////////////////////////////////////////////////////////////////////////
  56. CMyBitmap::CMyBitmap(void)
  57. {
  58. m_hinst = NULL;
  59. m_pbiNormal = NULL;
  60. m_pbiHighlighted = NULL;
  61. m_pbBitmap = NULL;
  62. m_hPalette = NULL;
  63. m_nSavedSystemPalette = 0;
  64. SetCustomPalette(FALSE);
  65. } //*** CMyBitmap::CMyBitmap()
  66. /////////////////////////////////////////////////////////////////////////////
  67. //++
  68. //
  69. // CMyBitmap::~CMyBitmap
  70. //
  71. // Routine Description:
  72. // Destructor.
  73. //
  74. // Arguments:
  75. // None.
  76. //
  77. // Return Value:
  78. // None.
  79. //
  80. // Exceptions Thrown:
  81. // None.
  82. //--
  83. /////////////////////////////////////////////////////////////////////////////
  84. CMyBitmap::~CMyBitmap(void)
  85. {
  86. delete [] (PBYTE) PbiNormal();
  87. delete [] (PBYTE) PbiHighlighted();
  88. delete [] (PBYTE) PbBitmap();
  89. // If we saved the System Palette Entries, we have a Palette, and the
  90. // number of colors for the Palette() is enough to restore the System
  91. // Palette entries...
  92. if (m_nSavedSystemPalette
  93. && (HPalette() != NULL)
  94. && (NColors() >= m_nSavedSystemPalette))
  95. {
  96. HDC hdcScreen;
  97. UINT nRestoredEntries;
  98. HPALETTE hOldPalette;
  99. Trace(g_tagBitmap, _T("Restoring Screen Palette HPalette()=0x%x..."), HPalette());
  100. Trace(g_tagBitmap, _T("Restoring Screen Palette Entries=%d"), m_nSavedSystemPalette);
  101. // Restore the System Palette Entries
  102. nRestoredEntries = ::SetPaletteEntries(HPalette(), 0, m_nSavedSystemPalette, s_rgpeSavedSystemPalette);
  103. Trace(g_tagBitmap, _T("Restored Screen Palette Entries=%d"), nRestoredEntries);
  104. // Get the Screen's HDC
  105. hdcScreen = ::GetDC(NULL);
  106. // Select the Palette into the Screen's HDC
  107. hOldPalette = ::SelectPalette(hdcScreen, HPalette(), FALSE);
  108. // Unrealize the Palette to insure all the colors are forced into the System Palette
  109. ::UnrealizeObject(HPalette());
  110. // Force the local Palette's colors into the System Palette.
  111. ::RealizePalette(hdcScreen);
  112. // Release the Screen's HDC
  113. ::ReleaseDC(NULL, hdcScreen);
  114. // Invalidate the Screen completely so all windows are redrawn.
  115. ::InvalidateRect(NULL, NULL, TRUE);
  116. }
  117. // Destroy the Handle to the locally created Custom Palette.
  118. if (HPalette() != NULL)
  119. ::DeleteObject(HPalette());
  120. } //*** CMyBitmap::~CMyBitmap()
  121. /////////////////////////////////////////////////////////////////////////////
  122. //++
  123. //
  124. // CMyBitmap::Load
  125. //
  126. // Purpose:
  127. // Loads a bitmap from the resource into memory.
  128. //
  129. // Arguments:
  130. // idBitmap id of the resource to load
  131. //
  132. // Return Value:
  133. // None.
  134. //
  135. // Exceptions Thrown:
  136. // Any exceptions thrown by LoadBitmapResource, CreatePallette,
  137. // CreatePALColorMapping, or new.
  138. //--
  139. /////////////////////////////////////////////////////////////////////////////
  140. void CMyBitmap::Load(ID idBitmap)
  141. {
  142. // Load the Bitmap Header Information, Color Mapping Information, and the Bitmap Image.
  143. LoadBitmapResource(
  144. idBitmap,
  145. Hinst(),
  146. MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)
  147. );
  148. ASSERT(PbiNormal() != NULL);
  149. ASSERT(PbBitmap() != NULL);
  150. // Start by initializing some internal variables...
  151. m_dx = PbiNormal()->bmiHeader.biWidth;
  152. m_dy = PbiNormal()->bmiHeader.biHeight;
  153. ASSERT(PbiHighlighted() == NULL);
  154. if (BCustomPalette())
  155. {
  156. Trace(g_tagBitmap, _T("Load() - Creating Logical Palette"));
  157. // Save the System Palette Entries for use in the Destructor.
  158. SaveSystemPalette();
  159. // Create a Global HPalette() for use in the Paint() routine.
  160. CreatePalette();
  161. // Re-create the PbiNormal() for DIB_PAL_COLORS in the Paint() routine.
  162. CreatePALColorMapping();
  163. } // if: using a custom pallette
  164. else
  165. {
  166. // Create and Initialize the PbiHighlighted() for 16 color bitmaps.
  167. ASSERT(NColors() <= 16);
  168. Trace(g_tagBitmap, _T("Load() - Allocating PbiHighlighted()"));
  169. m_pbiHighlighted = (BITMAPINFO *) new BYTE[CbBitmapInfo()];
  170. if (m_pbiHighlighted != NULL)
  171. {
  172. ::CopyMemory(PbiHighlighted(), PbiNormal(), CbBitmapInfo());
  173. } // if: bitmapinfo allocated successfully
  174. } // else: not using a custom pallette
  175. } //*** CMyBitmap::Load()
  176. /////////////////////////////////////////////////////////////////////////////
  177. //++
  178. //
  179. // CMyBitmap::LoadBitmapResource
  180. //
  181. // Purpose:
  182. // Load a bitmap resource into the CMyBitmap class. This includes loading (a) bitmap
  183. // header information, (b) color mapping table, and (c) the actual bitmap.
  184. //
  185. // Arguments:
  186. // idbBitmap Resource id of the bitmap to load.
  187. // hinst Handle to the Module Instance
  188. // langid Language specific resource (possibly different bitmaps for localized strings [Japanese, etc.])
  189. //
  190. // Return Value:
  191. // None.
  192. //
  193. // Exceptions Thrown:
  194. // GetLastError from FindResourceEx, LoadResource, LockResource,
  195. // Any exceptions thrown by new.
  196. //
  197. //--
  198. /////////////////////////////////////////////////////////////////////////////
  199. void CMyBitmap::LoadBitmapResource(ID idbBitmap, HINSTANCE hinst, LANGID langid)
  200. {
  201. HRSRC hrsrc = NULL;
  202. HGLOBAL hglbl = NULL;
  203. LPBITMAPINFO pBitmapInfo = NULL;
  204. LPBITMAPINFOHEADER pBitmapInfoHeader = NULL;
  205. LPRGBQUAD pRgbQuad = NULL;
  206. CB cbBitmapData;
  207. BYTE * pbImageBits;
  208. Trace(g_tagLoadBitmapResource, _T("LoadBitmapResource(%d) - Entering"), idbBitmap);
  209. ASSERT(idbBitmap != NULL);
  210. if (hinst == NULL)
  211. hinst = AfxGetApp()->m_hInstance;
  212. // We need to find the bitmap data which includes (a) header info, (b) color, and (c) the bitmap.
  213. hrsrc = ::FindResourceEx(hinst, RT_BITMAP, MAKEINTRESOURCE(idbBitmap), langid);
  214. if (hrsrc == NULL)
  215. {
  216. DWORD dwError = ::GetLastError();
  217. CString strError;
  218. if (dwError == ERROR_RESOURCE_NAME_NOT_FOUND)
  219. strError.Format(_T("Bitmap Resource %d Not Found. NT Error %d Loading Bitmap [Lang=%d, SubLang=%d]"),
  220. idbBitmap, dwError, PRIMARYLANGID(langid), SUBLANGID(langid));
  221. else
  222. strError.Format(_T("NT Error %d Attempting to Load Bitmap Resource %d [Lang=%d, SubLang=%d]"),
  223. dwError, idbBitmap, PRIMARYLANGID(langid), SUBLANGID(langid));
  224. Trace(g_tagAlways, _T("LoadBitmapResource() - Error '%s'"), strError);
  225. ThrowStaticException(dwError);
  226. } // if: error finding the resource
  227. hglbl = ::LoadResource(hinst, hrsrc);
  228. if (hglbl == NULL)
  229. ThrowStaticException(::GetLastError());
  230. pBitmapInfo = (LPBITMAPINFO) ::LockResource(hglbl);
  231. if (pBitmapInfo == NULL)
  232. ThrowStaticException(::GetLastError());
  233. cbBitmapData = ::SizeofResource(hinst, hrsrc);
  234. ASSERT(cbBitmapData != 0);
  235. Trace(g_tagLoadBitmapResource, _T("Bitmap Location = 0x%x"), pBitmapInfo);
  236. Trace(g_tagLoadBitmapResource, _T("Bitmap Data Size = %d bytes"), cbBitmapData);
  237. pBitmapInfoHeader = (LPBITMAPINFOHEADER) &pBitmapInfo->bmiHeader;
  238. ASSERT(pBitmapInfoHeader != NULL);
  239. Trace(g_tagLoadBitmapResource, _T("Bitmap Info Header = 0x%x"), pBitmapInfoHeader);
  240. ASSERT(pBitmapInfoHeader->biSize == sizeof(BITMAPINFOHEADER));
  241. Trace(g_tagLoadBitmapResource, _T("biSize=%d"), pBitmapInfoHeader->biSize);
  242. Trace(g_tagLoadBitmapResource, _T("biWidth=%d"), pBitmapInfoHeader->biWidth); // Width in Pixels
  243. Trace(g_tagLoadBitmapResource, _T("biHeight=%d"), pBitmapInfoHeader->biHeight); // Height in Pixels
  244. Trace(g_tagLoadBitmapResource, _T("biPlanes=%d"), pBitmapInfoHeader->biPlanes);
  245. Trace(g_tagLoadBitmapResource, _T("biBitCount=%d"), pBitmapInfoHeader->biBitCount);
  246. Trace(g_tagLoadBitmapResource, _T("biCompression=%d"), pBitmapInfoHeader->biCompression);
  247. Trace(g_tagLoadBitmapResource, _T("biSizeImage=%d"), pBitmapInfoHeader->biSizeImage);
  248. Trace(g_tagLoadBitmapResource, _T("biXPelsPerMeter=%d"), pBitmapInfoHeader->biXPelsPerMeter);
  249. Trace(g_tagLoadBitmapResource, _T("biYPelsPerMeter=%d"), pBitmapInfoHeader->biYPelsPerMeter);
  250. Trace(g_tagLoadBitmapResource, _T("biClrUsed=%d"), pBitmapInfoHeader->biClrUsed);
  251. Trace(g_tagLoadBitmapResource, _T("biClrImportant=%d"), pBitmapInfoHeader->biClrImportant);
  252. pRgbQuad = (LPRGBQUAD) &pBitmapInfo->bmiColors;
  253. ASSERT(pRgbQuad != NULL);
  254. Trace(g_tagLoadBitmapResource, _T("Bitmap Rgb Quad = 0x%x"), pRgbQuad);
  255. m_nColors = NColorsFromBitCount(pBitmapInfoHeader->biBitCount);
  256. m_cbColorTable = m_nColors * sizeof(RGBQUAD);
  257. m_cbBitmapInfo = sizeof(BITMAPINFOHEADER) + CbColorTable();
  258. Trace(g_tagLoadBitmapResource, _T("NColors()=%d"), NColors());
  259. Trace(g_tagLoadBitmapResource, _T("CbColorTable()=%d"), CbColorTable());
  260. Trace(g_tagLoadBitmapResource, _T("CbBitmapInfo()=%d"), CbBitmapInfo());
  261. ASSERT(PbiNormal() == NULL);
  262. // Allocate the Normal Bitmap Information
  263. m_pbiNormal = (LPBITMAPINFO) new BYTE[CbBitmapInfo()];
  264. if (m_pbiNormal == NULL)
  265. {
  266. return;
  267. } // if: error allocating the bitmapinfo structure
  268. // Fill PbiNormal() with the Loaded Resource (a) Bitmap Information and Color Mapping Table.
  269. ::CopyMemory(PbiNormal(), pBitmapInfo, CbBitmapInfo());
  270. m_cbImageSize = pBitmapInfoHeader->biSizeImage;
  271. if ((m_cbImageSize == 0) && (pBitmapInfoHeader->biCompression == BI_RGB))
  272. m_cbImageSize = cbBitmapData - CbBitmapInfo();
  273. Trace(g_tagLoadBitmapResource, _T("Allocating Bitmap of size CbImageSize()=%d"), CbImageSize());
  274. ASSERT(cbBitmapData == CbBitmapInfo() + CbImageSize());
  275. ASSERT(PbBitmap() == NULL);
  276. // Allocate memory for the Bitmap Image
  277. m_pbBitmap = new BYTE[CbImageSize()];
  278. if (m_pbBitmap == NULL)
  279. {
  280. return;
  281. } // if: error allocating the bitmap image
  282. pbImageBits = (BYTE *) pBitmapInfo + CbBitmapInfo();
  283. Trace(g_tagLoadBitmapResource, _T("Bitmap Location pbImageBits=0x%x"), pbImageBits);
  284. // Copy the Image Bits into the allocated memory.
  285. ::CopyMemory(PbBitmap(), pbImageBits, CbImageSize());
  286. } //*** CMyBitmap::LoadBitmapResource()
  287. /////////////////////////////////////////////////////////////////////////////
  288. //++
  289. //
  290. // CMyBitmap::NColorsFromBitCount
  291. //
  292. // Purpose:
  293. // Compute the number of colors given the number of bits to represent color.
  294. //
  295. // Arguments:
  296. // nBitCount The number of bits used for color representation.
  297. //
  298. // Return Value:
  299. // nColors Number of colors represented with nBitCount bits.
  300. //
  301. //--
  302. /////////////////////////////////////////////////////////////////////////////
  303. int CMyBitmap::NColorsFromBitCount(int nBitCount) const
  304. {
  305. int nColors;
  306. switch (nBitCount)
  307. {
  308. default:
  309. nColors = 0;
  310. break;
  311. case 1:
  312. nColors = 2;
  313. break;
  314. case 4:
  315. nColors = 16;
  316. break;
  317. case 8:
  318. nColors = 256;
  319. break;
  320. }
  321. return nColors;
  322. } //*** CMyBitmap::NColorsFromBitCount()
  323. /////////////////////////////////////////////////////////////////////////////
  324. //++
  325. //
  326. // CMyBitmap::SaveSystemPalette
  327. //
  328. // Purpose:
  329. // To save the System Palette Colors for use when a Custom Palette overwrites
  330. // the System Palette entries. The Saved System Palette (s_rgpeSavedSystemPalette)
  331. // is used in the CMyBitmap's destructor.
  332. //
  333. // Arguments:
  334. // None.
  335. //
  336. // Return Values:
  337. // None.
  338. //
  339. //--
  340. /////////////////////////////////////////////////////////////////////////////
  341. void CMyBitmap::SaveSystemPalette(void)
  342. {
  343. HDC hdcScreen;
  344. int nPaletteEntries;
  345. int nSavedEntries;
  346. // Get the Screen's HDC
  347. hdcScreen = ::GetDC(NULL);
  348. if (hdcScreen == NULL)
  349. {
  350. return;
  351. } // if: couldn't get the screen DC
  352. // Can only save the System Palette Colors when the Device's RC_PALETTE bit is set.
  353. if (::GetDeviceCaps(hdcScreen, RASTERCAPS) & RC_PALETTE)
  354. {
  355. // Get the Number of System Palette Entries
  356. nPaletteEntries = ::GetDeviceCaps(hdcScreen, SIZEPALETTE);
  357. Trace(g_tagBitmap, _T("SaveSystemPalette() - nPaletteEntries=%d"), nPaletteEntries);
  358. if ((nPaletteEntries > 0)
  359. && (nPaletteEntries <= nMaxSavedSystemPaletteEntries))
  360. {
  361. // Get the Current System Palette Entries
  362. nSavedEntries = ::GetSystemPaletteEntries(hdcScreen, 0, nPaletteEntries, s_rgpeSavedSystemPalette);
  363. // Set the number of Saved System Palette Entries list for use in OnDestroy().
  364. if (nSavedEntries == nPaletteEntries)
  365. {
  366. Trace(g_tagBitmap, _T("SaveSystemPalette() - Saved System Palette Entries=%d"), nPaletteEntries);
  367. m_nSavedSystemPalette = nPaletteEntries;
  368. }
  369. }
  370. }
  371. // Release the Screen's HDC
  372. ::ReleaseDC(NULL, hdcScreen);
  373. } //*** CMyBitmap::SaveSystemPalette()
  374. /////////////////////////////////////////////////////////////////////////////
  375. //++
  376. //
  377. // CMyBitmap::CreatePalette
  378. //
  379. // Purpose:
  380. // Create a logical palette from the color mapping table embedded in the
  381. // bitmap resource.
  382. //
  383. // Arguments:
  384. // None.
  385. //
  386. // Return Values:
  387. // None.
  388. //
  389. // Exceptions Thrown:
  390. // GetLastError from CreatePalette.
  391. // Any exceptions thrown by new.
  392. //--
  393. /////////////////////////////////////////////////////////////////////////////
  394. void CMyBitmap::CreatePalette(void)
  395. {
  396. LPLOGPALETTE pLogicalPalette = NULL;
  397. CB cbLogicalPalette;
  398. int nColor;
  399. LPPALETTEENTRY pPaletteEntry;
  400. Trace(g_tagBitmap, _T("CreatePalette() - Entering"));
  401. try
  402. {
  403. // Compute the size of the logical palette.
  404. cbLogicalPalette = sizeof(LOGPALETTE) + (NColors() * sizeof(PALETTEENTRY));
  405. Trace(g_tagBitmap, _T("CreatePalette() - cbLogicalPalette=%d"), cbLogicalPalette);
  406. // Allocate the Logical Palette Memory
  407. pLogicalPalette = (LPLOGPALETTE) new BYTE[cbLogicalPalette];
  408. if (pLogicalPalette == NULL)
  409. {
  410. ThrowStaticException(GetLastError());
  411. } // if: error allocating the Logical Palette Memory
  412. ASSERT(pLogicalPalette != NULL);
  413. ASSERT(PbiNormal() != NULL);
  414. pLogicalPalette->palVersion = 0x300; // Windows 3.0
  415. pLogicalPalette->palNumEntries = (WORD) NColors();
  416. // Fill the Logical Palette's Color Information
  417. for (nColor=0; nColor<NColors(); nColor++)
  418. {
  419. pPaletteEntry = &(pLogicalPalette->palPalEntry[nColor]);
  420. pPaletteEntry->peRed = PbiNormal()->bmiColors[nColor].rgbRed;
  421. pPaletteEntry->peGreen = PbiNormal()->bmiColors[nColor].rgbGreen;
  422. pPaletteEntry->peBlue = PbiNormal()->bmiColors[nColor].rgbBlue;
  423. pPaletteEntry->peFlags = 0;
  424. }
  425. // Create the NT Palette for use in the Paint Routine.
  426. m_hPalette = ::CreatePalette(pLogicalPalette);
  427. if (m_hPalette == NULL)
  428. ThrowStaticException(::GetLastError());
  429. ASSERT(HPalette() != NULL);
  430. delete [] (PBYTE) pLogicalPalette;
  431. } // try
  432. catch (CException *)
  433. {
  434. delete pLogicalPalette;
  435. throw;
  436. } // catch: anything
  437. } //*** CMyBitmap::CreatePalette()
  438. /////////////////////////////////////////////////////////////////////////////
  439. //++
  440. //
  441. // CMyBitmap::CreatePALColorMapping
  442. //
  443. // Purpose:
  444. // Given BITMAPINFO in PbiNormal(), recreate the PbiNormal() into a
  445. // DIB_PAL_COLORS format.
  446. //
  447. // Arguments:
  448. // None.
  449. //
  450. // Return Value:
  451. // None.
  452. //
  453. // Exceptions Thrown:
  454. // Any exceptions thrown by new.
  455. //--
  456. /////////////////////////////////////////////////////////////////////////////
  457. void CMyBitmap::CreatePALColorMapping(void)
  458. {
  459. LPBITMAPINFO pNewBitmapInfo = NULL;
  460. CB cbNewBitmapInfo;
  461. CB cbNewBitmapHeaderInfo;
  462. BYTE * pbColorTable;
  463. WORD wColor;
  464. ASSERT(PbiNormal() != NULL);
  465. ASSERT(PbiNormal()->bmiHeader.biSize == sizeof(BITMAPINFOHEADER));
  466. // ASSERT(PbiNormal()->bmiHeader.biClrUsed == (UINT) NColors());
  467. try
  468. {
  469. Trace(g_tagBitmap, _T("CreatePALColorMapping() - Entering"));
  470. cbNewBitmapHeaderInfo = sizeof(BITMAPINFOHEADER);
  471. Trace(g_tagBitmap, _T("CreatePALColorMapping() - cbNewBitmapHeaderInfo=%d"), cbNewBitmapHeaderInfo);
  472. // New Bitmap Info is the Info Header plus the Color mapping information.
  473. cbNewBitmapInfo = cbNewBitmapHeaderInfo + (NColors() * sizeof(WORD));
  474. Trace(g_tagBitmap, _T("CreatePALColorMapping() - cbNewBitmapInfo=%d"), cbNewBitmapInfo);
  475. // Allocate the New Bitmap Information
  476. pNewBitmapInfo = (LPBITMAPINFO) new BYTE[cbNewBitmapInfo];
  477. ASSERT(pNewBitmapInfo != NULL);
  478. if (pNewBitmapInfo == NULL)
  479. {
  480. ThrowStaticException(GetLastError());
  481. } // if: error allocating the new bitmapinfo structure
  482. Trace(g_tagBitmap, _T("CreatePALColorMapping() - New Bitmap Info Location=0x%x"), pNewBitmapInfo);
  483. // Copy the Header Information to the allocated memory.
  484. ::CopyMemory(pNewBitmapInfo, PbiNormal(), cbNewBitmapHeaderInfo);
  485. // Create the Color Lookup Table.
  486. pbColorTable = (BYTE *) (pNewBitmapInfo) + cbNewBitmapHeaderInfo;
  487. ASSERT(pbColorTable + (NColors() * sizeof(WORD)) == (BYTE *) (pNewBitmapInfo) + cbNewBitmapInfo);
  488. Trace(g_tagBitmap, _T("CreatePALColorMapping() - Filling %d Color Table at Location 0x%x"), NColors(), pbColorTable);
  489. // Fill the PAL Color Lookup Table
  490. for (wColor = 0 ; wColor < NColors() ; wColor++)
  491. {
  492. ::CopyMemory(pbColorTable, &wColor, sizeof(WORD));
  493. pbColorTable += sizeof(WORD);
  494. }
  495. delete [] (PBYTE) PbiNormal();
  496. m_pbiNormal = pNewBitmapInfo;
  497. m_cbBitmapInfo = cbNewBitmapInfo;
  498. pNewBitmapInfo = NULL;
  499. } // try
  500. catch (CException *)
  501. {
  502. delete pNewBitmapInfo;
  503. throw;
  504. } // catch: anything
  505. } //*** CMyBitmap::CreatePALColorMapping()
  506. /////////////////////////////////////////////////////////////////////////////
  507. //++
  508. //
  509. // CMyBitmap::Paint
  510. //
  511. // Purpose:
  512. // Paints a sub-bitmap
  513. //
  514. // Parameters:
  515. // hdc HDC to paint
  516. // prect Where to position the bitmap:
  517. // Only the upperleft corner is used
  518. // bHighlighted Used to select the color map to use.
  519. //
  520. //--
  521. /////////////////////////////////////////////////////////////////////////////
  522. void CMyBitmap::Paint(HDC hdc, RECT * prect, BOOL bHighlighted)
  523. {
  524. LPBITMAPINFO pBitmapInfo;
  525. UINT nColorUse;
  526. HPALETTE hOldPalette = NULL;
  527. ASSERT(hdc != NULL);
  528. ASSERT(prect != NULL);
  529. Trace(g_tagBitmap, _T("bHighlighted = %d"), bHighlighted);
  530. #ifdef _DEBUG
  531. {
  532. int nPlanes;
  533. int nBitsPerPixel;
  534. int nBitCount;
  535. nPlanes = ::GetDeviceCaps(hdc, PLANES);
  536. nBitsPerPixel = ::GetDeviceCaps(hdc, BITSPIXEL);
  537. nBitCount = nPlanes * nBitsPerPixel;
  538. Trace(g_tagBitmap, _T("Paint() - nPlanes=%d"), nPlanes);
  539. Trace(g_tagBitmap, _T("Paint() - nBitsPerPixel=%d"), nBitsPerPixel);
  540. Trace(g_tagBitmap, _T("Paint() - nBitCount=%u"), nBitCount);
  541. }
  542. #endif
  543. try
  544. {
  545. if (BCustomPalette())
  546. {
  547. ASSERT(PbiNormal() != NULL);
  548. ASSERT(HPalette() != NULL);
  549. // Select the Custom Palette into the HDC about to be drawn...
  550. hOldPalette = ::SelectPalette(hdc, HPalette(), FALSE); // FALSE causes the current Screen Palette to be Overwritten
  551. if (hOldPalette == NULL)
  552. ThrowStaticException(::GetLastError());
  553. // Force the Palette colors into the System Palette
  554. if (::RealizePalette(hdc) == GDI_ERROR)
  555. ThrowStaticException(::GetLastError());
  556. pBitmapInfo = PbiNormal();
  557. nColorUse = DIB_PAL_COLORS;
  558. #ifdef NEVER
  559. pBitmapInfo = PbiNormal();
  560. nColorUse = DIB_RGB_COLORS;
  561. #endif
  562. } // if: using a custom palette
  563. else
  564. {
  565. ASSERT(NColors() <= 16);
  566. ASSERT(PbiNormal() != NULL);
  567. ASSERT(PbiHighlighted() != NULL);
  568. pBitmapInfo = (bHighlighted ? PbiHighlighted() : PbiNormal());
  569. nColorUse = DIB_RGB_COLORS;
  570. } // else: not using a custom palette
  571. ::SetDIBitsToDevice(
  572. hdc,
  573. (int) prect->left, // X coordinate on screen.
  574. (int) prect->top, // Y coordinate on screen.
  575. (DWORD) Dx(), // cx to paint
  576. (DWORD) Dy(), // cy to paint
  577. // Note: (0,0) of the DIB is lower-left corner!?!
  578. 0, // In pbi, xLeft to paint
  579. 0, // In pbi, yLower to paint
  580. 0, // Start scan line
  581. Dy(), // Number of scan lines
  582. PbBitmap(), // The buffer description
  583. pBitmapInfo, // Bitmap Information
  584. nColorUse // DIB_RGB_COLORS or DIB_PAL_COLORS
  585. );
  586. } // try
  587. catch (CException * pe)
  588. {
  589. pe->ReportError();
  590. pe->Delete();
  591. } // catch: CException
  592. } //*** CMyBitmap::Paint()
  593. /////////////////////////////////////////////////////////////////////////////
  594. //++
  595. //
  596. // CMyBitmap::LoadColors
  597. //
  598. // Purpose:
  599. // Loads the color maps based on the system settings
  600. //
  601. // Arguments:
  602. // pnColorNormal & pnColorHighlighted
  603. // Arrays of 16 elements:
  604. // -1 Do not remap this color
  605. // COLOR_xxx Remap this color to the system color.
  606. //
  607. //--
  608. /////////////////////////////////////////////////////////////////////////////
  609. void CMyBitmap::LoadColors(int * pnColorNormal, int * pnColorHighlighted)
  610. {
  611. LoadColors(pnColorNormal, PbiNormal());
  612. LoadColors(pnColorHighlighted, PbiHighlighted());
  613. } //*** CMyBitmap::LoadColors(pnColorNormal, pnColorHighlighted)
  614. /////////////////////////////////////////////////////////////////////////////
  615. //++
  616. //
  617. // CMyBitmap::LoadColors
  618. //
  619. // Purpose:
  620. // Similar to above LoadColors except only the PbiNormal() colors are altered.
  621. //
  622. // Arguments:
  623. // pnColorNormal Array of color mapping table.
  624. //
  625. // Returns:
  626. // None.
  627. //
  628. //--
  629. /////////////////////////////////////////////////////////////////////////////
  630. void CMyBitmap::LoadColors(int * pnColorNormal)
  631. {
  632. LoadColors(pnColorNormal, PbiNormal());
  633. } //*** CMyBitmap::LoadColors(pnColorNormal)
  634. /////////////////////////////////////////////////////////////////////////////
  635. //++
  636. //
  637. // CMyBitmap::LoadColors
  638. //
  639. // Purpose:
  640. // Loads one color map based on the system settings
  641. //
  642. // Arguments:
  643. // pnColor
  644. // Arrays of 16 elements:
  645. // -1 Do not remap this color
  646. // COLOR_xxx Remap this color to the system color.
  647. // pbi
  648. // BITMAPINFO structure to adjust
  649. //
  650. //--
  651. /////////////////////////////////////////////////////////////////////////////
  652. void CMyBitmap::LoadColors(int * pnColor, BITMAPINFO * pbi)
  653. {
  654. int inColor;
  655. COLORREF cr;
  656. ASSERT(pbi != NULL);
  657. ASSERT(pbi->bmiHeader.biBitCount <= 4);
  658. ASSERT(NColors() <= 16);
  659. ASSERT(BCustomPalette() == FALSE);
  660. for (inColor = 0; inColor < 16; inColor++)
  661. {
  662. if (pnColor[inColor] == -1)
  663. continue;
  664. cr = GetSysColor(pnColor[inColor]);
  665. pbi->bmiColors[inColor].rgbRed = GetRValue(cr);
  666. pbi->bmiColors[inColor].rgbGreen = GetGValue(cr);
  667. pbi->bmiColors[inColor].rgbBlue = GetBValue(cr);
  668. }
  669. } //*** CMyBitmap::LoadColors(pnColor, pbi)