EnBitmap.cpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206
  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. BOOL CEnBitmap::ExtendDraw(CDC *pDC,CRect rc, int nX, int nY)
  923. {
  924. CEnBitmap bmp;
  925. if (ExtendDrawImage(bmp,rc,nX,nY))
  926. {
  927. bmp.Draw(pDC,&rc);
  928. return TRUE;
  929. }
  930. return FALSE;
  931. }
  932. BOOL CEnBitmap::ExtendDrawImage(CEnBitmap &bmp,CRect rc, int nX, int nY)
  933. {
  934. CBitmap *OldBmp;
  935. CDC memDC;
  936. CClientDC cdc(0);
  937. memDC.CreateCompatibleDC(&cdc);
  938. bmp.CreateCompatibleBitmap(&cdc, rc.Width() , rc.Height() );
  939. OldBmp = memDC.SelectObject( &bmp );
  940. if (nX==0 && nY==0)
  941. {
  942. StretchDraw(&memDC,&rc,GetRect());
  943. return TRUE;
  944. }
  945. CDC dc;
  946. dc.CreateCompatibleDC(&memDC);
  947. CBitmap * Bmp = dc.SelectObject( this );
  948. //dc.SetStretchBltMode(COLORONCOLOR);
  949. if (nX!=0 && nY==0)
  950. {
  951. //坐上角
  952. memDC.BitBlt( 0, 0, nX, rc.Height(), &dc, 0, 0,
  953. SRCCOPY );
  954. memDC.StretchBlt(nX, 0, rc.Width()-GetWidth(), rc.Height() , &dc,nX, 0, 1, GetHeight(),
  955. SRCCOPY );
  956. //右上角
  957. memDC.BitBlt(rc.right-(GetWidth()-nX), 0, GetWidth()-nX, rc.Height() , &dc,nX, 0,
  958. SRCCOPY );
  959. }
  960. else if (nX==0 && nY!=0)
  961. {
  962. //上角
  963. memDC.BitBlt( 0, 0, rc.Width(), nY, &dc, 0, 0,
  964. SRCCOPY );
  965. memDC.StretchBlt(0, nY, GetWidth(), rc.Height()-GetHeight(), &dc,0, nY, GetWidth(), 1,
  966. SRCCOPY );
  967. //右上角
  968. memDC.BitBlt(0, rc.bottom-(GetHeight()-nY), GetWidth(), GetHeight()-nY , &dc,0, nY,
  969. SRCCOPY );
  970. }
  971. else
  972. {
  973. //坐上角
  974. memDC.StretchBlt( 0, 0, nX, nY, &dc, 0, 0, nX, nY ,
  975. SRCCOPY );
  976. //上中
  977. memDC.StretchBlt(nX, 0, rc.Width()-GetWidth(),nY, &dc, nX, 0, 1, nY ,
  978. SRCCOPY );
  979. //右上角
  980. memDC.StretchBlt(rc.Width()-(GetWidth()-nX), 0, GetWidth()-nX, nY , &dc,nX, 0, GetWidth()-nX, nY,
  981. SRCCOPY );
  982. //左中
  983. memDC.StretchBlt(0, nY, nX,rc.Height()-GetHeight(), &dc, 0, nY, nX, 1 ,
  984. SRCCOPY );
  985. //正中
  986. memDC.StretchBlt(nX, nY, rc.Width()-GetWidth(),rc.Height()-GetHeight(), &dc, nX, nY, 1, 1 ,
  987. SRCCOPY );
  988. //右中
  989. memDC.StretchBlt(rc.Width()-(GetWidth()-nX), nY, GetWidth()-nX,rc.Height()-GetHeight(), &dc, nX, nY, GetWidth()-nX, 1 ,
  990. SRCCOPY );
  991. //左下角
  992. memDC.StretchBlt( 0, rc.Height()-(GetHeight()-nY), nX, GetHeight()-nY, &dc, 0, nY, nX,GetHeight()-nY ,
  993. SRCCOPY );
  994. //下中
  995. memDC.StretchBlt(nX, rc.Height()-(GetHeight()-nY), rc.Width()-GetWidth(),GetHeight()-nY, &dc, nX, nY, 1, GetHeight()-nY ,
  996. SRCCOPY );
  997. //右下角
  998. memDC.StretchBlt( rc.Width()-(GetWidth()-nX), rc.Height()-(GetHeight()-nY), GetWidth()-nX, GetHeight()-nY, &dc, nX, nY, GetWidth()-nX,GetHeight()-nY ,
  999. SRCCOPY );
  1000. }
  1001. dc.SelectObject( Bmp );
  1002. memDC.SelectObject(OldBmp);
  1003. return TRUE;
  1004. }