EnBitmap.cpp 35 KB

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