EnBitmap.cpp 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216
  1. // EnBitmap.cpp: implementation of the CEnBitmap class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "EnBitmap.h"
  6. #include <AFXPRIV.H>
  7. #ifdef _DEBUG
  8. #undef THIS_FILE
  9. static char THIS_FILE[]=__FILE__;
  10. #define new DEBUG_NEW
  11. #endif
  12. const int HIMETRIC_INCH = 2540;
  13. enum
  14. {
  15. FT_BMP,
  16. FT_ICO,
  17. FT_JPG,
  18. FT_GIF,
  19. FT_UNKNOWN
  20. };
  21. //////////////////////////////////////////////////////////////////////
  22. // Construction/Destruction
  23. //////////////////////////////////////////////////////////////////////
  24. CEnBitmap::CEnBitmap()
  25. {
  26. }
  27. CEnBitmap::~CEnBitmap()
  28. {
  29. }
  30. BOOL CEnBitmap::LoadImage(UINT uIDRes, LPCTSTR szResourceType, HMODULE hInst, COLORREF crBack)
  31. {
  32. ASSERT(m_hObject == NULL); // only attach once, detach on destroy
  33. if (m_hObject != NULL)
  34. return FALSE;
  35. return Attach(LoadImageResource(uIDRes, szResourceType, hInst, crBack));
  36. }
  37. BOOL CEnBitmap::LoadImage(LPCTSTR szImagePath, COLORREF crBack)
  38. {
  39. //如果原先存在就去除
  40. if (m_hObject != NULL)
  41. {
  42. DeleteObject();
  43. Detach();
  44. }
  45. return Attach(LoadImageFile(szImagePath, crBack));
  46. }
  47. HBITMAP CEnBitmap::LoadImageFile(LPCTSTR szImagePath, COLORREF crBack)
  48. {
  49. int nType = GetFileType(szImagePath);
  50. switch (nType)
  51. {
  52. // the reason for this is that i suspect it is more efficient to load
  53. // bmps this way since it avoids creating device contexts etc that the
  54. // IPicture methods requires. that method however is still valuable
  55. // since it handles other image types and transparency
  56. case FT_BMP:
  57. return (HBITMAP)::LoadImage(NULL, szImagePath, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
  58. case FT_UNKNOWN:
  59. return NULL;
  60. default: // all the rest
  61. {
  62. USES_CONVERSION;
  63. IPicture* pPicture = NULL;
  64. HBITMAP hbm = NULL;
  65. HRESULT hr = OleLoadPicturePath(T2OLE(szImagePath), NULL, 0, crBack, IID_IPicture, (LPVOID *)&pPicture);
  66. if (pPicture)
  67. {
  68. hbm = ExtractBitmap(pPicture, crBack);
  69. pPicture->Release();
  70. }
  71. return hbm;
  72. }
  73. }
  74. return NULL; // can't get here
  75. }
  76. HBITMAP CEnBitmap::LoadImageResource(UINT uIDRes, LPCTSTR szResourceType, HMODULE hInst, COLORREF crBack)
  77. {
  78. BYTE* pBuff = NULL;
  79. int nSize = 0;
  80. HBITMAP hbm = NULL;
  81. // first call is to get buffer size
  82. if (GetResource(MAKEINTRESOURCE(uIDRes), szResourceType, hInst, 0, nSize))
  83. {
  84. if (nSize > 0)
  85. {
  86. pBuff = new BYTE[nSize];
  87. // this loads it
  88. if (GetResource(MAKEINTRESOURCE(uIDRes), szResourceType, hInst, pBuff, nSize))
  89. {
  90. IPicture* pPicture = LoadFromBuffer(pBuff, nSize);
  91. if (pPicture)
  92. {
  93. hbm = ExtractBitmap(pPicture, crBack);
  94. pPicture->Release();
  95. }
  96. }
  97. delete [] pBuff;
  98. }
  99. }
  100. return hbm;
  101. }
  102. IPicture* CEnBitmap::LoadFromBuffer(BYTE* pBuff, int nSize)
  103. {
  104. bool bResult = false;
  105. HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, nSize);
  106. void* pData = GlobalLock(hGlobal);
  107. memcpy(pData, pBuff, nSize);
  108. GlobalUnlock(hGlobal);
  109. IStream* pStream = NULL;
  110. IPicture* pPicture = NULL;
  111. if (CreateStreamOnHGlobal(hGlobal, TRUE, &pStream) == S_OK)
  112. {
  113. HRESULT hr = OleLoadPicture(pStream, nSize, FALSE, IID_IPicture, (LPVOID *)&pPicture);
  114. pStream->Release();
  115. }
  116. return pPicture; // caller releases
  117. }
  118. BOOL CEnBitmap::GetResource(LPCTSTR lpName, LPCTSTR lpType, HMODULE hInst, void* pResource, int& nBufSize)
  119. {
  120. HRSRC hResInfo;
  121. HANDLE hRes;
  122. LPSTR lpRes = NULL;
  123. int nLen = 0;
  124. bool bResult = FALSE;
  125. // Find the resource
  126. hResInfo = FindResource(hInst, lpName, lpType);
  127. if (hResInfo == NULL)
  128. return false;
  129. // Load the resource
  130. hRes = LoadResource(hInst, hResInfo);
  131. if (hRes == NULL)
  132. return false;
  133. // Lock the resource
  134. lpRes = (char*)LockResource(hRes);
  135. if (lpRes != NULL)
  136. {
  137. if (pResource == NULL)
  138. {
  139. nBufSize = SizeofResource(hInst, hResInfo);
  140. bResult = true;
  141. }
  142. else
  143. {
  144. if (nBufSize >= (int)SizeofResource(hInst, hResInfo))
  145. {
  146. memcpy(pResource, lpRes, nBufSize);
  147. bResult = true;
  148. }
  149. }
  150. UnlockResource(hRes);
  151. }
  152. // Free the resource
  153. FreeResource(hRes);
  154. return bResult;
  155. }
  156. HBITMAP CEnBitmap::ExtractBitmap(IPicture* pPicture, COLORREF crBack)
  157. {
  158. ASSERT(pPicture);
  159. if (!pPicture)
  160. return NULL;
  161. CBitmap bmMem;
  162. CDC dcMem;
  163. CDC* pDC = CWnd::GetDesktopWindow()->GetDC();
  164. if (dcMem.CreateCompatibleDC(pDC))
  165. {
  166. long hmWidth;
  167. long hmHeight;
  168. pPicture->get_Width(&hmWidth);
  169. pPicture->get_Height(&hmHeight);
  170. int nWidth = MulDiv(hmWidth, pDC->GetDeviceCaps(LOGPIXELSX), HIMETRIC_INCH);
  171. int nHeight = MulDiv(hmHeight, pDC->GetDeviceCaps(LOGPIXELSY), HIMETRIC_INCH);
  172. if (bmMem.CreateCompatibleBitmap(pDC, nWidth, nHeight))
  173. {
  174. CBitmap* pOldBM = dcMem.SelectObject(&bmMem);
  175. if (crBack != -1)
  176. dcMem.FillSolidRect(0, 0, nWidth, nHeight, crBack);
  177. HRESULT hr = pPicture->Render(dcMem, 0, 0, nWidth, nHeight, 0, hmHeight, hmWidth, -hmHeight, NULL);
  178. dcMem.SelectObject(pOldBM);
  179. }
  180. }
  181. CWnd::GetDesktopWindow()->ReleaseDC(pDC);
  182. return (HBITMAP)bmMem.Detach();
  183. }
  184. int CEnBitmap::GetFileType(LPCTSTR szImagePath)
  185. {
  186. CString sPath(szImagePath);
  187. sPath.MakeUpper();
  188. if (sPath.Find(".BMP") > 0)
  189. return FT_BMP;
  190. else if (sPath.Find(".ICO") > 0)
  191. return FT_ICO;
  192. else if (sPath.Find(".JPG") > 0 || sPath.Find(".JPEG") > 0)
  193. return FT_JPG;
  194. else if (sPath.Find(".GIF") > 0)
  195. return FT_GIF;
  196. // else
  197. return FT_UNKNOWN;
  198. }
  199. /////////////////////////////////////////////////////////////////////
  200. // Converts a bitmap to a region
  201. //
  202. // BitmapToRegion : Create a region from the "non-transparent" pixels of a bitmap
  203. // Author : Jean-Edouard Lachand-Robert (http://www.geocities.com/Paris/LeftBank/1160/resume.htm), June 1998.
  204. //
  205. // hBmp : Source bitmap
  206. // cTransparentColor : Color base for the "transparent" pixels (default is black)
  207. // cTolerance : Color tolerance for the "transparent" pixels.
  208. //
  209. // A pixel is assumed to be transparent if the value of each of its 3 components (blue, green and red) is
  210. // greater or equal to the corresponding value in cTransparentColor and is lower or equal to the
  211. // corresponding value in cTransparentColor + cTolerance.
  212. //
  213. HRGN CEnBitmap::BitmapToRegion( COLORREF cTransparentColor ,COLORREF cTolerance)
  214. {
  215. HBITMAP hBmp = (HBITMAP)GetSafeHandle();
  216. HRGN hRgn = NULL;
  217. if(hBmp)
  218. {
  219. // Create a memory DC inside which we will scan the bitmap content
  220. HDC hMemDC = CreateCompatibleDC(NULL);
  221. if(hMemDC)
  222. {
  223. // Get bitmap size
  224. BITMAP bm;
  225. ::GetObject(hBmp, sizeof(bm), &bm);
  226. // Create a 32 bits depth bitmap and select it into the memory DC
  227. BITMAPINFOHEADER RGB32BITSBITMAPINFO = {
  228. sizeof(BITMAPINFOHEADER), // biSize
  229. bm.bmWidth, // biWidth;
  230. bm.bmHeight, // biHeight;
  231. 1, // biPlanes;
  232. 32, // biBitCount
  233. BI_RGB, // biCompression;
  234. 0, // biSizeImage;
  235. 0, // biXPelsPerMeter;
  236. 0, // biYPelsPerMeter;
  237. 0, // biClrUsed;
  238. 0 // biClrImportant;
  239. };
  240. VOID * pbits32;
  241. HBITMAP hbm32 = CreateDIBSection(hMemDC, (BITMAPINFO *)&RGB32BITSBITMAPINFO, DIB_RGB_COLORS, &pbits32, NULL, 0);
  242. if(hbm32)
  243. {
  244. HBITMAP holdBmp = (HBITMAP)SelectObject(hMemDC, hbm32);
  245. // Create a DC just to copy the bitmap into the memory DC
  246. HDC hDC = CreateCompatibleDC(hMemDC);
  247. if(hDC)
  248. {
  249. // Get how many bytes per row we have for the bitmap bits (rounded up to 32 bits)
  250. BITMAP bm32;
  251. ::GetObject(hbm32, sizeof(bm32), &bm32);
  252. while(bm32.bmWidthBytes % 4)
  253. bm32.bmWidthBytes++;
  254. // Copy the bitmap into the memory DC
  255. HBITMAP holdBmp = (HBITMAP)SelectObject(hDC, hBmp);
  256. BitBlt(hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, hDC, 0, 0, SRCCOPY);
  257. // For better performances, we will use the ExtCreateRegion() function to create the
  258. // region. This function take a RGNDATA structure on entry. We will add rectangles by
  259. // amount of ALLOC_UNIT number in this structure.
  260. #define ALLOC_UNIT 100
  261. DWORD maxRects = ALLOC_UNIT;
  262. HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects));
  263. RGNDATA *pData = (RGNDATA *)GlobalLock(hData);
  264. pData->rdh.dwSize = sizeof(RGNDATAHEADER);
  265. pData->rdh.iType = RDH_RECTANGLES;
  266. pData->rdh.nCount = pData->rdh.nRgnSize = 0;
  267. SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
  268. // Keep on hand highest and lowest values for the "transparent" pixels
  269. BYTE lr = GetRValue(cTransparentColor);
  270. BYTE lg = GetGValue(cTransparentColor);
  271. BYTE lb = GetBValue(cTransparentColor);
  272. BYTE hr = min(0xff, lr + GetRValue(cTolerance));
  273. BYTE hg = min(0xff, lg + GetGValue(cTolerance));
  274. BYTE hb = min(0xff, lb + GetBValue(cTolerance));
  275. // Scan each bitmap row from bottom to top (the bitmap is inverted vertically)
  276. BYTE *p32 = (BYTE *)bm32.bmBits + (bm32.bmHeight - 1) * bm32.bmWidthBytes;
  277. for(int y = 0; y < bm.bmHeight; y++)
  278. {
  279. // Scan each bitmap pixel from left to right
  280. for(int x = 0; x < bm.bmWidth; x++)
  281. {
  282. // Search for a continuous range of "non transparent pixels"
  283. int x0 = x;
  284. LONG *p = (LONG *)p32 + x;
  285. while(x < bm.bmWidth)
  286. {
  287. BYTE b = GetRValue(*p);
  288. if(b >= lr && b <= hr)
  289. {
  290. b = GetGValue(*p);
  291. if(b >= lg && b <= hg)
  292. {
  293. b = GetBValue(*p);
  294. if(b >= lb && b <= hb)
  295. // This pixel is "transparent"
  296. break;
  297. }
  298. }
  299. p++;
  300. x++;
  301. }
  302. if(x > x0)
  303. {
  304. // Add the pixels (x0, y) to (x, y+1) as a new rectangle in the region
  305. if(pData->rdh.nCount >= maxRects)
  306. {
  307. GlobalUnlock(hData);
  308. maxRects += ALLOC_UNIT;
  309. hData = GlobalReAlloc(hData, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), GMEM_MOVEABLE);
  310. pData = (RGNDATA *)GlobalLock(hData);
  311. }
  312. RECT *pr = (RECT *)&pData->Buffer;
  313. SetRect(&pr[pData->rdh.nCount], x0, y, x, y+1);
  314. if(x0 < pData->rdh.rcBound.left)
  315. pData->rdh.rcBound.left = x0;
  316. if(y < pData->rdh.rcBound.top)
  317. pData->rdh.rcBound.top = y;
  318. if(x > pData->rdh.rcBound.right)
  319. pData->rdh.rcBound.right = x;
  320. if(y+1 > pData->rdh.rcBound.bottom)
  321. pData->rdh.rcBound.bottom = y+1;
  322. pData->rdh.nCount++;
  323. // On Windows98, ExtCreateRegion() may fail if the number of rectangles is too
  324. // large (ie: > 4000). Therefore, we have to create the region by multiple steps.
  325. if(pData->rdh.nCount == 2000)
  326. {
  327. HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);
  328. if(hRgn)
  329. {
  330. CombineRgn(hRgn, hRgn, h, RGN_OR);
  331. ::DeleteObject(h);
  332. }
  333. else
  334. hRgn = h;
  335. pData->rdh.nCount = 0;
  336. SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
  337. }
  338. }
  339. }
  340. // Go to next row (remember, the bitmap is inverted vertically)
  341. p32 -= bm32.bmWidthBytes;
  342. }
  343. // Create or extend the region with the remaining rectangles
  344. HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);
  345. if(hRgn)
  346. {
  347. CombineRgn(hRgn, hRgn, h, RGN_OR);
  348. ::DeleteObject(h);
  349. }
  350. else
  351. hRgn = h;
  352. // Clean up
  353. GlobalFree(hData);
  354. SelectObject(hDC, holdBmp);
  355. DeleteDC(hDC);
  356. }
  357. ::DeleteObject(SelectObject(hMemDC, holdBmp));
  358. }
  359. DeleteDC(hMemDC);
  360. }
  361. }
  362. return hRgn;
  363. }
  364. BOOL CEnBitmap::Draw(CDC *pDC, LPRECT r)
  365. {
  366. CDC dc;
  367. dc.CreateCompatibleDC( pDC );
  368. CBitmap * bmp = dc.SelectObject( this );
  369. pDC->BitBlt( r->left, r->top, r->right - r->left, r->bottom - r->top, &dc, 0, 0 ,
  370. SRCCOPY );
  371. dc.SelectObject( bmp );
  372. return TRUE;
  373. }
  374. // TransparentBlt - Copies a bitmap transparently onto the destination DC
  375. // hdcDest - Handle to destination device context
  376. // nXDest - x-coordinate of destination rectangle's upper-left corner
  377. // nYDest - y-coordinate of destination rectangle's upper-left corner
  378. // nWidth - Width of destination rectangle
  379. // nHeight - height of destination rectangle
  380. // hBitmap - Handle of the source bitmap
  381. // nXSrc - x-coordinate of source rectangle's upper-left corner
  382. // nYSrc - y-coordinate of source rectangle's upper-left corner
  383. // colorTransparent - The transparent color
  384. // hPal - Logical palette to be used with bitmap. Can be NULL
  385. void CEnBitmap::TransparentBlt(CDC &dc,CRect rc,UINT colorTransparent)
  386. {
  387. CDC pDC;
  388. pDC.CreateCompatibleDC(&dc);
  389. HBITMAP hOldBmp = (HBITMAP) ::SelectObject( pDC.m_hDC, m_hObject );
  390. ::TransparentBlt(dc.GetSafeHdc(),rc.left ,rc.top ,rc.Width(),rc.Height(),pDC.GetSafeHdc() ,0,0,GetWidth(),GetHeight(),colorTransparent);
  391. ::SelectObject(pDC.m_hDC,hOldBmp);
  392. pDC.DeleteDC();
  393. }
  394. // DrawGreyScale - Draws a bitmap in Grey scale
  395. // pDC - Pointer to target device context
  396. // hDIB - Handle of device-independent bitmap
  397. //
  398. void CEnBitmap::DrawGreyScale( CDC *pDC )
  399. {
  400. CPalette pal;
  401. CPalette *pOldPalette = 0;
  402. HBITMAP hBmp = (HBITMAP)this->GetSafeHandle();
  403. // allocate memory for extended image information
  404. BITMAPINFO &bmInfo= *(LPBITMAPINFO) new BYTE[ sizeof(BITMAPINFO) + 8 ];
  405. memset( &bmInfo, 0, sizeof(BITMAPINFO) + 8 );
  406. bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  407. // get extended information about image (length, compression, length of color table if exist, ...)
  408. DWORD res = GetDIBits(pDC->GetSafeHdc() , hBmp, 0, GetHeight(), 0, &bmInfo, DIB_RGB_COLORS );
  409. // allocate memory for image data (colors)
  410. LPBYTE pBits = new BYTE[ bmInfo.bmiHeader.biSizeImage + 4 ];
  411. res = GetDIBits( pDC->GetSafeHdc(), hBmp, 0, bmInfo.bmiHeader.biHeight, pBits, &bmInfo, DIB_RGB_COLORS );
  412. int nColors = bmInfo.bmiHeader.biClrUsed ? bmInfo.bmiHeader.biClrUsed :
  413. 1 << bmInfo.bmiHeader.biBitCount;
  414. int nWidth = bmInfo.bmiHeader.biWidth;
  415. int nHeight = bmInfo.bmiHeader.biHeight;
  416. // Compute the address of the bitmap bits
  417. LPVOID lpDIBBits;
  418. if( bmInfo.bmiHeader.biBitCount > 8 )
  419. lpDIBBits = (LPVOID)((LPDWORD)(pBits +
  420. bmInfo.bmiHeader.biClrUsed) +
  421. ((bmInfo.bmiHeader.biCompression == BI_BITFIELDS) ? 3 : 0));
  422. else
  423. lpDIBBits = (LPVOID)(pBits + nColors);
  424. // Create the palette if needed
  425. if( pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE && nColors <= 256 )
  426. {
  427. // The device supports a palette and bitmap has color table
  428. // Allocate memory for a palette
  429. UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * nColors);
  430. LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];
  431. pLP->palVersion = 0x300;
  432. pLP->palNumEntries = nColors;
  433. for( int i=0; i < nColors; i++)
  434. {
  435. int nGrey = Grey( bmInfo.bmiColors[i].rgbRed, bmInfo.bmiColors[i].rgbGreen,
  436. bmInfo.bmiColors[i].rgbBlue );
  437. pLP->palPalEntry[i].peRed = nGrey;
  438. pLP->palPalEntry[i].peGreen = nGrey;
  439. pLP->palPalEntry[i].peBlue = nGrey;
  440. pLP->palPalEntry[i].peFlags = 0;
  441. }
  442. pal.CreatePalette( pLP );
  443. delete[] pLP;
  444. // Select the palette
  445. pOldPalette = pDC->SelectPalette(&pal, FALSE);
  446. pDC->RealizePalette();
  447. }
  448. else
  449. {
  450. // Modify the bitmaps pixels directly
  451. // Note : This ends up changing the DIB. If that is not acceptable then
  452. // copy the DIB and then change the copy rather than the original
  453. if ( bmInfo.bmiHeader.biBitCount == 24 || bmInfo.bmiHeader.biBitCount == 32)
  454. {
  455. BYTE *dst=(BYTE*)lpDIBBits;
  456. int Size=nWidth*nHeight;
  457. while ( Size-- )
  458. {
  459. int nGrey = Grey( dst[2], dst[1], dst[0] );
  460. dst[0]=(BYTE)nGrey;
  461. dst[1]=(BYTE)nGrey;
  462. dst[2]=(BYTE)nGrey;
  463. dst+=4;
  464. }
  465. }
  466. else if ( bmInfo.bmiHeader.biBitCount == 16 )
  467. {
  468. WORD *dst=(WORD*)lpDIBBits;
  469. int Size=nWidth*nHeight;
  470. while ( Size-- )
  471. {
  472. BYTE b = (BYTE)((*dst)&(0x1F));
  473. BYTE g = (BYTE)(((*dst)>>5)&(0x1F));
  474. BYTE r = (BYTE)(((*dst)>>10)&(0x1F));
  475. int nGrey = Grey( r, g, b );
  476. *dst++ = ((WORD)(((BYTE)(nGrey)|((WORD)((BYTE)(nGrey))<<5))|(((DWORD)(BYTE)(nGrey))<<10)));
  477. }
  478. }
  479. }
  480. // Draw the image
  481. ::SetDIBitsToDevice(pDC->m_hDC, // hDC
  482. 0, // XDest
  483. 0, // YDest
  484. nWidth, // nDestWidth
  485. nHeight, // nDestHeight
  486. 0, // XSrc
  487. 0, // YSrc
  488. 0, // nStartScan
  489. nHeight, // nNumScans
  490. lpDIBBits, // lpBits
  491. &bmInfo, // lpBitsInfo
  492. DIB_RGB_COLORS); // wUsage
  493. if ( pOldPalette )
  494. pDC->SelectPalette(pOldPalette, FALSE);
  495. }
  496. //
  497. // DitherBlt : Draw a bitmap dithered (3D grayed effect like disabled buttons in toolbars) into a destination DC
  498. // Author : Jean-Edouard Lachand-Robert (iamwired@geocities.com), June 1997.
  499. //
  500. // hdcDest : destination DC
  501. // nXDest : x coordinate of the upper left corner of the destination rectangle into the DC
  502. // nYDest : y coordinate of the upper left corner of the destination rectangle into the DC
  503. // nWidth : width of the destination rectangle into the DC
  504. // nHeight : height of the destination rectangle into the DC
  505. // hbm : the bitmap to draw (as a part or as a whole)
  506. // nXSrc : x coordinates of the upper left corner of the source rectangle into the bitmap
  507. // nYSrc : y coordinates of the upper left corner of the source rectangle into the bitmap
  508. //
  509. void CEnBitmap::DitherBlt (HDC hdcDest, int nXDest, int nYDest, int nWidth,
  510. int nHeight, HBITMAP hbm, int nXSrc, int nYSrc)
  511. {
  512. ASSERT(hdcDest && hbm);
  513. ASSERT(nWidth > 0 && nHeight > 0);
  514. // Create a generic DC for all BitBlts
  515. HDC hDC = CreateCompatibleDC(hdcDest);
  516. ASSERT(hDC);
  517. if (hDC)
  518. {
  519. // Create a DC for the monochrome DIB section
  520. HDC bwDC = CreateCompatibleDC(hDC);
  521. ASSERT(bwDC);
  522. if (bwDC)
  523. {
  524. // Create the monochrome DIB section with a black and white palette
  525. struct {
  526. BITMAPINFOHEADER bmiHeader;
  527. RGBQUAD bmiColors[2];
  528. } RGBBWBITMAPINFO = {
  529. { // a BITMAPINFOHEADER
  530. sizeof(BITMAPINFOHEADER), // biSize
  531. nWidth, // biWidth;
  532. nHeight, // biHeight;
  533. 1, // biPlanes;
  534. 1, // biBitCount
  535. BI_RGB, // biCompression;
  536. 0, // biSizeImage;
  537. 0, // biXPelsPerMeter;
  538. 0, // biYPelsPerMeter;
  539. 0, // biClrUsed;
  540. 0 // biClrImportant;
  541. },
  542. {
  543. { 0x00, 0x00, 0x00, 0x00 }, { 0xFF, 0xFF, 0xFF, 0x00 }
  544. }
  545. };
  546. VOID *pbitsBW;
  547. HBITMAP hbmBW = CreateDIBSection(bwDC,
  548. (LPBITMAPINFO)&RGBBWBITMAPINFO, DIB_RGB_COLORS, &pbitsBW, NULL, 0);
  549. ASSERT(hbmBW);
  550. if (hbmBW)
  551. {
  552. // Attach the monochrome DIB section and the bitmap to the DCs
  553. SelectObject(bwDC, hbmBW);
  554. SelectObject(hDC, hbm);
  555. // BitBlt the bitmap into the monochrome DIB section
  556. BitBlt(bwDC, 0, 0, nWidth, nHeight, hDC, nXSrc, nYSrc, SRCCOPY);
  557. // Paint the destination rectangle in gray
  558. FillRect(hdcDest, CRect(nXDest, nYDest, nXDest + nWidth, nYDest +
  559. nHeight), GetSysColorBrush(COLOR_3DFACE));
  560. // BitBlt the black bits in the monochrome bitmap into COLOR_3DHILIGHT bits in the destination DC
  561. // The magic ROP comes from the Charles Petzold's book
  562. HBRUSH hb = CreateSolidBrush(GetSysColor(COLOR_3DHILIGHT));
  563. HBRUSH oldBrush = (HBRUSH)SelectObject(hdcDest, hb);
  564. BitBlt(hdcDest, nXDest + 1, nYDest + 1, nWidth, nHeight, bwDC, 0, 0, 0xB8074A);
  565. // BitBlt the black bits in the monochrome bitmap into COLOR_3DSHADOW bits in the destination DC
  566. hb = CreateSolidBrush(GetSysColor(COLOR_3DSHADOW));
  567. ::DeleteObject(SelectObject(hdcDest, hb));
  568. BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, bwDC, 0, 0, 0xB8074A);
  569. ::DeleteObject(SelectObject(hdcDest, oldBrush));
  570. }
  571. VERIFY(DeleteDC(bwDC));
  572. }
  573. VERIFY(DeleteDC(hDC));
  574. }
  575. }
  576. // CreateReservedPalette - Create a palette using the PC_RESERVED flag
  577. // Limit the colors to 236 colors
  578. // Returns - Handle to a palette object
  579. // hDIB - Handle to a device-independent bitmap
  580. //
  581. HPALETTE CEnBitmap::CreateReservedPalette(CDC *pDC)
  582. {
  583. HPALETTE hPal = NULL; // handle to a palette
  584. HBITMAP hBmp = (HBITMAP)this->GetSafeHandle();
  585. // get image properties
  586. //BITMAP bmp = { 0 };
  587. //::GetObject( hBmp, sizeof(BITMAP), &bmp );
  588. // allocate memory for extended image information
  589. BITMAPINFO &bmInfo= *(LPBITMAPINFO) new BYTE[ sizeof(BITMAPINFO) + 8 ];
  590. memset( &bmInfo, 0, sizeof(BITMAPINFO) + 8 );
  591. bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  592. // get extended information about image (length, compression, length of color table if exist, ...)
  593. DWORD res = GetDIBits(pDC->GetSafeHdc() , hBmp, 0, GetHeight(), 0, &bmInfo, DIB_RGB_COLORS );
  594. // allocate memory for image data (colors)
  595. LPBYTE pBits = new BYTE[ bmInfo.bmiHeader.biSizeImage + 4 ];
  596. res = GetDIBits( pDC->GetSafeHdc(), hBmp, 0, bmInfo.bmiHeader.biHeight, pBits, &bmInfo, DIB_RGB_COLORS );
  597. int nWidth = bmInfo.bmiHeader.biWidth;
  598. int nHeight = bmInfo.bmiHeader.biHeight;
  599. int nColors = bmInfo.bmiHeader.biClrUsed ? bmInfo.bmiHeader.biClrUsed :
  600. 1 << bmInfo.bmiHeader.biBitCount;
  601. if( nColors > 256 )
  602. return NULL; // No Palette
  603. //allocate memory block for logical palette
  604. UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * nColors);
  605. LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];
  606. // Initialize the palette version
  607. pLP->palVersion = 0x300;
  608. // If it is a 256 color DIB, then let's find the most used 236 colors
  609. // and make a palette out of those colors
  610. if (nColors > 236)
  611. {
  612. typedef struct _tagBESTCOLORS
  613. {
  614. DWORD dwColorCnt; //Count of how many times a color is used
  615. BOOL bDontUse; //Should we use this color?
  616. } BESTCOLORS;
  617. BESTCOLORS bc[256];
  618. BYTE dwLeastUsed[20]; // Least used color indices
  619. LPSTR lpBits; // pointer to D.I. bits of a DIB
  620. int nWidth, nHeight, nBytesPerLine, cx, cy;
  621. ::ZeroMemory( bc, 256*sizeof(BESTCOLORS));
  622. lpBits = (LPSTR)(pBits + nColors);
  623. nWidth = bmInfo.bmiHeader.biWidth;
  624. nHeight = bmInfo.bmiHeader.biHeight;
  625. nBytesPerLine = ((((bmInfo.bmiHeader.biWidth *
  626. bmInfo.bmiHeader.biBitCount) + 31) & ~31) / 8);
  627. // Traverse through all of the bits in the bitmap and place the
  628. // color count of each color in the BESTCOLORS array
  629. for (cy = 0; cy < nHeight; cy++)
  630. for (cx = 0; cx < nWidth; cx++)
  631. bc[*(LPBYTE)(lpBits+cy*nBytesPerLine+cx)].dwColorCnt++;
  632. // Let's arbitrarily place the first few colors in the "Least Used" list.
  633. int nReject = nColors - 236;
  634. for (cx=0; cx < nReject; cx++)
  635. {
  636. bc[cx].bDontUse = TRUE;
  637. dwLeastUsed[cx] = cx;
  638. }
  639. // Now, let's traverse through all of the colors and
  640. // sort out the least used
  641. for (cx=0; cx < nColors; cx++)
  642. {
  643. cy = 0;
  644. while ((!(bc[cx].bDontUse)) && cy < nReject)
  645. {
  646. if (bc[cx].dwColorCnt < bc[dwLeastUsed[cy]].dwColorCnt)
  647. {
  648. bc[dwLeastUsed[cy]].bDontUse = FALSE;
  649. dwLeastUsed[cy] = cx;
  650. bc[cx].bDontUse = TRUE;
  651. }
  652. cy++;
  653. }
  654. }
  655. // We want only 236 colors, so that the 20 system colors
  656. // are left untouched
  657. pLP->palNumEntries = 236;
  658. cx = 0;
  659. for(int i = 0; i < nColors; i++)
  660. {
  661. // Should we use this color?
  662. if (!((bc[i].bDontUse)))
  663. {
  664. pLP->palPalEntry[cx].peRed = bmInfo.bmiColors[i].rgbRed;
  665. pLP->palPalEntry[cx].peGreen =
  666. bmInfo.bmiColors[i].rgbGreen;
  667. pLP->palPalEntry[cx].peBlue = bmInfo.bmiColors[i].rgbBlue;
  668. pLP->palPalEntry[cx].peFlags = PC_RESERVED;
  669. cx++;
  670. }
  671. }
  672. }
  673. else if (nColors)
  674. {
  675. // We have enough room for all the colors
  676. pLP->palNumEntries = nColors;
  677. // Copy the colors
  678. for(int i = 0; i < nColors; i++)
  679. {
  680. pLP->palPalEntry[i].peRed = bmInfo.bmiColors[i].rgbRed;
  681. pLP->palPalEntry[i].peGreen = bmInfo.bmiColors[i].rgbGreen;
  682. pLP->palPalEntry[i].peBlue = bmInfo.bmiColors[i].rgbBlue;
  683. pLP->palPalEntry[i].peFlags = PC_RESERVED;
  684. }
  685. }
  686. hPal = CreatePalette( pLP );
  687. delete[] pLP;
  688. // return handle to DIB's palette
  689. return hPal;
  690. }
  691. // FadeColorToGrayScale - Draws a bitmap in color slowly turns it to grayscale
  692. // pDC - Pointer to target device context
  693. // hDIB - Handle of device-independent bitmap
  694. // xDest - x-coordinate of upper-left corner of dest. rect.
  695. // yDest - y-coordinate of upper-left corner of dest. rect.
  696. // nLoops - How many loops to fade the image into color
  697. // nDelay - Delay in milli-seconds between each loop
  698. //
  699. void CEnBitmap::FadeColorToGrayScale( CDC *pDC,int xDest, int yDest, int nLoops,
  700. int nDelay )
  701. {
  702. CPalette pal;
  703. CPalette *pOldPalette;
  704. PALETTEENTRY peAnimate[256];
  705. PALETTEENTRY peGray[256];
  706. PALETTEENTRY peOriginal[256];
  707. HBITMAP hBmp = (HBITMAP)this->GetSafeHandle();
  708. // get image properties
  709. //BITMAP bmp = { 0 };
  710. //::GetObject( hBmp, sizeof(BITMAP), &bmp );
  711. // allocate memory for extended image information
  712. BITMAPINFO &bmInfo= *(LPBITMAPINFO) new BYTE[ sizeof(BITMAPINFO) + 8 ];
  713. memset( &bmInfo, 0, sizeof(BITMAPINFO) + 8 );
  714. bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  715. // get extended information about image (length, compression, length of color table if exist, ...)
  716. DWORD res = GetDIBits(pDC->GetSafeHdc() , hBmp, 0, GetHeight(), 0, &bmInfo, DIB_RGB_COLORS );
  717. // allocate memory for image data (colors)
  718. LPBYTE pBits = new BYTE[ bmInfo.bmiHeader.biSizeImage + 4 ];
  719. res = GetDIBits( pDC->GetSafeHdc(), hBmp, 0, bmInfo.bmiHeader.biHeight, pBits, &bmInfo, DIB_RGB_COLORS );
  720. int nColors = bmInfo.bmiHeader.biClrUsed ? bmInfo.bmiHeader.biClrUsed :
  721. 1 << bmInfo.bmiHeader.biBitCount;
  722. int nWidth = bmInfo.bmiHeader.biWidth;
  723. int nHeight = bmInfo.bmiHeader.biHeight;
  724. // Compute the address of the bitmap bits
  725. LPVOID lpDIBBits;
  726. if( bmInfo.bmiHeader.biBitCount > 8 )
  727. lpDIBBits = (LPVOID)((LPDWORD)(pBits +
  728. bmInfo.bmiHeader.biClrUsed) +
  729. ((bmInfo.bmiHeader.biCompression == BI_BITFIELDS) ? 3 : 0));
  730. else
  731. lpDIBBits = (LPVOID)(pBits + nColors);
  732. int nReservedColors = nColors > 236 ? 236 : nColors;
  733. // Create the palette if needed
  734. if( pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE && nColors <= 256 )
  735. {
  736. // The device supports a palette and bitmap has color table
  737. HPALETTE hPal = CreateReservedPalette(pDC);
  738. pal.Attach( hPal );
  739. // Now save the original colors and get the grayscale colors
  740. pal.GetPaletteEntries(0, nReservedColors, (LPPALETTEENTRY)&peOriginal);
  741. for( int i=0; i < nReservedColors; i++)
  742. {
  743. int nGray = Grey( peOriginal[i].peRed, peOriginal[i].peGreen , peOriginal[i].peBlue );
  744. peGray[i].peRed = nGray;
  745. peGray[i].peGreen = nGray;
  746. peGray[i].peBlue = nGray;
  747. }
  748. // Select the palette
  749. pOldPalette = pDC->SelectPalette(&pal, FALSE);
  750. pDC->RealizePalette();
  751. ::SetDIBitsToDevice(pDC->m_hDC, xDest, yDest, nWidth, nHeight, 0, 0, 0,
  752. nHeight, lpDIBBits, (LPBITMAPINFO)&bmInfo, DIB_RGB_COLORS);
  753. // Now animate palette to set the image to grayscale
  754. for(int i=1; i <= nLoops; i++ )
  755. {
  756. for (int j = 0; j< nColors; j++)
  757. {
  758. peAnimate[j].peRed = peOriginal[j].peRed -
  759. ((peOriginal[j].peRed -peGray[j].peRed)*i)/nLoops;
  760. peAnimate[j].peGreen = peOriginal[j].peGreen -
  761. ((peOriginal[j].peGreen-peGray[j].peGreen)*i)
  762. /nLoops;
  763. peAnimate[j].peBlue = peOriginal[j].peBlue -
  764. ((peOriginal[j].peBlue -peGray[j].peBlue)*i)/nLoops;
  765. peAnimate[j].peFlags = peOriginal[j].peFlags;
  766. }
  767. pal.AnimatePalette(0, nColors, (LPPALETTEENTRY)&peAnimate);
  768. // Delay...
  769. Sleep(nDelay);
  770. }
  771. // Select the old palette back
  772. pDC->SelectPalette(pOldPalette, FALSE);
  773. }
  774. else if( (pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE) == 0 && nColors <= 256 )
  775. {
  776. // Now change the image to grayscale
  777. for(int i=1; i <= nLoops; i++ )
  778. {
  779. BYTE *dst=(BYTE*)lpDIBBits;
  780. int Size=nWidth*nHeight;
  781. while ( Size-- )
  782. {
  783. int nGrey = Grey( dst[2], dst[1], dst[0] );
  784. dst[2]=(BYTE)dst[2] -((dst[2] -nGrey)*i)/nLoops;
  785. dst[1]=(BYTE)dst[1] -((dst[1] -nGrey)*i)/nLoops;
  786. dst[0]=(BYTE)dst[0] -((dst[0] -nGrey)*i)/nLoops;
  787. dst+=4;
  788. }
  789. // Draw the image again
  790. ::SetDIBitsToDevice(pDC->m_hDC, xDest, yDest, nWidth, nHeight, 0,
  791. 0, 0, nHeight, lpDIBBits, (LPBITMAPINFO)&bmInfo,
  792. DIB_RGB_COLORS);
  793. // Delay...
  794. Sleep(nDelay);
  795. }
  796. }
  797. else
  798. {
  799. ::SetDIBitsToDevice(pDC->m_hDC, xDest, yDest, nWidth, nHeight, 0, 0, 0,
  800. nHeight, lpDIBBits, (LPBITMAPINFO)&bmInfo, DIB_RGB_COLORS);
  801. }
  802. }
  803. void CEnBitmap::AlphaDisplay(CDC *pDC, BYTE bAlpha)
  804. {
  805. CDC dc;
  806. dc.CreateCompatibleDC( pDC );
  807. CBitmap * bmp = dc.SelectObject( this );
  808. BLENDFUNCTION rBlendProps;
  809. rBlendProps.BlendOp = AC_SRC_OVER;
  810. rBlendProps.BlendFlags = 0;
  811. rBlendProps.AlphaFormat = 0;
  812. rBlendProps.SourceConstantAlpha = bAlpha;
  813. BITMAP bmInfo;
  814. ::GetObject(m_hObject, sizeof(BITMAP), &bmInfo );
  815. INT nWidth, nHeigh;
  816. nWidth = bmInfo.bmWidth;
  817. nHeigh = bmInfo.bmHeight;
  818. AlphaBlend(pDC->m_hDC, 0, 0, nWidth, nHeigh, dc.m_hDC , 0, 0,
  819. nWidth, nHeigh, rBlendProps );
  820. dc.SelectObject( bmp );
  821. }
  822. /* ExtCreateRegion replacement */
  823. HRGN CEnBitmap::CreateRegionExt(DWORD nCount, CONST RGNDATA *pRgnData )
  824. {
  825. HRGN hRgn=CreateRectRgn(0, 0, 0, 0);
  826. const DWORD RDHDR = sizeof(RGNDATAHEADER);
  827. ASSERT( hRgn!=NULL );
  828. LPRECT pRects = (LPRECT)((LPBYTE)pRgnData + RDHDR);
  829. for(int i=0;i<(int)nCount;i++)
  830. {
  831. HRGN hr=CreateRectRgn(pRects[i].left, pRects[i].top, pRects[i].right, pRects[i].bottom);
  832. VERIFY(CombineRgn(hRgn, hRgn, hr, RGN_OR)!=ERROR);
  833. if (hr)
  834. ::DeleteObject(hr);
  835. }
  836. ASSERT( hRgn!=NULL );
  837. return hRgn;
  838. }
  839. ///////////////////////////////////////////////////////////////////
  840. // InflateRegion - Inflates a region by the x and y values
  841. // specified in nXInflate and nYInflate
  842. // Creates a new region that represents the inflated region
  843. // (retains the contents of the old region)
  844. // Returns NULL if unsuccessfull
  845. HRGN CEnBitmap::InflateRegion(HRGN hRgn, int nXInflate, int nYInflate)
  846. {
  847. // Local Variables
  848. LPRGNDATA lpData; // The RGNDATA structure
  849. LPRECT lpRect; // Pointer to the array of RECT structures
  850. DWORD BufSize; // The amount of memory required
  851. DWORD i; // General index variable
  852. HRGN hRgnNew; // The newly created region
  853. // Get the number of rectangles in the region
  854. BufSize = GetRegionData(hRgn, 0, NULL);
  855. if(BufSize == 0)
  856. return NULL;
  857. // Allocate memory for the RGNDATA structure
  858. lpData = (LPRGNDATA)malloc(BufSize);
  859. // Set the location of the RECT structures
  860. lpRect = (LPRECT)(lpData->Buffer);
  861. // Get the region data
  862. if(!GetRegionData(hRgn, BufSize, lpData))
  863. {
  864. free(lpData);
  865. return NULL;
  866. }
  867. // Expand (or contract) all the rectangles in the data
  868. for(i=0; i<lpData->rdh.nCount; i++)
  869. InflateRect(&lpRect[i], nXInflate, nYInflate);
  870. // Create the new region
  871. hRgnNew = CreateRegionExt(lpData->rdh.nCount, lpData);
  872. free((void*)lpData);
  873. return hRgnNew;
  874. }
  875. BOOL CEnBitmap::StretchDraw(CDC *pDC, LPRECT r, LPRECT sr )
  876. {
  877. if ( !r )
  878. return FALSE;
  879. CDC dc;
  880. dc.CreateCompatibleDC( pDC );
  881. CBitmap * bmp = dc.SelectObject( this );
  882. //pDC->SetStretchBltMode(COLORONCOLOR);
  883. if ( !sr )
  884. pDC->StretchBlt( r->left, r->top, r->right, r->bottom, &dc, 0, 0, GetWidth(), GetHeight() ,
  885. SRCCOPY );
  886. else
  887. pDC->StretchBlt( r->left, r->top, r->right - r->left, r->bottom - r->top, &dc, sr->left, sr->top,
  888. sr->right - sr->left, sr->bottom - sr->top,
  889. SRCCOPY );
  890. dc.SelectObject( bmp );
  891. return TRUE;
  892. }
  893. BOOL CEnBitmap::DrawImage(CEnBitmap &bmp,int nX,int nY,int nCol,int nRow)
  894. {
  895. nX-=1;
  896. nY-=1;
  897. //单个图片的长和宽
  898. int w = GetWidth()/nCol;
  899. int h = GetHeight()/nRow;
  900. CBitmap *OldBmp;
  901. CDC memDC;
  902. CClientDC dc(0);
  903. memDC.CreateCompatibleDC(&dc);
  904. bmp.CreateCompatibleBitmap(&dc, w, h);
  905. OldBmp = memDC.SelectObject( &bmp );
  906. StretchDraw(&memDC, CRect( 0, 0, w, h ),CRect(GetWidth()*nX/nCol, GetHeight()*nY/nRow, GetWidth()*nX/nCol+w ,GetHeight()*nY/nRow+h ));
  907. memDC.SelectObject(OldBmp);
  908. return TRUE;
  909. }
  910. CRect CEnBitmap::GetRect()
  911. {
  912. return CRect(0,0,GetWidth(),GetHeight());
  913. }
  914. HBITMAP CEnBitmap::SetBitmap(HBITMAP hBitmap)
  915. {
  916. CEnBitmap *pBmp=(CEnBitmap *)CEnBitmap::FromHandle(hBitmap);
  917. HBITMAP hBmp=(HBITMAP)this->Detach();
  918. this->DeleteObject();
  919. pBmp->DrawImage(*this,1,1,1,1);
  920. return hBmp;
  921. }
  922. /************************************************************************/
  923. /*
  924. 参数:
  925. pDC:控件的DC;
  926. rc: 控件的大小;
  927. nX:
  928. nY:
  929. */
  930. /************************************************************************/
  931. BOOL CEnBitmap::ExtendDraw(CDC *pDC,CRect rc, int nX, int nY)
  932. {
  933. CEnBitmap bmp;
  934. if (ExtendDrawImage(bmp,rc,nX,nY))
  935. {
  936. bmp.Draw(pDC,&rc);
  937. return TRUE;
  938. }
  939. return FALSE;
  940. }
  941. BOOL CEnBitmap::ExtendDrawImage(CEnBitmap &bmp,CRect rc, int nX, int nY)
  942. {
  943. CBitmap *OldBmp;
  944. CDC memDC;
  945. CClientDC cdc(0);
  946. // CreateCompatibleDC函数功能:该函数创建一个与指定设备兼容的内存设备上下文环境(DC)。
  947. /*参数:
  948. hdc:现有设备上下文环境的句柄,如果该句柄为NULL,该函数创建一个与应用程序的当前显示器兼容的内存设备上下文环境。*/
  949. memDC.CreateCompatibleDC(&cdc);
  950. //CreateCompatibleBitmap函数功能:该函数创建与指定的设备环境相关的设备兼容的位图。
  951. /*参数:
  952. hdc: 设备环境句柄。
  953. nWidth:指定位图的宽度,单位为像素。
  954. nHeight:指定位图的高度,单位为像素。
  955. 返回值:如果函数执行成功,那么返回值是位图的句柄;如果函数执行失败,那么返回值为NULL。若想获取更多错误信息,请调用GetLastError。
  956. 备注:由CreateCompatibleBitmap函数创建的位图的颜色格式与由参数hdc标识的设备的颜色格式匹配。该位图可以选入任意一个与原设备兼容的内存设备环境中。由于内存设备环境允许彩色和单色两种位图。因此当指定的设备环境是内存设备环境时,由CreateCompatibleBitmap函数返回的位图格式不一定相同。然而为非内存设备环境创建的兼容位图通常拥有相同的颜色格式,并且使用与指定的设备环境一样的色彩调色板。
  957. 当你不再需要这个位图的时候,调用DeleteObject删除它。
  958. */
  959. bmp.CreateCompatibleBitmap(&cdc, rc.Width() , rc.Height() );
  960. OldBmp = memDC.SelectObject( &bmp );
  961. if (nX==0 && nY==0)
  962. {
  963. StretchDraw(&memDC,&rc,GetRect());
  964. return TRUE;
  965. }
  966. CDC dc;
  967. dc.CreateCompatibleDC(&memDC);
  968. CBitmap * Bmp = dc.SelectObject( this );
  969. //dc.SetStretchBltMode(COLORONCOLOR);
  970. if (nX!=0 && nY==0)
  971. {
  972. //坐上角
  973. memDC.BitBlt( 0, 0, nX, rc.Height(), &dc, 0, 0, SRCCOPY );
  974. // 中间部分,以1像素宽来填充;
  975. memDC.StretchBlt(nX, 0, rc.Width()-GetWidth(), rc.Height() , &dc,nX, 0, 1, GetHeight(),SRCCOPY );
  976. //右上角
  977. memDC.BitBlt(rc.right-(GetWidth()-nX), 0, GetWidth()-nX, rc.Height() , &dc,nX, 0,SRCCOPY );
  978. }
  979. else if (nX==0 && nY!=0)
  980. {
  981. //上角
  982. memDC.BitBlt( 0, 0, rc.Width(), nY, &dc, 0, 0,SRCCOPY );
  983. memDC.StretchBlt(0, nY, GetWidth(), rc.Height()-GetHeight(), &dc,0, nY, GetWidth(), 1,SRCCOPY );
  984. //右上角
  985. memDC.BitBlt(0, rc.bottom-(GetHeight()-nY), GetWidth(), GetHeight()-nY , &dc,0, nY, SRCCOPY );
  986. }
  987. else
  988. {
  989. //坐上角
  990. memDC.StretchBlt( 0, 0, nX, nY, &dc, 0, 0, nX, nY , SRCCOPY );
  991. //上中
  992. memDC.StretchBlt(nX, 0, rc.Width()-GetWidth(),nY, &dc, nX, 0, 1, nY ,SRCCOPY );
  993. //右上角
  994. memDC.StretchBlt(rc.Width()-(GetWidth()-nX), 0, GetWidth()-nX, nY , &dc,nX, 0, GetWidth()-nX, nY,SRCCOPY );
  995. //左中
  996. memDC.StretchBlt(0, nY, nX,rc.Height()-GetHeight(), &dc, 0, nY, nX, 1 , SRCCOPY );
  997. //正中
  998. memDC.StretchBlt(nX, nY, rc.Width()-GetWidth(),rc.Height()-GetHeight(), &dc, nX, nY, 1, 1 , SRCCOPY );
  999. //右中
  1000. memDC.StretchBlt(rc.Width()-(GetWidth()-nX), nY, GetWidth()-nX,rc.Height()-GetHeight(), &dc, nX, nY, GetWidth()-nX, 1 , SRCCOPY );
  1001. //左下角
  1002. memDC.StretchBlt( 0, rc.Height()-(GetHeight()-nY), nX, GetHeight()-nY, &dc, 0, nY, nX,GetHeight()-nY ,SRCCOPY );
  1003. //下中
  1004. memDC.StretchBlt(nX, rc.Height()-(GetHeight()-nY), rc.Width()-GetWidth(),GetHeight()-nY, &dc, nX, nY, 1, GetHeight()-nY ,SRCCOPY );
  1005. //右下角
  1006. memDC.StretchBlt( rc.Width()-(GetWidth()-nX), rc.Height()-(GetHeight()-nY), GetWidth()-nX, GetHeight()-nY, &dc, nX, nY, GetWidth()-nX,GetHeight()-nY , SRCCOPY );
  1007. }
  1008. dc.SelectObject( Bmp );
  1009. memDC.SelectObject(OldBmp);
  1010. return TRUE;
  1011. }