EnBitmap.cpp 35 KB

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