BitmapEx.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  1. // BitmapEx.cpp: implementation of the CBitmapEx class.
  2. //
  3. // History:
  4. // 2002.11.23
  5. // copy from kdphoto projects
  6. //
  7. //
  8. //
  9. //
  10. //////////////////////////////////////////////////////////////////////
  11. #include "stdafx.h"
  12. #include "BitmapEx.h"
  13. #ifdef _DEBUG
  14. #undef THIS_FILE
  15. static char THIS_FILE[]=__FILE__;
  16. #define new DEBUG_NEW
  17. #endif
  18. const int HIMETRIC_INCH = 2540;
  19. // TransparentBlt - Copies a bitmap transparently onto the destination DC
  20. // hdcDest - Handle to destination device context
  21. // nXDest - x-coordinate of destination rectangle's upper-left corner
  22. // nYDest - y-coordinate of destination rectangle's upper-left corner
  23. // nWidth - Width of destination rectangle
  24. // nHeight - height of destination rectangle
  25. // hBitmap - Handle of the source bitmap
  26. // nXSrc - x-coordinate of source rectangle's upper-left corner
  27. // nYSrc - y-coordinate of source rectangle's upper-left corner
  28. // colorTransparent - The transparent color
  29. // hPal - Logical palette to be used with bitmap. Can be NULL
  30. void MyTransparentBlt( HDC hdcDest, int nXDest, int nYDest, int nWidth,
  31. int nHeight, HBITMAP hBitmap, int nXSrc, int nYSrc,
  32. COLORREF colorTransparent, HPALETTE hPal )
  33. {
  34. /* CDC dc;
  35. dc.Attach (hdcDest);
  36. CDC memdc, maskdc;
  37. CBitmap Image, *oldImage;
  38. CBitmap MaskImage, *oldMaskImage;
  39. memdc.CreateCompatibleDC (&dc);
  40. maskdc.CreateCompatibleDC (&dc);
  41. Image.Attach (hBitmap);
  42. MaskImage.CreateBitmap (nWidth, nHeight, 1, 1, NULL);
  43. oldImage=memdc.SelectObject (&Image);
  44. oldMaskImage=maskdc.SelectObject (&MaskImage);
  45. memdc.SetBkColor (colorTransparent);
  46. maskdc.BitBlt (0, 0, nWidth, nHeight, &memdc, 0, 0, SRCCOPY);
  47. memdc.SetBkColor (RGB(0,0,0));
  48. memdc.SetTextColor (RGB(255,255,255));
  49. memdc.BitBlt (0, 0, nWidth, nHeight, &maskdc, 0, 0, SRCAND);
  50. dc.BitBlt (nXDest, nYDest, nWidth, nHeight, &maskdc, 0, 0, SRCAND);
  51. dc.BitBlt (nXDest, nYDest, nWidth, nHeight, &memdc, 0, 0, SRCPAINT);
  52. memdc.SelectObject (oldImage);
  53. maskdc.SelectObject (oldMaskImage);
  54. Image.Detach ();
  55. dc.Detach ();*/
  56. CDC dc, memDC, maskDC, tempDC;
  57. dc.Attach( hdcDest );
  58. maskDC.CreateCompatibleDC(&dc);
  59. CBitmap maskBitmap;
  60. //add these to store return of SelectObject() calls
  61. CBitmap* pOldMemBmp = NULL;
  62. CBitmap* pOldMaskBmp = NULL;
  63. HBITMAP hOldTempBmp = NULL;
  64. memDC.CreateCompatibleDC(&dc);
  65. tempDC.CreateCompatibleDC(&dc);
  66. CBitmap bmpImage;
  67. bmpImage.CreateCompatibleBitmap( &dc, nWidth, nHeight );
  68. pOldMemBmp = memDC.SelectObject( &bmpImage );
  69. // Select and realize the palette
  70. if( dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE && hPal )
  71. {
  72. ::SelectPalette( dc, hPal, FALSE );
  73. dc.RealizePalette();
  74. ::SelectPalette( memDC, hPal, FALSE );
  75. }
  76. hOldTempBmp = (HBITMAP) ::SelectObject( tempDC.m_hDC, hBitmap );
  77. memDC.BitBlt( 0,0,nWidth, nHeight, &tempDC, nXSrc, nYSrc, SRCCOPY );
  78. // Create monochrome bitmap for the mask
  79. maskBitmap.CreateBitmap( nWidth, nHeight, 1, 1, NULL );
  80. pOldMaskBmp = maskDC.SelectObject( &maskBitmap );
  81. memDC.SetBkColor( colorTransparent );
  82. // Create the mask from the memory DC
  83. maskDC.BitBlt( 0, 0, nWidth, nHeight, &memDC,
  84. 0, 0, SRCCOPY );
  85. // Set the background in memDC to black. Using SRCPAINT with black
  86. // and any other color results in the other color, thus making
  87. // black the transparent color
  88. memDC.SetBkColor(RGB(0,0,0));
  89. memDC.SetTextColor(RGB(255,255,255));
  90. memDC.BitBlt(0, 0, nWidth, nHeight, &maskDC, 0, 0, SRCAND);
  91. // Set the foreground to black. See comment above.
  92. dc.SetBkColor(RGB(255,255,255));
  93. dc.SetTextColor(RGB(0,0,0));
  94. dc.BitBlt(nXDest, nYDest, nWidth, nHeight, &maskDC, 0, 0, SRCAND);
  95. // Combine the foreground with the background
  96. dc.BitBlt(nXDest, nYDest, nWidth, nHeight, &memDC,
  97. 0, 0, SRCPAINT);
  98. if (hOldTempBmp)
  99. ::SelectObject( tempDC.m_hDC, hOldTempBmp);
  100. if (pOldMaskBmp)
  101. maskDC.SelectObject( pOldMaskBmp );
  102. if (pOldMemBmp)
  103. memDC.SelectObject( pOldMemBmp );
  104. dc.Detach();
  105. }
  106. /*
  107. void MyTransparentBlt( HDC hdcDest, int nXDest, int nYDest, int nWidth,
  108. int nHeight, HBITMAP hBitmap, int nXSrc, int nYSrc,
  109. COLORREF colorTransparent, HPALETTE hPal )
  110. {
  111. CDC *pDC =CDC::FromHandle(hdcDest);
  112. CDC ImageDC,MaskDC;
  113. CBitmap Image,*pOldImage;
  114. CBitmap maskBitmap,*pOldMaskDCBitmap ;
  115. Image.Attach (hBitmap);
  116. ImageDC.CreateCompatibleDC(pDC);
  117. pOldImage=ImageDC.SelectObject(&Image);
  118. MaskDC.CreateCompatibleDC(pDC);
  119. maskBitmap.CreateBitmap( nWidth, nHeight, 1, 1, NULL );
  120. pOldMaskDCBitmap = MaskDC.SelectObject( &maskBitmap );
  121. ImageDC.SetBkColor(colorTransparent);
  122. MaskDC.BitBlt( 0, 0, nWidth, nHeight, &ImageDC, 0, 0, SRCCOPY );
  123. ImageDC.SetBkColor(RGB(0,0,0));
  124. ImageDC.SetTextColor(RGB(255,255,255));
  125. ImageDC.BitBlt(0, 0, nWidth, nHeight, &MaskDC, 0, 0, SRCAND);
  126. pDC->BitBlt(nXDest,nYDest,nWidth, nHeight, &MaskDC, 0, 0, SRCAND);
  127. pDC->BitBlt(nXDest,nYDest,nWidth, nHeight, &ImageDC, 0, 0,SRCPAINT);
  128. MaskDC.SelectObject(pOldMaskDCBitmap);
  129. ImageDC.SelectObject(pOldImage);
  130. Image.Detach ();
  131. }*/
  132. //////////////////////////////////////////////////////////////////////
  133. // Construction/Destruction
  134. //////////////////////////////////////////////////////////////////////
  135. CBitmapEx::CBitmapEx()
  136. {
  137. }
  138. CBitmapEx::~CBitmapEx()
  139. {
  140. }
  141. BOOL CBitmapEx::StretchDraw(CDC *pDC, LPRECT r, LPRECT sr )
  142. {
  143. if ( !r ) return FALSE;
  144. CDC dc;
  145. dc.CreateCompatibleDC( pDC );
  146. CBitmap * bmp = dc.SelectObject( this );
  147. pDC->SetStretchBltMode(COLORONCOLOR);
  148. if ( !sr )
  149. pDC->StretchBlt( r->left, r->top, r->right, r->bottom, &dc, 0, 0, GetWidth(), GetHeight() ,
  150. SRCCOPY );
  151. else
  152. pDC->StretchBlt( r->left, r->top, r->right - r->left, r->bottom - r->top, &dc, sr->left, sr->top,
  153. sr->right - sr->left, sr->bottom - sr->top,
  154. SRCCOPY );
  155. dc.SelectObject( bmp );
  156. return TRUE;
  157. }
  158. BOOL CBitmapEx::StretchDraw(CDC *pDC, LPRECT r)
  159. {
  160. CDC dc;
  161. dc.CreateCompatibleDC( pDC );
  162. CBitmap * bmp = dc.SelectObject( this );
  163. // pDC->StretchBlt( r->left, r->top, r->right-r->left, r->bottom -r->top , &dc, 0, 0, GetWidth(), GetHeight() ,SRCCOPY );
  164. pDC->StretchBlt( r->left, r->top, r->right-r->left, GetHeight() , &dc, 0, 0, GetWidth(), GetHeight() ,SRCCOPY );
  165. dc.SelectObject( bmp );
  166. return TRUE;
  167. }
  168. BOOL CBitmapEx::StretchDraw2(CDC *pDC, LPRECT r)
  169. {
  170. CDC dc;
  171. dc.CreateCompatibleDC( pDC );
  172. CBitmap * bmp = dc.SelectObject( this );
  173. // pDC->StretchBlt( r->left, r->top, r->right-r->left, r->bottom -r->top , &dc, 0, 0, GetWidth(), GetHeight() ,SRCCOPY );
  174. pDC->StretchBlt( r->left, r->top, GetWidth(), r->bottom -r->top , &dc, 0, 0, GetWidth(), GetHeight() ,SRCCOPY );
  175. dc.SelectObject( bmp );
  176. return TRUE;
  177. }
  178. BOOL CBitmapEx::Draw( CDC *pDC, int x, int y, LPRECT sr, COLORREF colTrans, BOOL bTrans )
  179. {
  180. if ( !bTrans )
  181. Draw( pDC ,x, y, sr );
  182. else
  183. {
  184. MyTransparentBlt( pDC->GetSafeHdc(), x, y, sr->right - sr->left, sr->bottom - sr->top,
  185. (HBITMAP)this->GetSafeHandle(), sr->left, sr->top, colTrans, NULL );
  186. }
  187. return TRUE;
  188. }
  189. //draw sub bmp to special point
  190. BOOL CBitmapEx::Draw( CDC *pDC, int x, int y, LPRECT sr )
  191. {
  192. CDC dc;
  193. dc.CreateCompatibleDC( pDC );
  194. CBitmap * bmp = dc.SelectObject( this );
  195. if ( sr != NULL)
  196. pDC->BitBlt( x, y, sr->right - sr->left, sr->bottom - sr->top, &dc,
  197. sr->left, sr->top, SRCCOPY );
  198. else
  199. pDC->BitBlt( x, y, Width(), Height(), &dc,
  200. 0, 0, SRCCOPY );
  201. dc.SelectObject( bmp );
  202. return TRUE;
  203. }
  204. BOOL CBitmapEx::Draw(CDC *pDC, LPRECT r)
  205. {
  206. CDC dc;
  207. dc.CreateCompatibleDC( pDC );
  208. CBitmap * bmp = dc.SelectObject( this );
  209. pDC->BitBlt( r->left, r->top, r->right - r->left, r->bottom - r->top, &dc, 0, 0 ,
  210. SRCCOPY );
  211. dc.SelectObject( bmp );
  212. return TRUE;
  213. }
  214. BOOL CBitmapEx::Draw(CDC *pDC, LPRECT r, int pos)
  215. {
  216. CDC dc;
  217. dc.CreateCompatibleDC( pDC );
  218. CBitmap * bmp = dc.SelectObject( this );
  219. pDC->BitBlt( r->left, r->top, r->right - r->left, r->bottom - r->top, &dc, pos, 0 ,
  220. SRCCOPY );
  221. dc.SelectObject( bmp );
  222. return TRUE;
  223. }
  224. ///HOWTO: Drawing Transparent Bitmaps
  225. //see: Microsoft Knowledge Base Article - Q79212
  226. BOOL CBitmapEx::DrawTransparent(CDC * pDC, int x, int y, COLORREF crColour)
  227. {
  228. MyTransparentBlt( pDC->GetSafeHdc(), x, y, GetWidth(), GetHeight(), (HBITMAP)this->GetSafeHandle(), 0, 0, crColour, NULL );
  229. /*
  230. COLORREF crOldBack = pDC->SetBkColor(0);
  231. COLORREF crOldText = pDC->SetTextColor(RGB(255,255,255));
  232. CDC dcImage, dcTrans;
  233. // Create two memory dcs for the image and the mask
  234. dcImage.CreateCompatibleDC(pDC);
  235. dcTrans.CreateCompatibleDC(pDC);
  236. // Select the image into the appropriate dc
  237. CBitmap* pOldBitmapImage = dcImage.SelectObject(this);
  238. // Create the mask bitmap
  239. CBitmap bitmapTrans;
  240. int nWidth = GetWidth();
  241. int nHeight = GetHeight();
  242. bitmapTrans.CreateBitmap(nWidth, nHeight, 1, 1, NULL);
  243. // Select the mask bitmap into the appropriate dc
  244. CBitmap* pOldBitmapTrans = dcTrans.SelectObject(&bitmapTrans);
  245. // Build mask based on transparent colour
  246. dcImage.SetBkColor(crColour);
  247. dcTrans.BitBlt(0, 0, nWidth, nHeight, &dcImage, 0, 0, SRCCOPY);
  248. // Do the work - True Mask method - cool if not actual display
  249. pDC->BitBlt(x, y, nWidth, nHeight, &dcImage, 0, 0, SRCINVERT);
  250. pDC->BitBlt(x, y, nWidth, nHeight, &dcTrans, 0, 0, SRCAND);
  251. pDC->BitBlt(x, y, nWidth, nHeight, &dcImage, 0, 0, SRCINVERT);
  252. // Restore settings
  253. dcImage.SelectObject(pOldBitmapImage);
  254. dcTrans.SelectObject(pOldBitmapTrans);
  255. pDC->SetBkColor(crOldBack);
  256. pDC->SetTextColor(crOldText);
  257. */
  258. return TRUE;
  259. }
  260. HRGN CBitmapEx::CreateRgnFromFile( COLORREF color )
  261. {
  262. HBITMAP hBmp = (HBITMAP)this->GetSafeHandle();
  263. // get image properties
  264. BITMAP bmp = { 0 };
  265. ::GetObject( hBmp, sizeof(BITMAP), &bmp );
  266. // allocate memory for extended image information
  267. LPBITMAPINFO bi = (LPBITMAPINFO) new BYTE[ sizeof(BITMAPINFO) + 8 ];
  268. memset( bi, 0, sizeof(BITMAPINFO) + 8 );
  269. bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  270. // set window size
  271. int m_dwWidth = bmp.bmWidth; // bitmap width
  272. int m_dwHeight = bmp.bmHeight; // bitmap height
  273. // create temporary dc
  274. HDC dc = CreateIC( "DISPLAY",NULL,NULL,NULL );
  275. // get extended information about image (length, compression, length of color table if exist, ...)
  276. DWORD res = GetDIBits( dc, hBmp, 0, bmp.bmHeight, 0, bi, DIB_RGB_COLORS );
  277. // allocate memory for image data (colors)
  278. LPBYTE pBits = new BYTE[ bi->bmiHeader.biSizeImage + 4 ];
  279. // allocate memory for color table
  280. if ( bi->bmiHeader.biBitCount == 8 )
  281. {
  282. // actually color table should be appended to this header(BITMAPINFO),
  283. // so we have to reallocate and copy it
  284. LPBITMAPINFO old_bi = bi;
  285. // 255 - because there is one in BITMAPINFOHEADER
  286. bi = (LPBITMAPINFO)new char[ sizeof(BITMAPINFO) + 255 * sizeof(RGBQUAD) ];
  287. memcpy( bi, old_bi, sizeof(BITMAPINFO) );
  288. // release old header
  289. delete old_bi;
  290. }
  291. // get bitmap info header
  292. BITMAPINFOHEADER& bih = bi->bmiHeader;
  293. // get color table (for 256 color mode contains 256 entries of RGBQUAD(=DWORD))
  294. LPDWORD clr_tbl = (LPDWORD)&bi->bmiColors;
  295. // fill bits buffer
  296. res = GetDIBits( dc, hBmp, 0, bih.biHeight, pBits, bi, DIB_RGB_COLORS );
  297. DeleteDC( dc );
  298. BITMAP bm;
  299. ::GetObject( hBmp, sizeof(BITMAP), &bm );
  300. // shift bits and byte per pixel (for comparing colors)
  301. LPBYTE pClr = (LPBYTE)&color;
  302. // swap red and blue components
  303. BYTE tmp = pClr[0]; pClr[0] = pClr[2]; pClr[2] = tmp;
  304. // convert color if curent DC is 16-bit (5:6:5) or 15-bit (5:5:5)
  305. if ( bih.biBitCount == 16 )
  306. {
  307. // for 16 bit
  308. color = ((DWORD)(pClr[0] & 0xf8) >> 3) |
  309. ((DWORD)(pClr[1] & 0xfc) << 3) |
  310. ((DWORD)(pClr[2] & 0xf8) << 8);
  311. // for 15 bit
  312. // color = ((DWORD)(pClr[0] & 0xf8) >> 3) |
  313. // ((DWORD)(pClr[1] & 0xf8) << 2) |
  314. // ((DWORD)(pClr[2] & 0xf8) << 7);
  315. }
  316. const DWORD RGNDATAHEADER_SIZE = sizeof(RGNDATAHEADER);
  317. const DWORD ADD_RECTS_COUNT = 40; // number of rects to be appended
  318. // to region data buffer
  319. // BitPerPixel
  320. BYTE Bpp = bih.biBitCount >> 3; // bytes per pixel
  321. // bytes per line in pBits is DWORD aligned and bmp.bmWidthBytes is WORD aligned
  322. // so, both of them not
  323. DWORD m_dwAlignedWidthBytes = (bmp.bmWidthBytes & ~0x3) + (!!(bmp.bmWidthBytes & 0x3) << 2);
  324. // DIB image is flipped that's why we scan it from the last line
  325. LPBYTE pColor = pBits + (bih.biHeight - 1) * m_dwAlignedWidthBytes;
  326. DWORD dwLineBackLen = m_dwAlignedWidthBytes + bih.biWidth * Bpp; // offset of previous scan line
  327. // (after processing of current)
  328. DWORD dwRectsCount = bih.biHeight; // number of rects in allocated buffer
  329. INT i, j; // current position in mask image
  330. INT first = 0; // left position of current scan line
  331. // where mask was found
  332. bool wasfirst = false; // set when mask has been found in current scan line
  333. bool ismask; // set when current color is mask color
  334. // allocate memory for region data
  335. // region data here is set of regions that are rectangles with height 1 pixel (scan line)
  336. // that's why first allocation is <bm.biHeight> RECTs - number of scan lines in image
  337. RGNDATAHEADER* pRgnData =
  338. (RGNDATAHEADER*)new BYTE[ RGNDATAHEADER_SIZE + dwRectsCount * sizeof(RECT) ];
  339. // get pointer to RECT table
  340. LPRECT pRects = (LPRECT)((LPBYTE)pRgnData + RGNDATAHEADER_SIZE);
  341. // zero region data header memory (header part only)
  342. memset( pRgnData, 0, RGNDATAHEADER_SIZE + dwRectsCount * sizeof(RECT) );
  343. // fill it by default
  344. pRgnData->dwSize = RGNDATAHEADER_SIZE;
  345. pRgnData->iType = RDH_RECTANGLES;
  346. for ( i = 0; i < bih.biHeight; i++ )
  347. {
  348. for ( j = 0; j < bih.biWidth; j++ )
  349. {
  350. // get color
  351. switch ( bih.biBitCount )
  352. {
  353. case 8:
  354. ismask = (clr_tbl[ *pColor ] != color);
  355. break;
  356. case 16:
  357. ismask = (*(LPWORD)pColor != (WORD)color);
  358. break;
  359. case 24:
  360. ismask = ((*(LPDWORD)pColor & 0x00ffffff) != color);
  361. break;
  362. case 32:
  363. ismask = (*(LPDWORD)pColor != color);
  364. }
  365. // shift pointer to next color
  366. pColor += Bpp;
  367. // place part of scan line as RECT region if transparent color found after mask color or
  368. // mask color found at the end of mask image
  369. if ( wasfirst )
  370. {
  371. if ( !ismask )
  372. {
  373. // save current RECT
  374. pRects[ pRgnData->nCount++ ] = CRect( first, i, j, i + 1 );
  375. // if buffer full reallocate it with more room
  376. if ( pRgnData->nCount >= dwRectsCount )
  377. {
  378. dwRectsCount += ADD_RECTS_COUNT;
  379. // allocate new buffer
  380. LPBYTE pRgnDataNew = new BYTE[ RGNDATAHEADER_SIZE + dwRectsCount * sizeof(RECT) ];
  381. // copy current region data to it
  382. memcpy( pRgnDataNew, pRgnData, RGNDATAHEADER_SIZE + pRgnData->nCount * sizeof(RECT) );
  383. // delte old region data buffer
  384. delete pRgnData;
  385. // set pointer to new regiondata buffer to current
  386. pRgnData = (RGNDATAHEADER*)pRgnDataNew;
  387. // correct pointer to RECT table
  388. pRects = (LPRECT)((LPBYTE)pRgnData + RGNDATAHEADER_SIZE);
  389. }
  390. wasfirst = false;
  391. }
  392. }
  393. else if ( ismask ) // set wasfirst when mask is found
  394. {
  395. first = j;
  396. wasfirst = true;
  397. }
  398. }
  399. if ( wasfirst && ismask )
  400. {
  401. // save current RECT
  402. pRects[ pRgnData->nCount++ ] = CRect( first, i, j, i + 1 );
  403. // if buffer full reallocate it with more room
  404. if ( pRgnData->nCount >= dwRectsCount )
  405. {
  406. dwRectsCount += ADD_RECTS_COUNT;
  407. // allocate new buffer
  408. LPBYTE pRgnDataNew = new BYTE[ RGNDATAHEADER_SIZE + dwRectsCount * sizeof(RECT) ];
  409. // copy current region data to it
  410. memcpy( pRgnDataNew, pRgnData, RGNDATAHEADER_SIZE + pRgnData->nCount * sizeof(RECT) );
  411. // delte old region data buffer
  412. delete pRgnData;
  413. // set pointer to new regiondata buffer to current
  414. pRgnData = (RGNDATAHEADER*)pRgnDataNew;
  415. // correct pointer to RECT table
  416. pRects = (LPRECT)((LPBYTE)pRgnData + RGNDATAHEADER_SIZE);
  417. }
  418. wasfirst = false;
  419. }
  420. pColor -= dwLineBackLen;
  421. }
  422. // release image data
  423. delete pBits;
  424. delete bi;
  425. // create region
  426. HRGN hRgn = ExtCreateRegion( NULL, RGNDATAHEADER_SIZE + pRgnData->nCount * sizeof(RECT), (LPRGNDATA)pRgnData );
  427. // release region data
  428. delete pRgnData;
  429. return hRgn;
  430. }
  431. BOOL CBitmapEx::LoadImage(UINT uIDRes, LPCTSTR szResourceType, HMODULE hInst, COLORREF crBack)
  432. {
  433. ASSERT(m_hObject == NULL); // only attach once, detach on destroy
  434. if (m_hObject != NULL)
  435. return FALSE;
  436. BYTE* pBuff = NULL;
  437. int nSize = 0;
  438. BOOL bResult = FALSE;
  439. // first call is to get buffer size
  440. if (GetResource(MAKEINTRESOURCE(uIDRes), szResourceType, hInst, 0, nSize))
  441. {
  442. if (nSize > 0)
  443. {
  444. pBuff = new BYTE[nSize];
  445. // this loads it
  446. if (GetResource(MAKEINTRESOURCE(uIDRes), szResourceType, hInst, pBuff, nSize))
  447. {
  448. IPicture* pPicture = LoadFromBuffer(pBuff, nSize);
  449. if (pPicture)
  450. {
  451. bResult = Attach(pPicture, crBack);
  452. pPicture->Release();
  453. }
  454. }
  455. delete [] pBuff;
  456. }
  457. }
  458. return bResult;
  459. }
  460. BOOL CBitmapEx::LoadImage(LPCTSTR szImagePath, COLORREF crBack)
  461. {
  462. ASSERT(m_hObject == NULL); // only attach once, detach on destroy
  463. if (m_hObject != NULL)
  464. return FALSE;
  465. BOOL bResult = FALSE;
  466. CFile cFile;
  467. CFileException e;
  468. if (cFile.Open(szImagePath, CFile::modeRead | CFile::typeBinary, &e))
  469. {
  470. int nSize = cFile.GetLength();
  471. BYTE* pBuff = new BYTE[nSize];
  472. if (cFile.Read(pBuff, nSize) > 0)
  473. {
  474. IPicture* pPicture = LoadFromBuffer(pBuff, nSize);
  475. if (pPicture)
  476. {
  477. bResult = Attach(pPicture, crBack);
  478. pPicture->Release();
  479. }
  480. }
  481. delete [] pBuff;
  482. }
  483. return bResult;
  484. }
  485. IPicture* CBitmapEx::LoadFromBuffer(BYTE* pBuff, int nSize)
  486. {
  487. bool bResult = false;
  488. HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, nSize);
  489. void* pData = GlobalLock(hGlobal);
  490. memcpy(pData, pBuff, nSize);
  491. GlobalUnlock(hGlobal);
  492. IStream* pStream = NULL;
  493. IPicture* pPicture = NULL;
  494. if (CreateStreamOnHGlobal(hGlobal, TRUE, &pStream) == S_OK)
  495. {
  496. HRESULT hr = OleLoadPicture(pStream, nSize, FALSE, IID_IPicture, (LPVOID *)&pPicture);
  497. pStream->Release();
  498. }
  499. return pPicture; // caller releases
  500. }
  501. BOOL CBitmapEx::GetResource(LPCTSTR lpName, LPCTSTR lpType, HMODULE hInst, void* pResource, int& nBufSize)
  502. {
  503. HRSRC hResInfo;
  504. HANDLE hRes;
  505. LPSTR lpRes = NULL;
  506. int nLen = 0;
  507. bool bResult = FALSE;
  508. // Find the resource
  509. hResInfo = FindResource(hInst, lpName, lpType);
  510. if (hResInfo == NULL)
  511. return false;
  512. // Load the resource
  513. hRes = LoadResource(hInst, hResInfo);
  514. if (hRes == NULL)
  515. return false;
  516. // Lock the resource
  517. lpRes = (char*)LockResource(hRes);
  518. if (lpRes != NULL)
  519. {
  520. if (pResource == NULL)
  521. {
  522. nBufSize = SizeofResource(hInst, hResInfo);
  523. bResult = true;
  524. }
  525. else
  526. {
  527. if (nBufSize >= (int)SizeofResource(hInst, hResInfo))
  528. {
  529. memcpy(pResource, lpRes, nBufSize);
  530. bResult = true;
  531. }
  532. }
  533. UnlockResource(hRes);
  534. }
  535. // Free the resource
  536. FreeResource(hRes);
  537. return bResult;
  538. }
  539. BOOL CBitmapEx::Attach(IPicture* pPicture, COLORREF crBack)
  540. {
  541. ASSERT(m_hObject == NULL); // only attach once, detach on destroy
  542. if (m_hObject != NULL)
  543. return FALSE;
  544. ASSERT(pPicture);
  545. if (!pPicture)
  546. return FALSE;
  547. BOOL bResult = FALSE;
  548. CDC dcMem;
  549. CDC* pDC = CWnd::GetDesktopWindow()->GetDC();
  550. if (dcMem.CreateCompatibleDC(pDC))
  551. {
  552. long hmWidth;
  553. long hmHeight;
  554. pPicture->get_Width(&hmWidth);
  555. pPicture->get_Height(&hmHeight);
  556. int nWidth = MulDiv(hmWidth, pDC->GetDeviceCaps(LOGPIXELSX), HIMETRIC_INCH);
  557. int nHeight = MulDiv(hmHeight, pDC->GetDeviceCaps(LOGPIXELSY), HIMETRIC_INCH);
  558. CBitmap bmMem;
  559. if (bmMem.CreateCompatibleBitmap(pDC, nWidth, nHeight))
  560. {
  561. CBitmap* pOldBM = dcMem.SelectObject(&bmMem);
  562. if (crBack != -1)
  563. dcMem.FillSolidRect(0, 0, nWidth, nHeight, crBack);
  564. HRESULT hr = pPicture->Render(dcMem, 0, 0, nWidth, nHeight, 0, hmHeight, hmWidth, -hmHeight, NULL);
  565. dcMem.SelectObject(pOldBM);
  566. if (hr == S_OK)
  567. bResult = CBitmap::Attach(bmMem.Detach());
  568. }
  569. }
  570. CWnd::GetDesktopWindow()->ReleaseDC(pDC);
  571. return bResult;
  572. }
  573. HBITMAP CreateBitmapMask(HBITMAP hSourceBitmap, DWORD dwWidth, DWORD dwHeight, COLORREF crTransColor)
  574. {
  575. HBITMAP hMask = NULL;
  576. HDC hdcSrc = NULL;
  577. HDC hdcDest = NULL;
  578. HBITMAP hbmSrcT = NULL;
  579. HBITMAP hbmDestT = NULL;
  580. COLORREF crSaveBk;
  581. COLORREF crSaveDestText;
  582. hMask = ::CreateBitmap(dwWidth, dwHeight, 1, 1, NULL);
  583. if (hMask == NULL) return NULL;
  584. hdcSrc = ::CreateCompatibleDC(NULL);
  585. hdcDest = ::CreateCompatibleDC(NULL);
  586. hbmSrcT = (HBITMAP)::SelectObject(hdcSrc, hSourceBitmap);
  587. hbmDestT = (HBITMAP)::SelectObject(hdcDest, hMask);
  588. crSaveBk = ::SetBkColor(hdcSrc, crTransColor);
  589. ::BitBlt(hdcDest, 0, 0, dwWidth, dwHeight, hdcSrc, 0, 0, SRCCOPY);
  590. crSaveDestText = ::SetTextColor(hdcSrc, RGB(255, 255, 255));
  591. ::SetBkColor(hdcSrc,RGB(0, 0, 0));
  592. ::BitBlt(hdcSrc, 0, 0, dwWidth, dwHeight, hdcDest, 0, 0, SRCAND);
  593. SetTextColor(hdcDest, crSaveDestText);
  594. ::SetBkColor(hdcSrc, crSaveBk);
  595. ::SelectObject(hdcSrc, hbmSrcT);
  596. ::SelectObject(hdcDest, hbmDestT);
  597. ::DeleteDC(hdcSrc);
  598. ::DeleteDC(hdcDest);
  599. return hMask;
  600. } // End of CreateBitmapMask
  601. void CBitmapEx::TransParentDraw(CDC *pDC, CRect rc, COLORREF col)
  602. {
  603. HDC hdc;
  604. hdc=pDC->m_hDC ;
  605. HBITMAP hbmp=(HBITMAP)this->m_hObject;
  606. MyTransparentBlt( hdc, rc.left , rc.top ,rc.Width (), rc.Height (), hbmp, 0, 0, col, NULL );
  607. }
  608. /*
  609. //这是一个用来画透明位图的函数
  610. //CDC *pDC 需要画位图的CDC指针
  611. //UINT IDImage 位图资源ID
  612. //CRect &rect 指定位图在pDC中的位置
  613. //COLORREF rgbMask 位图的透明色
  614. void DrawTransparentBitmap(CDC *pDC, UINT IDImage,CRect &rect, COLORREF rgbMask)
  615. {
  616. CDC ImageDC,MaskDC;
  617. CBitmap Image,*pOldImage;
  618. CBitmap maskBitmap,*pOldMaskDCBitmap ;
  619. Image.LoadBitmap(IDImage);
  620. ImageDC.CreateCompatibleDC(pDC);
  621. pOldImage=ImageDC.SelectObject(&Image);
  622. MaskDC.CreateCompatibleDC(pDC);
  623. maskBitmap.CreateBitmap( rect.Width(), rect.Height(), 1, 1, NULL );
  624. pOldMaskDCBitmap = MaskDC.SelectObject( &maskBitmap );
  625. ImageDC.SetBkColor(rgbMask);
  626. MaskDC.BitBlt( 0, 0, rect.Width(), rect.Height(), &ImageDC, 0, 0, SRCCOPY );
  627. ImageDC.SetBkColor(RGB(0,0,0));
  628. ImageDC.SetTextColor(RGB(255,255,255));
  629. ImageDC.BitBlt(0, 0, rect.Width(), rect.Height(), &MaskDC, 0, 0, SRCAND);
  630. pDC->BitBlt(rect.left,rect.top,rect.Width(), rect.Height(), &MaskDC, 0, 0, SRCAND);
  631. pDC->BitBlt(rect.left,rect.top,rect.Width(), rect.Height(), &ImageDC, 0, 0,SRCPAINT);
  632. MaskDC.SelectObject(pOldMaskDCBitmap);
  633. ImageDC.SelectObject(pOldImage);
  634. }
  635. */