DIBSectionLite.cpp 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213
  1. #include "stdafx.h"
  2. #include "DIBSectionLite.h"
  3. #ifdef _DEBUG
  4. #define new DEBUG_NEW
  5. #endif
  6. // Standard colours
  7. PALETTEENTRY CDIBSectionLite::ms_StdColours[] = {
  8. { 0x00, 0x00, 0x00, 0 }, // First 2 will be palette for monochrome bitmaps
  9. { 0xFF, 0xFF, 0xFF, 0 },
  10. { 0x00, 0x00, 0xFF, 0 }, // First 16 will be palette for 16 colour bitmaps
  11. { 0x00, 0xFF, 0x00, 0 },
  12. { 0x00, 0xFF, 0xFF, 0 },
  13. { 0xFF, 0x00, 0x00, 0 },
  14. { 0xFF, 0x00, 0xFF, 0 },
  15. { 0xFF, 0xFF, 0x00, 0 },
  16. { 0x00, 0x00, 0x80, 0 },
  17. { 0x00, 0x80, 0x00, 0 },
  18. { 0x00, 0x80, 0x80, 0 },
  19. { 0x80, 0x00, 0x00, 0 },
  20. { 0x80, 0x00, 0x80, 0 },
  21. { 0x80, 0x80, 0x00, 0 },
  22. { 0x80, 0x80, 0x80, 0 },
  23. { 0xC0, 0xC0, 0xC0, 0 },
  24. };
  25. /////////////////////////////////////////////////////////////////////////////
  26. // CDIBSectionLite static functions
  27. // --- In?: nBitsPerPixel - bits per pixel
  28. // --- Out :
  29. // --- Returns :The number of colours for this colour depth
  30. // --- Effect : Returns the number of color table entries given the number
  31. // of bits per pixel of a bitmap
  32. int CDIBSectionLite::NumColorEntries(int nBitsPerPixel)
  33. {
  34. int nColors = 0;
  35. switch (nBitsPerPixel)
  36. {
  37. case 1: nColors = 2; break;
  38. case 4: nColors = 16; break;
  39. case 8: nColors = 256; break;
  40. case 16:
  41. case 24:
  42. case 32: nColors = 0; break; // 16,24 or 32 bpp have no color table
  43. default:
  44. ASSERT(FALSE);
  45. }
  46. return nColors;
  47. }
  48. // --- In?: nWidth - image width in pixels
  49. // nBitsPerPixel - bits per pixel
  50. // --- Out :
  51. // --- Returns : Returns the number of storage bytes needed for each scanline
  52. // in the bitmap
  53. // --- Effect :
  54. int CDIBSectionLite::BytesPerLine(int nWidth, int nBitsPerPixel)
  55. {
  56. int nBytesPerLine = nWidth * nBitsPerPixel;
  57. nBytesPerLine = ( (nBytesPerLine + 31) & (~31) ) / 8;
  58. return nBytesPerLine;
  59. }
  60. // --- In?: palette - reference to a palette object which will be filled
  61. // nNumColours - number of colour entries to fill
  62. // --- Out :
  63. // --- Returns : TRUE on success, false otherwise
  64. // --- Effect : Creates a halftone color palette independant of screen color depth.
  65. // palette will be filled with the colors, and nNumColours is the No.
  66. // of colors to file. If nNumColoursis 0 or > 256, then 256 colors are used.
  67. BOOL CDIBSectionLite::CreateHalftonePalette(CPalette& palette, int nNumColours)
  68. {
  69. palette.DeleteObject();
  70. int nNumStandardColours = sizeof(ms_StdColours) / sizeof(ms_StdColours[0]);
  71. int nIndex = 0;
  72. int nNumEntries = nNumColours;
  73. if (nNumEntries <= 0 || nNumEntries > 256)
  74. nNumEntries = 256;
  75. PALETTEINFO PalInfo;
  76. PalInfo.palNumEntries = (WORD) nNumEntries;
  77. // The standard colours (16)
  78. for (int i = 0; i < nNumStandardColours; i++)
  79. {
  80. if (nIndex >= nNumEntries) break;
  81. memcpy( &(PalInfo.palPalEntry[nIndex]), &(ms_StdColours[i]), sizeof(PALETTEENTRY) );
  82. nIndex++;
  83. }
  84. // A colour cube (6 divisions = 216)
  85. for (int blue = 0; blue <= 5; blue++)
  86. for (int green = 0; green <= 5; green++)
  87. for (int red = 0; red <= 5; red++)
  88. {
  89. if (nIndex >= nNumEntries)
  90. break;
  91. PalInfo.palPalEntry[nIndex].peRed = (BYTE) ((red*255)/5);
  92. PalInfo.palPalEntry[nIndex].peGreen = (BYTE) ((green*255)/5);
  93. PalInfo.palPalEntry[nIndex].peBlue = (BYTE) ((blue*255)/5);
  94. PalInfo.palPalEntry[nIndex].peFlags = 0;
  95. nIndex++;
  96. }
  97. // A grey scale (24 divisions)
  98. for (int grey = 0; grey <= 23; grey++)
  99. {
  100. if (nIndex >= nNumEntries)
  101. break;
  102. PalInfo.palPalEntry[nIndex].peRed = (BYTE) (grey*255/23);
  103. PalInfo.palPalEntry[nIndex].peGreen = (BYTE) (grey*255/23);
  104. PalInfo.palPalEntry[nIndex].peBlue = (BYTE) (grey*255/23);
  105. PalInfo.palPalEntry[nIndex].peFlags = 0;
  106. nIndex++;
  107. }
  108. return palette.CreatePalette((LPLOGPALETTE) PalInfo);
  109. }
  110. /////////////////////////////////////////////////////////////////////////////
  111. // CDIBSectionLite
  112. CDIBSectionLite::CDIBSectionLite()
  113. {
  114. m_hBitmap = NULL;
  115. m_bDither = FALSE;
  116. m_hDrawDib = NULL;
  117. m_ppvBits = NULL;
  118. m_pdwBits = NULL;
  119. DeleteObject(); // This will initialise to a known state - ie. empty
  120. }
  121. CDIBSectionLite::~CDIBSectionLite()
  122. {
  123. DeleteObject();
  124. }
  125. // --- In?:
  126. // --- Out :
  127. // --- Returns :
  128. // --- Effect : Resets the object to an empty state, and frees all memory used.
  129. void CDIBSectionLite::DeleteObject()
  130. {
  131. if (m_hBitmap)
  132. {
  133. ::DeleteObject(m_hBitmap);
  134. m_hBitmap = NULL;
  135. }
  136. if ( m_pdwBits)
  137. {
  138. delete []m_pdwBits;
  139. m_pdwBits = NULL;
  140. }
  141. m_ppvBits = NULL;
  142. memset(&m_DIBinfo, 0, sizeof(m_DIBinfo));
  143. if (m_hDrawDib)
  144. {
  145. DrawDibClose(m_hDrawDib);
  146. m_hDrawDib = NULL;
  147. }
  148. m_iColorDataType = DIB_RGB_COLORS;
  149. m_iColorTableSize = 0;
  150. }
  151. void CDIBSectionLite::ClearObject()
  152. {
  153. //#if 0
  154. // if (m_hBitmap)
  155. // ::DeleteObject(m_hBitmap);
  156. // m_hBitmap = NULL;
  157. // m_ppvBits = NULL;
  158. //
  159. // memset(&m_DIBinfo, 0, sizeof(m_DIBinfo));
  160. //
  161. // if (m_hDrawDib)
  162. // DrawDibClose(m_hDrawDib);
  163. // m_hDrawDib = NULL;
  164. //#endif
  165. if ( m_hBitmap != NULL )
  166. {
  167. ::DeleteObject(m_hBitmap);
  168. m_hBitmap = NULL;
  169. }
  170. #if 0
  171. if ( m_ppvBits != NULL )
  172. {
  173. DWORD *dwAry = (DWORD*)m_ppvBits;
  174. delete []dwAry;
  175. m_ppvBits = NULL;
  176. }
  177. #else
  178. m_ppvBits = NULL;
  179. #endif
  180. memset(&m_DIBinfo, 0, sizeof(m_DIBinfo));
  181. if (m_hDrawDib)
  182. {
  183. DrawDibClose(m_hDrawDib);
  184. m_hDrawDib = NULL;
  185. }
  186. m_iColorDataType = DIB_RGB_COLORS;
  187. m_iColorTableSize = 0;
  188. }
  189. /////////////////////////////////////////////////////////////////////////////
  190. // CDIBSectionLite diagnostics
  191. #ifdef _DEBUG
  192. void CDIBSectionLite::AssertValid() const
  193. {
  194. ASSERT(m_hBitmap);
  195. DIBSECTION ds;
  196. DWORD dwSize = GetObject( m_hBitmap, sizeof(DIBSECTION), &ds );
  197. ASSERT(dwSize == sizeof(DIBSECTION));
  198. ASSERT(0 <= m_iColorTableSize && m_iColorTableSize <= 256);
  199. CObject::AssertValid();
  200. }
  201. void CDIBSectionLite::Dump(CDumpContext& dc) const
  202. {
  203. CObject::Dump(dc);
  204. }
  205. #endif //_DEBUG
  206. // --- In?: bDither - whether or not dithering should be enabled
  207. // --- Out :
  208. // --- Returns : TRUE on success
  209. // --- Effect : Turns dithering on by using the DrawDib functions instead of
  210. // the GDI functions
  211. BOOL CDIBSectionLite::SetDither(BOOL bDither)
  212. {
  213. BOOL bResult = TRUE;
  214. // Check for a no-change op.
  215. if ( (m_bDither == bDither) &&
  216. ((m_hDrawDib && bDither) || (!m_hDrawDib && !bDither)) )
  217. return bResult;
  218. if (m_hDrawDib != NULL)
  219. {
  220. DrawDibClose(m_hDrawDib);
  221. m_hDrawDib = NULL;
  222. }
  223. if (bDither)
  224. {
  225. if ( (m_hDrawDib = DrawDibOpen()) == NULL )
  226. bResult = FALSE;
  227. }
  228. m_bDither = (m_hDrawDib != NULL);
  229. return bResult;
  230. }
  231. // --- In?:
  232. // --- Out :
  233. // --- Returns : TRUE if dithering is used
  234. // --- Effect : Returns whether or not the DrawDib functions (and hence dithering)
  235. // is being used.
  236. BOOL CDIBSectionLite::GetDither()
  237. {
  238. return (m_bDither && (m_hDrawDib != NULL));
  239. }
  240. /////////////////////////////////////////////////////////////////////////////
  241. // CDIBSectionLite operations
  242. // --- In?: pDC - Pointer to a device context
  243. // ptDest - point at which the topleft corner of the image is drawn
  244. // bForceBackground - Specifies whether the palette is forced to be
  245. // a background palette
  246. // --- Out :
  247. // --- Returns : TRUE on success
  248. // --- Effect : Draws the image 1:1 on the device context
  249. BOOL CDIBSectionLite::Draw(CDC* pDC, CPoint ptDest, BOOL bForceBackground )
  250. {
  251. if (!m_hBitmap)
  252. return FALSE;
  253. CSize size = GetSize();
  254. CPoint SrcOrigin = CPoint(0,0);
  255. BOOL bResult = FALSE;
  256. if (GetDither() && GetBitCount() >= 8)
  257. {
  258. DrawDibSetPalette( m_hDrawDib, (HPALETTE)m_Palette);
  259. DrawDibRealize( m_hDrawDib, pDC->GetSafeHdc(), bForceBackground);
  260. bResult = DrawDibDraw(m_hDrawDib, pDC->GetSafeHdc(),
  261. ptDest.x, ptDest.y, size.cx, size.cy,
  262. GetBitmapInfoHeader(), GetDIBits(),
  263. SrcOrigin.x, SrcOrigin.y, size.cx, size.cy,
  264. 0/*DDF_HALFTONE*/);
  265. }
  266. else
  267. {
  268. CPalette* pOldPalette = NULL;
  269. if (m_Palette.m_hObject && UsesPalette(pDC))
  270. {
  271. pOldPalette = pDC->SelectPalette(&m_Palette, bForceBackground);
  272. pDC->RealizePalette();
  273. }
  274. bResult = SetDIBitsToDevice(pDC->GetSafeHdc(),
  275. ptDest.x, ptDest.y,
  276. size.cx, size.cy,
  277. SrcOrigin.x, SrcOrigin.y,
  278. SrcOrigin.y, size.cy - SrcOrigin.y,
  279. GetDIBits(), GetBitmapInfo(),
  280. m_iColorDataType);
  281. if (pOldPalette)
  282. pDC->SelectPalette(pOldPalette, FALSE);
  283. }
  284. return bResult;
  285. }
  286. // --- In?: pDC - Pointer to a device context
  287. // ptDest - point at which the topleft corner of the image is drawn
  288. // size - size to stretch the image
  289. // bForceBackground - Specifies whether the palette is forced to be
  290. // a background palette
  291. // --- Out :
  292. // --- Returns : TRUE on success
  293. // --- Effect : Stretch draws the image to the desired size on the device context
  294. BOOL CDIBSectionLite::Stretch(CDC* pDC, CPoint ptDest, CSize size, BOOL bForceBackground )
  295. {
  296. if (!m_hBitmap)
  297. return FALSE;
  298. CSize imagesize = GetSize();
  299. CPoint SrcOrigin = CPoint(0,0);
  300. BOOL bResult = FALSE;
  301. if (GetDither() && GetBitCount() >= 8)
  302. {
  303. DrawDibSetPalette( m_hDrawDib, (HPALETTE)m_Palette);
  304. DrawDibRealize( m_hDrawDib, pDC->GetSafeHdc(), bForceBackground);
  305. bResult = DrawDibDraw(m_hDrawDib, pDC->GetSafeHdc(),
  306. ptDest.x, ptDest.y, size.cx, size.cy,
  307. GetBitmapInfoHeader(), GetDIBits(),
  308. SrcOrigin.x, SrcOrigin.y, imagesize.cx, imagesize.cy,
  309. 0/*DDF_HALFTONE*/);
  310. }
  311. else
  312. {
  313. CPalette* pOldPalette = NULL;
  314. if (m_Palette.m_hObject && UsesPalette(pDC))
  315. {
  316. pOldPalette = pDC->SelectPalette(&m_Palette, bForceBackground);
  317. pDC->RealizePalette();
  318. }
  319. pDC->SetStretchBltMode(COLORONCOLOR);
  320. bResult = StretchDIBits(pDC->GetSafeHdc(),
  321. ptDest.x, ptDest.y,
  322. size.cx, size.cy,
  323. SrcOrigin.x, SrcOrigin.y,
  324. imagesize.cx, imagesize.cy,
  325. GetDIBits(), GetBitmapInfo(),
  326. m_iColorDataType, SRCCOPY);
  327. if (pOldPalette)
  328. pDC->SelectPalette(pOldPalette, FALSE);
  329. }
  330. return bResult;
  331. }
  332. //////////////////////////////////////////////////////////////////////////////
  333. // Setting the bitmap...
  334. // --- In?: nIDResource - resource ID
  335. // --- Out :
  336. // --- Returns : Returns TRUE on success, FALSE otherwise
  337. // --- Effect : Initialises the bitmap from a resource. If failure, then object is
  338. // initialised back to an empty bitmap.
  339. BOOL CDIBSectionLite::SetBitmap(UINT nIDResource)
  340. {
  341. return SetBitmap(MAKEINTRESOURCE(nIDResource));
  342. }
  343. // --- In?: lpszResourceName - resource name
  344. // --- Out :
  345. // --- Returns : Returns TRUE on success, FALSE otherwise
  346. // --- Effect : Initialises the bitmap from a resource. If failure, then object is
  347. // initialised back to an empty bitmap.
  348. BOOL CDIBSectionLite::SetBitmap(LPCTSTR lpszResourceName)
  349. {
  350. HBITMAP hBmp = (HBITMAP)::LoadImage(AfxGetResourceHandle(),
  351. lpszResourceName,
  352. IMAGE_BITMAP,
  353. 0,0,
  354. LR_CREATEDIBSECTION);
  355. if (!hBmp) return FALSE;
  356. BOOL bResult = SetBitmap(hBmp);
  357. ::DeleteObject(hBmp);
  358. return bResult;
  359. }
  360. // --- In?: lpBitmapInfo - pointer to a BITMAPINFO structure
  361. // lpBits - pointer to image bits
  362. // --- Out :
  363. // --- Returns : Returns TRUE on success, FALSE otherwise
  364. // --- Effect : Initialises the bitmap using the information in lpBitmapInfo to determine
  365. // the dimensions and colours, and the then sets the bits from the bits in
  366. // lpBits. If failure, then object is initialised back to an empty bitmap.
  367. BOOL CDIBSectionLite::SetBitmap(LPBITMAPINFO lpBitmapInfo, LPVOID lpBits)
  368. {
  369. //DeleteObject(); //Z.t注释
  370. if (!lpBitmapInfo || !lpBits)
  371. return FALSE;
  372. HDC hDC = NULL;
  373. try {
  374. BITMAPINFOHEADER& bmih = lpBitmapInfo->bmiHeader;
  375. // Compute the number of colours in the colour table
  376. m_iColorTableSize = NumColorEntries(bmih.biBitCount);
  377. DWORD dwBitmapInfoSize = sizeof(BITMAPINFO) + m_iColorTableSize*sizeof(RGBQUAD);
  378. // Copy over BITMAPINFO contents
  379. memcpy(&m_DIBinfo, lpBitmapInfo, dwBitmapInfoSize);
  380. // Should now have all the info we need to create the sucker.
  381. //TRACE(_T("Width %d, Height %d, Bits/pixel %d, Image Size %d\n"),
  382. // bmih.biWidth, bmih.biHeight, bmih.biBitCount, bmih.biSizeImage);
  383. // Create a DC which will be used to get DIB, then create DIBsection
  384. hDC = ::GetDC(NULL);
  385. if (!hDC)
  386. {
  387. TRACE0("Unable to get DC\n");
  388. AfxThrowResourceException();
  389. }
  390. m_hBitmap = CreateDIBSection(hDC, (const BITMAPINFO*) m_DIBinfo,
  391. m_iColorDataType, &m_ppvBits, NULL, 0);
  392. ::ReleaseDC(NULL, hDC);
  393. if (!m_hBitmap)
  394. {
  395. TRACE0("CreateDIBSection failed\n");
  396. AfxThrowResourceException();
  397. }
  398. DWORD dwImageSize = m_DIBinfo.bmiHeader.biSizeImage;
  399. if (dwImageSize == 0)
  400. {
  401. int nBytesPerLine = BytesPerLine(lpBitmapInfo->bmiHeader.biWidth,
  402. lpBitmapInfo->bmiHeader.biBitCount);
  403. dwImageSize = nBytesPerLine * lpBitmapInfo->bmiHeader.biHeight;
  404. }
  405. // Flush the GDI batch queue
  406. GdiFlush();
  407. memcpy(m_ppvBits, lpBits, dwImageSize);
  408. if (!CreatePalette())
  409. {
  410. TRACE0("Unable to create palette\n");
  411. AfxThrowResourceException();
  412. }
  413. }
  414. catch (CException *e)
  415. {
  416. e->Delete();
  417. _ShowLastError();
  418. if (hDC)
  419. ::ReleaseDC(NULL, hDC);
  420. DeleteObject();
  421. return FALSE;
  422. }
  423. return TRUE;
  424. }
  425. // --- In?: hBitmap - handle to image
  426. // pPalette - optional palette to use when setting image
  427. // --- Out :
  428. // --- Returns : Returns TRUE on success, FALSE otherwise
  429. // --- Effect : Initialises the bitmap from the HBITMAP supplied. If failure, then
  430. // object is initialised back to an empty bitmap.
  431. BOOL CDIBSectionLite::SetBitmap(HBITMAP hBitmap, CPalette* pPalette /*= NULL*/)
  432. {
  433. //DeleteObject(); //Z.t注释
  434. if (!hBitmap)
  435. return FALSE;
  436. // Get dimensions of bitmap
  437. BITMAP bm;
  438. if (!::GetObject(hBitmap, sizeof(bm),(LPVOID)&bm))
  439. return FALSE;
  440. bm.bmHeight = abs(bm.bmHeight);
  441. CWindowDC dc(NULL);
  442. CPalette* pOldPalette = NULL;
  443. try {
  444. m_iColorTableSize = NumColorEntries(bm.bmBitsPixel);
  445. // Initialize the BITMAPINFOHEADER in m_DIBinfo
  446. BITMAPINFOHEADER& bih = m_DIBinfo.bmiHeader;
  447. bih.biSize = sizeof(BITMAPINFOHEADER);
  448. bih.biWidth = bm.bmWidth;
  449. bih.biHeight = bm.bmHeight;
  450. bih.biPlanes = 1; // Must always be 1 according to docs
  451. bih.biBitCount = bm.bmBitsPixel;
  452. bih.biCompression = BI_RGB;
  453. bih.biSizeImage = BytesPerLine(bm.bmWidth, bm.bmBitsPixel) * bm.bmHeight;
  454. bih.biXPelsPerMeter = 0;
  455. bih.biYPelsPerMeter = 0;
  456. bih.biClrUsed = 0;
  457. bih.biClrImportant = 0;
  458. // calls GetDIBits with NULL bits pointer to fill in the BITMAPINFOHEADER data
  459. if (!::GetDIBits(dc.m_hDC, hBitmap, 0, bm.bmHeight, NULL, m_DIBinfo, m_iColorDataType))
  460. {
  461. TRACE0("Unable to GetDIBits\n");
  462. AfxThrowResourceException();
  463. }
  464. // If the driver did not fill in the biSizeImage field, then compute it
  465. // Each scan line of the image is aligned on a DWORD (32bit) boundary
  466. if (bih.biSizeImage == 0)
  467. bih.biSizeImage = BytesPerLine(bih.biWidth, bih.biBitCount) * bih.biHeight;
  468. if (pPalette)
  469. SetPalette(pPalette);
  470. else
  471. CreateHalftonePalette(m_Palette, m_iColorTableSize);
  472. if (m_Palette.GetSafeHandle())
  473. {
  474. pOldPalette = dc.SelectPalette(&m_Palette, FALSE);
  475. dc.RealizePalette();
  476. }
  477. // Create it!
  478. m_hBitmap = CreateDIBSection(dc.m_hDC,
  479. (const BITMAPINFO*) m_DIBinfo,
  480. m_iColorDataType,
  481. &m_ppvBits,
  482. NULL, 0);
  483. if (pOldPalette)
  484. dc.SelectPalette(pOldPalette, FALSE);
  485. pOldPalette = NULL;
  486. if (!m_hBitmap)
  487. {
  488. TRACE0("Unable to CreateDIBSection\n");
  489. AfxThrowResourceException();
  490. }
  491. // Need to copy the supplied bitmap onto the newly created DIBsection
  492. CDC memDC, CopyDC;
  493. if (!CopyDC.CreateCompatibleDC(&dc) || !memDC.CreateCompatibleDC(&dc))
  494. {
  495. TRACE0("Unable to create compatible DC's\n");
  496. AfxThrowResourceException();
  497. }
  498. if (m_Palette.GetSafeHandle())
  499. {
  500. memDC.SelectPalette(&m_Palette, FALSE); memDC.RealizePalette();
  501. CopyDC.SelectPalette(&m_Palette, FALSE); CopyDC.RealizePalette();
  502. }
  503. GdiFlush();
  504. HBITMAP hOldMemBitmap = (HBITMAP) SelectObject(memDC.m_hDC, hBitmap);
  505. HBITMAP hOldCopyBitmap = (HBITMAP) SelectObject(CopyDC.m_hDC, m_hBitmap);
  506. CopyDC.BitBlt(0,0, bm.bmWidth, bm.bmHeight, &memDC, 0,0, SRCCOPY);
  507. SelectObject(memDC.m_hDC, hOldMemBitmap);
  508. SelectObject(CopyDC.m_hDC, hOldCopyBitmap);
  509. if (m_Palette.GetSafeHandle())
  510. {
  511. memDC.SelectStockObject(DEFAULT_PALETTE);
  512. CopyDC.SelectStockObject(DEFAULT_PALETTE);
  513. }
  514. }
  515. catch (CException *e)
  516. {
  517. e->Delete();
  518. _ShowLastError();
  519. if (pOldPalette)
  520. dc.SelectPalette(pOldPalette, FALSE);
  521. DeleteObject();
  522. return FALSE;
  523. }
  524. return TRUE;
  525. }
  526. //////////////////////////////////////////////////////////////////////////////
  527. // Persistance...
  528. // --- In?: lpszFileName - image filename
  529. // --- Out :
  530. // --- Returns : Returns TRUE on success, FALSE otherwise
  531. // --- Effect : Loads the bitmap from a bitmap file with the name lpszFileName.
  532. // If failure, then object is initialised back to an empty bitmap.
  533. BOOL CDIBSectionLite::Load(LPCTSTR lpszFileName)
  534. {
  535. CFile file;
  536. if (!file.Open(lpszFileName, CFile::modeRead))
  537. return FALSE;
  538. // Get the current file position.
  539. DWORD dwFileStart = file.GetPosition();
  540. // The first part of the file contains the file header.
  541. // This will tell us if it is a bitmap, how big the header is, and how big
  542. // the file is. The header size in the file header includes the color table.
  543. BITMAPFILEHEADER BmpFileHdr;
  544. int nBytes;
  545. nBytes = file.Read(&BmpFileHdr, sizeof(BmpFileHdr));
  546. if (nBytes != sizeof(BmpFileHdr))
  547. {
  548. TRACE0("Failed to read file header\n");
  549. return FALSE;
  550. }
  551. // Check that we have the magic 'BM' at the start.
  552. if (BmpFileHdr.bfType != DS_BITMAP_FILEMARKER)
  553. {
  554. TRACE0("Not a bitmap file\n");
  555. return FALSE;
  556. }
  557. // Read the header (assuming it's a DIB).
  558. DIBINFO BmpInfo;
  559. nBytes = file.Read(&BmpInfo, sizeof(BITMAPINFOHEADER));
  560. if (nBytes != sizeof(BITMAPINFOHEADER))
  561. {
  562. TRACE0("Failed to read BITMAPINFOHEADER\n");
  563. return FALSE;
  564. }
  565. // Check that we have a real Windows DIB file.
  566. if (BmpInfo.bmiHeader.biSize != sizeof(BITMAPINFOHEADER))
  567. {
  568. TRACE0(" File is not a Windows DIB\n");
  569. return FALSE;
  570. }
  571. // See how big the color table is in the file (if there is one).
  572. int nColors = NumColorEntries(BmpInfo.bmiHeader.biBitCount);
  573. if (nColors > 0)
  574. {
  575. // Read the color table from the file.
  576. int nColorTableSize = nColors * sizeof(RGBQUAD);
  577. nBytes = file.Read(BmpInfo.ColorTable(), nColorTableSize);
  578. if (nBytes != nColorTableSize)
  579. {
  580. TRACE0("Failed to read color table\n");
  581. return FALSE;
  582. }
  583. }
  584. // So how big the bitmap surface is.
  585. int nBitsSize = BmpFileHdr.bfSize - BmpFileHdr.bfOffBits;
  586. // Allocate the memory for the bits and read the bits from the file.
  587. BYTE* pBits = (BYTE*) malloc(nBitsSize);
  588. if (!pBits)
  589. {
  590. TRACE0("Out of memory for DIB bits\n");
  591. return FALSE;
  592. }
  593. // Seek to the bits in the file.
  594. file.Seek(dwFileStart + BmpFileHdr.bfOffBits, CFile::begin);
  595. // read the bits
  596. nBytes = file.Read(pBits, nBitsSize);
  597. if (nBytes != nBitsSize)
  598. {
  599. TRACE0("Failed to read bits\n");
  600. free(pBits);
  601. return FALSE;
  602. }
  603. // Everything went OK.
  604. BmpInfo.bmiHeader.biSizeImage = nBitsSize;
  605. if (!SetBitmap((LPBITMAPINFO) BmpInfo, pBits))
  606. {
  607. TRACE0("Failed to set bitmap info\n");
  608. free(pBits);
  609. return FALSE;
  610. }
  611. free(pBits);
  612. return TRUE;
  613. }
  614. // --- In?: lpszFileName - image filename
  615. // --- Out :
  616. // --- Returns : Returns TRUE on success, FALSE otherwise
  617. // --- Effect : Saves the image to file.
  618. BOOL CDIBSectionLite::Save(LPCTSTR lpszFileName)
  619. {
  620. BITMAPFILEHEADER hdr;
  621. LPBITMAPINFOHEADER lpbi = GetBitmapInfoHeader();
  622. if (!lpbi || !lpszFileName)
  623. return FALSE;
  624. CFile file;
  625. if (!file.Open(lpszFileName, CFile::modeWrite|CFile::modeCreate))
  626. return FALSE;
  627. DWORD dwBitmapInfoSize = sizeof(BITMAPINFO) + m_iColorTableSize*sizeof(RGBQUAD);
  628. DWORD dwFileHeaderSize = dwBitmapInfoSize + sizeof(hdr);
  629. // Fill in the fields of the file header
  630. hdr.bfType = DS_BITMAP_FILEMARKER;
  631. hdr.bfSize = dwFileHeaderSize + lpbi->biSizeImage;
  632. hdr.bfReserved1 = 0;
  633. hdr.bfReserved2 = 0;
  634. hdr.bfOffBits = dwFileHeaderSize;
  635. // Write the file header
  636. file.Write(&hdr, sizeof(hdr));
  637. // Write the DIB header
  638. file.Write(lpbi, dwBitmapInfoSize);
  639. // Write DIB bits
  640. file.Write(GetDIBits(), lpbi->biSizeImage);
  641. return TRUE;
  642. }
  643. /////////////////////////////////////////////////////////////////////////////
  644. // CDIBSectionLite palette stuff
  645. // --- In?:
  646. // --- Out :
  647. // --- Returns : TRUE on success
  648. // --- Effect : Creates the palette from the DIBSection's color table. Assumes
  649. // m_iColorTableSize has been set and the DIBsection m_hBitmap created
  650. BOOL CDIBSectionLite::CreatePalette()
  651. {
  652. m_Palette.DeleteObject();
  653. if (!m_hBitmap)
  654. return FALSE;
  655. // Create a 256 color halftone palette if there is no color table in the DIBSection
  656. if (m_iColorTableSize == 0)
  657. return CreateHalftonePalette(m_Palette, 256);
  658. HDC hDC = ::GetDC(NULL);
  659. if (!hDC)
  660. return FALSE;
  661. // Get space for the colour entries
  662. RGBQUAD *pRGB = new RGBQUAD[m_iColorTableSize];
  663. if (!pRGB)
  664. {
  665. ReleaseDC(NULL, hDC);
  666. return CreateHalftonePalette(m_Palette, m_iColorTableSize);
  667. }
  668. // Create a memory DC compatible with the current DC
  669. CDC MemDC;
  670. MemDC.CreateCompatibleDC(CDC::FromHandle(hDC));
  671. if (!MemDC.GetSafeHdc())
  672. {
  673. delete [] pRGB;
  674. ::ReleaseDC(NULL, hDC);
  675. return CreateHalftonePalette(m_Palette, m_iColorTableSize);
  676. }
  677. ::ReleaseDC(NULL, hDC);
  678. HBITMAP hOldBitmap = (HBITMAP) ::SelectObject(MemDC.GetSafeHdc(), m_hBitmap);
  679. if (!hOldBitmap)
  680. {
  681. delete [] pRGB;
  682. return CreateHalftonePalette(m_Palette, m_iColorTableSize);
  683. }
  684. // Get the colours used.
  685. int nColours = ::GetDIBColorTable(MemDC.GetSafeHdc(), 0, m_iColorTableSize, pRGB);
  686. // Clean up
  687. ::SelectObject(MemDC.GetSafeHdc(), hOldBitmap);
  688. if (!nColours) // No colours retrieved => the bitmap in the DC is not a DIB section
  689. {
  690. delete [] pRGB;
  691. return CreateHalftonePalette(m_Palette, m_iColorTableSize);
  692. }
  693. // Create and fill a LOGPALETTE structure with the colours used.
  694. PALETTEINFO PaletteInfo;
  695. PaletteInfo.palNumEntries = (WORD) m_iColorTableSize;
  696. int i ;
  697. for ( i = 0; i < nColours; i++)
  698. {
  699. PaletteInfo.palPalEntry[i].peRed = pRGB[i].rgbRed;
  700. PaletteInfo.palPalEntry[i].peGreen = pRGB[i].rgbGreen;
  701. PaletteInfo.palPalEntry[i].peBlue = pRGB[i].rgbBlue;
  702. PaletteInfo.palPalEntry[i].peFlags = 0;
  703. }
  704. for (; i < (int) m_iColorTableSize; i++)
  705. {
  706. PaletteInfo.palPalEntry[i].peRed = 0;
  707. PaletteInfo.palPalEntry[i].peGreen = 0;
  708. PaletteInfo.palPalEntry[i].peBlue = 0;
  709. PaletteInfo.palPalEntry[i].peFlags = 0;
  710. }
  711. if ( pRGB )
  712. {
  713. delete [] pRGB;
  714. pRGB = NULL;
  715. }
  716. // Create Palette!
  717. return m_Palette.CreatePalette(&PaletteInfo);
  718. }
  719. // --- In?: pPalette - new palette to use
  720. // --- Out :
  721. // --- Returns : TRUE on success
  722. // --- Effect : Sets the current palette used by the image from the supplied CPalette,
  723. // and sets the color table in the DIBSection
  724. BOOL CDIBSectionLite::SetPalette(CPalette* pPalette)
  725. {
  726. m_Palette.DeleteObject();
  727. if (!pPalette)
  728. return FALSE;
  729. UINT nColours = pPalette->GetEntryCount();
  730. if (nColours <= 0 || nColours > 256)
  731. return FALSE;
  732. // Get palette entries
  733. PALETTEINFO pi;
  734. pi.palNumEntries = (WORD) pPalette->GetPaletteEntries(0, nColours, (LPPALETTEENTRY) pi);
  735. // TODO: If pi.palNumEntries < m_iColorTableSize, then fill in blanks with 0's
  736. return SetLogPalette(&pi);
  737. }
  738. // --- In?: pLogPalette - new palette to use
  739. // --- Out :
  740. // --- Returns : TRUE on success
  741. // --- Effect : Sets the current palette used by the image from the supplied LOGPALETTE
  742. BOOL CDIBSectionLite::SetLogPalette(LOGPALETTE* pLogPalette)
  743. {
  744. ASSERT(pLogPalette->palVersion == (WORD) 0x300);
  745. UINT nColours = pLogPalette->palNumEntries;
  746. if (nColours <= 0 || nColours > 256)
  747. {
  748. CreatePalette();
  749. return FALSE;
  750. }
  751. // Create new palette
  752. m_Palette.DeleteObject();
  753. if (!m_Palette.CreatePalette(pLogPalette))
  754. {
  755. CreatePalette();
  756. return FALSE;
  757. }
  758. if (m_iColorTableSize == 0)
  759. return TRUE;
  760. // Set the DIB colours
  761. RGBQUAD RGBquads[256];
  762. for (UINT i = 0; i < nColours; i++)
  763. {
  764. RGBquads[i].rgbRed = pLogPalette->palPalEntry[i].peRed;
  765. RGBquads[i].rgbGreen = pLogPalette->palPalEntry[i].peGreen;
  766. RGBquads[i].rgbBlue = pLogPalette->palPalEntry[i].peBlue;
  767. RGBquads[i].rgbReserved = 0;
  768. }
  769. return FillDIBColorTable(nColours, RGBquads);
  770. }
  771. void CDIBSectionLite::CreateGradientBmp (COLORREF clrBack,COLORREF clrStart,COLORREF clrEnd,int iWidth,int iHeight,int iDirection)
  772. {
  773. RECT rectFill; // Rectangle for filling band
  774. float fStep; // How wide is each band?
  775. CBrush brush; // Brush to fill in the bar
  776. CBitmap ourNewBitmap;
  777. CWindowDC dc(NULL);
  778. CDC tempDC;
  779. CDC tempDC1;
  780. tempDC.CreateCompatibleDC(&dc);
  781. tempDC1.CreateCompatibleDC(&dc);
  782. ourNewBitmap.CreateDiscardableBitmap(&dc,iWidth,iHeight);
  783. //ourNewBitmap.CreateBitmap(iWidth,iHeight,3,32,NULL);
  784. CBitmap* pOldBitmap = tempDC.SelectObject(&ourNewBitmap);
  785. // First find out the largest color distance between the start and end colors. This distance
  786. // will determine how many steps we use to carve up the client region and the size of each
  787. // gradient rect.
  788. int r, g, b; // First distance, then starting value
  789. float rStep, gStep, bStep; // Step size for each color
  790. // Get the color differences
  791. r = (GetRValue(clrEnd) - GetRValue(clrStart));
  792. g = (GetGValue(clrEnd) - GetGValue(clrStart));
  793. b = (GetBValue(clrEnd) - GetBValue(clrStart));
  794. // Make the number of steps equal to the greatest distance
  795. int nSteps = max(abs(r), max(abs(g), abs(b)));
  796. // Determine how large each band should be in order to cover the
  797. // client with nSteps bands (one for every color intensity level)
  798. if(iDirection == BMGRADIENT_DIRECTION_HORZ)
  799. fStep = (float)iWidth / (float)nSteps;
  800. else if(iDirection == BMGRADIENT_DIRECTION_VERT)
  801. fStep = (float)iHeight / (float)nSteps;
  802. // Calculate the step size for each color
  803. rStep = r/(float)nSteps;
  804. gStep = g/(float)nSteps;
  805. bStep = b/(float)nSteps;
  806. // Reset the colors to the starting position
  807. r = GetRValue(clrStart);
  808. g = GetGValue(clrStart);
  809. b = GetBValue(clrStart);
  810. // Start filling bands
  811. for (int iOnBand = 0; iOnBand < nSteps; iOnBand++)
  812. {
  813. // Set the rect we will fill with the gradient
  814. if(iDirection == BMGRADIENT_DIRECTION_HORZ)
  815. {
  816. ::SetRect(&rectFill,
  817. (int)(iOnBand * fStep), // Upper left X
  818. 0, // Upper left Y
  819. (int)((iOnBand+1) * fStep), // Lower right X
  820. iHeight+1); // Lower right Y
  821. }
  822. else if(iDirection == BMGRADIENT_DIRECTION_VERT)
  823. {
  824. ::SetRect(&rectFill,
  825. 0, // Upper left X
  826. (iOnBand * fStep), // Upper left Y
  827. iWidth, // Lower right X
  828. (int)((iOnBand+1) * fStep)); // Lower right Y
  829. }
  830. // CDC::FillSolidRect is faster, but it does not handle 8-bit color depth
  831. VERIFY(brush.CreateSolidBrush(RGB(r+rStep*iOnBand, g + gStep*iOnBand, b + bStep *iOnBand)));
  832. tempDC.FillRect(&rectFill,&brush);
  833. VERIFY(brush.DeleteObject());
  834. // If we are past the maximum for the current position we need to get out of the loop.
  835. // Before we leave, we repaint the remainder of the client area with the background color.
  836. if(iDirection == BMGRADIENT_DIRECTION_HORZ)
  837. {
  838. if (rectFill.right > iWidth)
  839. {
  840. ::SetRect(&rectFill, rectFill.right, 0, iWidth, iHeight);
  841. VERIFY(brush.CreateSolidBrush(clrBack));
  842. tempDC.FillRect(&rectFill, &brush);
  843. VERIFY(brush.DeleteObject());
  844. return;
  845. }
  846. }
  847. else if(iDirection == BMGRADIENT_DIRECTION_VERT)
  848. {
  849. if (rectFill.right > iHeight)
  850. {
  851. ::SetRect(&rectFill, rectFill.right, 0, iWidth, iHeight);
  852. VERIFY(brush.CreateSolidBrush(clrBack));
  853. tempDC.FillRect(&rectFill, &brush);
  854. VERIFY(brush.DeleteObject());
  855. return;
  856. }
  857. }
  858. }
  859. // Create a 32 bit bitmap
  860. #if 1
  861. m_pdwBits = new DWORD[iWidth*iHeight];
  862. m_ppvBits = m_pdwBits;
  863. #else
  864. m_ppvBits = new DWORD[iWidth*iHeight];
  865. #endif
  866. BITMAPINFO bih;
  867. // create DIB Section
  868. bih.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  869. bih.bmiHeader.biWidth = iWidth;
  870. bih.bmiHeader.biHeight = iHeight;
  871. bih.bmiHeader.biPlanes = 1;
  872. bih.bmiHeader.biBitCount = 32;
  873. bih.bmiHeader.biCompression = BI_RGB;
  874. bih.bmiHeader.biSizeImage = 0;
  875. bih.bmiHeader.biXPelsPerMeter = 0;
  876. bih.bmiHeader.biYPelsPerMeter = 0;
  877. bih.bmiHeader.biClrUsed = 0;
  878. bih.bmiHeader.biClrImportant = 0;
  879. SetBitmap(&bih,m_ppvBits);
  880. DWORD* pLine = (DWORD*)GetDIBits();
  881. // Copy the bits into our 32 bit dib..
  882. for(int i=0;i<iHeight;i++)
  883. {
  884. for(int j=0;j<iWidth;j++)
  885. {
  886. pLine[(i*iWidth)+j] = FixColorRef(tempDC.GetPixel(j,i));
  887. }
  888. }
  889. // Set the dc back to normal
  890. tempDC.SelectObject(pOldBitmap);
  891. #if 0
  892. if ( m_pdwBits )
  893. {
  894. delete []m_pdwBits;
  895. m_pdwBits = NULL;
  896. }
  897. #endif
  898. }
  899. void CDIBSectionLite::Create32BitFromPicture (CPictureHolder* pPicture,int iWidth,int iHeight)
  900. {
  901. CBitmap ourNewSizedBMP;
  902. CWindowDC dc(NULL); // 创建DC时出错,内存泄漏了;
  903. CDC tempDC;
  904. CRect rcRender;
  905. tempDC.CreateCompatibleDC(&dc);
  906. ourNewSizedBMP.CreateDiscardableBitmap(&dc,iWidth,iHeight);
  907. // Now we need to select it into our temp DC so we can render the picture onto it
  908. CBitmap* pOldBitmap = tempDC.SelectObject(&ourNewSizedBMP);
  909. // Render the picture onto our bmp
  910. rcRender.SetRect(0,0,iWidth,iHeight);
  911. pPicture->Render(&tempDC,rcRender,rcRender);
  912. // Create a 32 bit bitmap
  913. #if 1
  914. m_pdwBits = new DWORD[iWidth*iHeight];
  915. //memcpy(m_ppvBits,pdwBits,sizeof(DWORD));
  916. m_ppvBits = m_pdwBits;
  917. #else
  918. m_ppvBits = new DWORD[iWidth*iHeight];
  919. #endif
  920. BITMAPINFO bih;
  921. // create DIB Section
  922. bih.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  923. bih.bmiHeader.biWidth = iWidth;
  924. bih.bmiHeader.biHeight = iHeight;
  925. bih.bmiHeader.biPlanes = 1;
  926. bih.bmiHeader.biBitCount = 32;
  927. bih.bmiHeader.biCompression = BI_RGB;
  928. bih.bmiHeader.biSizeImage = 0;
  929. bih.bmiHeader.biXPelsPerMeter = 0;
  930. bih.bmiHeader.biYPelsPerMeter = 0;
  931. bih.bmiHeader.biClrUsed = 0;
  932. bih.bmiHeader.biClrImportant = 0;
  933. SetBitmap(&bih,m_ppvBits);
  934. DWORD* pLine = (DWORD*)GetDIBits();
  935. // Copy the bits into our 32 bit dib..
  936. for(int i=0;i<iHeight;i++)
  937. {
  938. for(int j=0;j<iWidth;j++)
  939. {
  940. pLine[(i*iWidth)+j] = FixColorRef(tempDC.GetPixel(j,i));
  941. }
  942. }
  943. // Set the dc back to normal
  944. tempDC.SelectObject(pOldBitmap);
  945. #if 0
  946. if ( m_pdwBits )
  947. {
  948. delete []m_pdwBits;
  949. m_pdwBits = NULL;
  950. }
  951. #endif
  952. }
  953. inline COLORREF CDIBSectionLite::FixColorRef(COLORREF clr)
  954. {
  955. int r = GetRValue(clr);
  956. int g = GetGValue(clr);
  957. int b = GetBValue(clr);
  958. return RGB(b,g,r);
  959. }
  960. // --- In?: nNumColours - number of colours to set
  961. // pRGB - colours to fill
  962. // --- Out :
  963. // --- Returns : Returns TRUE on success
  964. // --- Effect : Sets the colours used by the image. Only works if # colours <= 256
  965. BOOL CDIBSectionLite::FillDIBColorTable(UINT nNumColours, RGBQUAD *pRGB)
  966. {
  967. if (!m_hBitmap || !pRGB || !nNumColours || !m_iColorTableSize
  968. || nNumColours > 256)
  969. return FALSE;
  970. // Create a memory DC compatible with the screen
  971. HDC hDC = ::GetDC(NULL);
  972. if (!hDC) return FALSE;
  973. CDC MemDC;
  974. MemDC.CreateCompatibleDC(CDC::FromHandle(hDC));
  975. ::ReleaseDC(NULL, hDC);
  976. if (!MemDC.GetSafeHdc())
  977. return FALSE;
  978. HBITMAP hOldBitmap = (HBITMAP) ::SelectObject(MemDC.GetSafeHdc(), m_hBitmap);
  979. // Set the bitmap colours.
  980. int nColours = ::SetDIBColorTable(MemDC.GetSafeHdc(), 0, nNumColours, pRGB);
  981. // Clean up
  982. if (hOldBitmap)
  983. ::SelectObject(MemDC.GetSafeHdc(), hOldBitmap);
  984. MemDC.DeleteDC();
  985. return (nColours > 0);
  986. }
  987. #ifdef _DEBUG
  988. // Makes trace windows a little bit more informative...
  989. void CDIBSectionLite::_ShowLastError()
  990. {
  991. LPVOID lpMsgBuf;
  992. FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  993. NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  994. (LPTSTR) &lpMsgBuf, 0, NULL);
  995. TRACE1("Last error: %s\n", lpMsgBuf);
  996. LocalFree(lpMsgBuf);
  997. }
  998. #else
  999. void CDIBSectionLite::_ShowLastError() {}
  1000. #endif