RTDraw.cpp
上传用户:qhonly
上传日期:2013-06-10
资源大小:487k
文件大小:28k
源码类别:

界面编程

开发平台:

Visual C++

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Draw.cpp : implementation file
  4. //
  5. ///////////////////////////////////////////////////////////////////////////////
  6. #include "stdafx.h"
  7. #include "RTDraw.h"
  8. ///////////////////////////////////////////////////////////////////////////////
  9. HLSCOLOR RGB2HLS (COLORREF rgb)
  10. {
  11.     unsigned char minval = min(GetRValue(rgb), min(GetGValue(rgb), GetBValue(rgb)));
  12.     unsigned char maxval = max(GetRValue(rgb), max(GetGValue(rgb), GetBValue(rgb)));
  13.     float mdiff  = float(maxval) - float(minval);
  14.     float msum   = float(maxval) + float(minval);
  15.    
  16.     float luminance = msum / 510.0f;
  17.     float saturation = 0.0f;
  18.     float hue = 0.0f; 
  19.     if ( maxval != minval )
  20.     { 
  21.         float rnorm = (maxval - GetRValue(rgb)  ) / mdiff;      
  22.         float gnorm = (maxval - GetGValue(rgb)) / mdiff;
  23.         float bnorm = (maxval - GetBValue(rgb) ) / mdiff;   
  24.         saturation = (luminance <= 0.5f) ? (mdiff / msum) : (mdiff / (510.0f - msum));
  25.         if (GetRValue(rgb) == maxval) hue = 60.0f * (6.0f + bnorm - gnorm);
  26.         if (GetGValue(rgb) == maxval) hue = 60.0f * (2.0f + rnorm - bnorm);
  27.         if (GetBValue(rgb) == maxval) hue = 60.0f * (4.0f + gnorm - rnorm);
  28.         if (hue > 360.0f) hue = hue - 360.0f;
  29.     }
  30.     return HLS ((hue*255)/360, luminance*255, saturation*255);
  31. }
  32. ///////////////////////////////////////////////////////////////////////////////
  33. static BYTE _ToRGB (float rm1, float rm2, float rh)
  34. {
  35.   if      (rh > 360.0f) rh -= 360.0f;
  36.   else if (rh <   0.0f) rh += 360.0f;
  37.  
  38.   if      (rh <  60.0f) rm1 = rm1 + (rm2 - rm1) * rh / 60.0f;   
  39.   else if (rh < 180.0f) rm1 = rm2;
  40.   else if (rh < 240.0f) rm1 = rm1 + (rm2 - rm1) * (240.0f - rh) / 60.0f;      
  41.                    
  42.   return (BYTE)(rm1 * 255);
  43. }
  44. ///////////////////////////////////////////////////////////////////////////////
  45. COLORREF HLS2RGB (HLSCOLOR hls)
  46. {
  47.     float hue        = ((int)HLS_H(hls)*360)/255.0f;
  48.     float luminance  = HLS_L(hls)/255.0f;
  49.     float saturation = HLS_S(hls)/255.0f;
  50.     if ( saturation == 0.0f )
  51.     {
  52.         return RGB (HLS_L(hls), HLS_L(hls), HLS_L(hls));
  53.     }
  54.     float rm1, rm2;
  55.      
  56.     if ( luminance <= 0.5f ) rm2 = luminance + luminance * saturation;  
  57.     else                     rm2 = luminance + saturation - luminance * saturation;
  58.     rm1 = 2.0f * luminance - rm2;   
  59.     BYTE red   = _ToRGB (rm1, rm2, hue + 120.0f);   
  60.     BYTE green = _ToRGB (rm1, rm2, hue);
  61.     BYTE blue  = _ToRGB (rm1, rm2, hue - 120.0f);
  62.     return RGB (red, green, blue);
  63. }
  64. ///////////////////////////////////////////////////////////////////////////////
  65. COLORREF HLS_TRANSFORM (COLORREF rgb, int percent_L, int percent_S)
  66. {
  67.     HLSCOLOR hls = RGB2HLS (rgb);
  68.     BYTE h = HLS_H(hls);
  69.     BYTE l = HLS_L(hls);
  70.     BYTE s = HLS_S(hls);
  71.     if ( percent_L > 0 )
  72.     {
  73.         l = BYTE(l + ((255 - l) * percent_L) / 100);
  74.     }
  75.     else if ( percent_L < 0 )
  76.     {
  77.         l = BYTE((l * (100+percent_L)) / 100);
  78.     }
  79.     if ( percent_S > 0 )
  80.     {
  81.         s = BYTE(s + ((255 - s) * percent_S) / 100);
  82.     }
  83.     else if ( percent_S < 0 )
  84.     {
  85.         s = BYTE((s * (100+percent_S)) / 100);
  86.     }
  87.     return HLS2RGB (HLS(h, l, s));
  88. }
  89. /////////////////////////////////////////////////////////////////////////////
  90. HBITMAP WINAPI GetScreenBitmap (LPCRECT pRect)
  91. {
  92.     HDC     hDC;
  93.     HDC     hMemDC;
  94.     HBITMAP hNewBitmap = NULL;
  95.     if ( (hDC = ::GetDC (NULL)) != NULL )
  96.     {
  97.         if ( (hMemDC = ::CreateCompatibleDC (hDC)) != NULL )
  98.         {
  99.             if ( (hNewBitmap = ::CreateCompatibleBitmap (hDC, pRect->right - pRect->left, pRect->bottom - pRect->top)) != NULL )
  100.             {
  101.                 HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hMemDC, hNewBitmap);
  102.                 ::BitBlt (hMemDC, 0, 0, pRect->right - pRect->left, pRect->bottom - pRect->top,
  103.                           hDC, pRect->left, pRect->top, SRCCOPY);
  104.                 ::SelectObject (hMemDC, (HGDIOBJ) hOldBitmap);
  105.             }
  106.             ::DeleteDC (hMemDC);
  107.         }
  108.         ::ReleaseDC (NULL, hDC);
  109.     }
  110.     return hNewBitmap;
  111. }
  112. ///////////////////////////////////////////////////////////////////////////////
  113. ///////////////////////////////////////////////////////////////////////////////
  114. CBufferDC::CBufferDC (HDC hDestDC, const CRect& rcPaint) : m_hDestDC (hDestDC)
  115. {
  116.     if ( rcPaint.IsRectEmpty() )
  117.     {
  118.         ::GetClipBox (m_hDestDC, m_rect);
  119.     }
  120.     else
  121.     {
  122.         m_rect = rcPaint;
  123.     }
  124.     VERIFY(Attach (::CreateCompatibleDC (m_hDestDC)));
  125.     m_bitmap.Attach (::CreateCompatibleBitmap (m_hDestDC, m_rect.right, m_rect.bottom));
  126.     m_hOldBitmap = ::SelectObject (m_hDC, m_bitmap);
  127.     if ( m_rect.top > 0 )
  128.     {
  129.         ExcludeClipRect (0, 0, m_rect.right, m_rect.top);
  130.     }
  131.     if ( m_rect.left > 0 )
  132.     {
  133.         ExcludeClipRect (0, m_rect.top, m_rect.left, m_rect.bottom);
  134.     }
  135. }
  136. ///////////////////////////////////////////////////////////////////////////////
  137. CBufferDC::~CBufferDC ()
  138. {
  139.     VERIFY(::BitBlt (m_hDestDC, m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(), m_hDC, m_rect.left, m_rect.top, SRCCOPY));
  140.     ::SelectObject (m_hDC, m_hOldBitmap);
  141. }
  142. ///////////////////////////////////////////////////////////////////////////////
  143. ///////////////////////////////////////////////////////////////////////////////
  144. CPenDC::CPenDC (HDC hDC, COLORREF crColor) : m_hDC (hDC)
  145. {
  146.     VERIFY(m_pen.CreatePen (PS_SOLID, 1, crColor));
  147.     m_hOldPen = (HPEN)::SelectObject (m_hDC, m_pen);
  148. }
  149. ///////////////////////////////////////////////////////////////////////////////
  150. CPenDC::~CPenDC ()
  151. {
  152.     ::SelectObject (m_hDC, m_hOldPen);
  153. }
  154. ///////////////////////////////////////////////////////////////////////////////
  155. void CPenDC::Color (COLORREF crColor)
  156. {
  157.     ::SelectObject (m_hDC, m_hOldPen);
  158.     VERIFY(m_pen.DeleteObject());
  159.     VERIFY(m_pen.CreatePen (PS_SOLID, 1, crColor));
  160.     m_hOldPen = (HPEN)::SelectObject (m_hDC, m_pen);
  161. }
  162. ///////////////////////////////////////////////////////////////////////////////
  163. COLORREF CPenDC::Color () const
  164. {
  165.     LOGPEN logPen;
  166.     ((CPenDC*)this)->m_pen.GetLogPen (&logPen);
  167.     return logPen.lopnColor;
  168. }
  169. ///////////////////////////////////////////////////////////////////////////////
  170. ///////////////////////////////////////////////////////////////////////////////
  171. CBrushDC::CBrushDC (HDC hDC, COLORREF crColor) : m_hDC (hDC)
  172. {
  173.     if ( crColor == CLR_NONE ) VERIFY(m_brush.CreateStockObject (NULL_BRUSH));
  174.     else                       VERIFY(m_brush.CreateSolidBrush (crColor));
  175.     m_hOldBrush = (HBRUSH)::SelectObject (m_hDC, m_brush);
  176. }
  177. ///////////////////////////////////////////////////////////////////////////////
  178. CBrushDC::~CBrushDC ()
  179. {
  180.     ::SelectObject (m_hDC, m_hOldBrush);
  181. }
  182. ///////////////////////////////////////////////////////////////////////////////
  183. void CBrushDC::Color (COLORREF crColor)
  184. {
  185.     ::SelectObject (m_hDC, m_hOldBrush);
  186.     VERIFY(m_brush.DeleteObject());
  187.     if ( crColor == CLR_NONE ) VERIFY(m_brush.CreateStockObject (NULL_BRUSH));
  188.     else                       VERIFY(m_brush.CreateSolidBrush (crColor));
  189.     m_hOldBrush = (HBRUSH)::SelectObject (m_hDC, m_brush);
  190. }
  191. ///////////////////////////////////////////////////////////////////////////////
  192. COLORREF CBrushDC::Color () const
  193. {
  194.     LOGBRUSH logBrush;
  195.     ((CBrushDC*)this)->m_brush.GetLogBrush (&logBrush);
  196.     return logBrush.lbColor;
  197. }
  198. /////////////////////////////////////////////////////////////////////////////
  199. /////////////////////////////////////////////////////////////////////////////
  200. CFontDC::CFontDC (HDC hDC, LPCTSTR sFaceName, COLORREF crText)
  201.         : m_hDC (hDC), m_hFont (NULL), m_hDefFont (NULL), m_crTextOld (CLR_NONE)
  202. {
  203.     *this = sFaceName;
  204.     if ( crText != CLR_DEFAULT )
  205.     {
  206.         *this = crText;
  207.     }
  208. }
  209. /////////////////////////////////////////////////////////////////////////////
  210. CFontDC::CFontDC (HDC hDC, BYTE nStockFont, COLORREF crText)
  211.         : m_hDC (hDC), m_hFont (NULL), m_hDefFont (NULL), m_crTextOld (CLR_NONE)
  212. {
  213.     *this = nStockFont;
  214.     if ( crText != CLR_DEFAULT )
  215.     {
  216.         *this = crText;
  217.     }
  218. }
  219. /////////////////////////////////////////////////////////////////////////////
  220. CFontDC::CFontDC (HDC hDC, HFONT hFont, COLORREF crText)
  221.         : m_hDC (hDC), m_hFont (NULL), m_hDefFont (NULL), m_crTextOld (CLR_NONE)
  222. {
  223.     *this = hFont;
  224.     if ( crText != CLR_DEFAULT )
  225.     {
  226.         *this = crText;
  227.     }
  228. }
  229. /////////////////////////////////////////////////////////////////////////////
  230. CFontDC::~CFontDC ()
  231. {
  232.     if ( m_hDefFont != NULL )
  233.     {
  234.         ::SelectObject (m_hDC, m_hDefFont);
  235.         DeleteObject (m_hFont);
  236.     }
  237.     if ( m_crTextOld != CLR_NONE )
  238.     {
  239.         ::SetTextColor (m_hDC, m_crTextOld);
  240.     }
  241. }
  242. /////////////////////////////////////////////////////////////////////////////
  243. const CFontDC& CFontDC::operator = (LPCTSTR sFaceName)
  244. {
  245.     LOGFONT lf;
  246. ::GetObject (::GetCurrentObject (m_hDC, OBJ_FONT), sizeof(LOGFONT), &lf);
  247.     if ( _tcsicmp (sFaceName, lf.lfFaceName) )
  248.     {
  249.         if ( m_hDefFont != NULL )
  250.         {
  251.             ::SelectObject (m_hDC, m_hDefFont);
  252.             DeleteObject (m_hFont);
  253.         }
  254.         _tcscpy (lf.lfFaceName, sFaceName);
  255.         m_hFont = ::CreateFontIndirect (&lf);
  256.         m_hDefFont = (HFONT)::SelectObject (m_hDC, m_hFont);
  257.     }
  258. return *this;
  259. }
  260. /////////////////////////////////////////////////////////////////////////////
  261. const CFontDC& CFontDC::operator = (BYTE nStockFont)
  262. {
  263.     if ( m_hDefFont != NULL )
  264.     {
  265.         ::SelectObject (m_hDC, m_hDefFont);
  266.         DeleteObject (m_hFont);
  267.     }
  268.     m_hFont = (HFONT)::GetStockObject (nStockFont);
  269.     m_hDefFont = (HFONT)::SelectObject (m_hDC, m_hFont);
  270. return *this;
  271. }
  272. /////////////////////////////////////////////////////////////////////////////
  273. const CFontDC& CFontDC::operator = (HFONT hFont)
  274. {
  275.     if ( m_hDefFont != NULL )
  276.     {
  277.         ::SelectObject (m_hDC, m_hDefFont);
  278.         DeleteObject (m_hFont);
  279.     }
  280.     m_hFont = hFont;
  281.     m_hDefFont = (HFONT)::SelectObject (m_hDC, m_hFont);
  282. return *this;
  283. }
  284. /////////////////////////////////////////////////////////////////////////////
  285. const CFontDC& CFontDC::operator = (COLORREF crText)
  286. {
  287.     if ( m_crTextOld == CLR_NONE )
  288.     {
  289.         m_crTextOld = ::GetTextColor (m_hDC);
  290.     }
  291.     ::SetTextColor (m_hDC, crText);
  292. return *this;
  293. }
  294. /////////////////////////////////////////////////////////////////////////////
  295. CFontDC::operator LPCTSTR ()
  296. {
  297.     LOGFONT lf;
  298. ::GetObject (::GetCurrentObject (m_hDC, OBJ_FONT), sizeof(LOGFONT), &lf);
  299.     return lf.lfFaceName;
  300. }
  301. /////////////////////////////////////////////////////////////////////////////
  302. CFontDC::operator COLORREF ()
  303. {
  304.     return ::GetTextColor (m_hDC);
  305. }
  306. /////////////////////////////////////////////////////////////////////////////
  307. /////////////////////////////////////////////////////////////////////////////
  308. CBoldDC::CBoldDC (HDC hDC, bool bBold) : m_hDC (hDC), m_hDefFont (NULL)
  309. {
  310.     LOGFONT lf;
  311.     CFont::FromHandle((HFONT)::GetCurrentObject(m_hDC, OBJ_FONT))->GetLogFont (&lf);
  312.     if ( ( bBold && lf.lfWeight != FW_BOLD) ||
  313.          (!bBold && lf.lfWeight == FW_BOLD) )
  314.     {
  315.         lf.lfWeight = bBold ? FW_BOLD : FW_NORMAL;
  316.         m_fontBold.CreateFontIndirect (&lf);
  317.         m_hDefFont = (HFONT)::SelectObject (m_hDC, m_fontBold);
  318.     }
  319. }
  320. /////////////////////////////////////////////////////////////////////////////
  321. CBoldDC::~CBoldDC ()
  322. {
  323.     if ( m_hDefFont != NULL )
  324.     {
  325.         ::SelectObject (m_hDC, m_hDefFont);
  326.     }
  327. }
  328. /////////////////////////////////////////////////////////////////////////////
  329. /////////////////////////////////////////////////////////////////////////////
  330. #define DB_GETTYPE(Style)       ((Style)&0x00FF)
  331. #define DB_ISENABLED(Style)     (!((Style)&DB_DISABLED))
  332. #define DB_ISBORDER(Style)      (((Style)&DB_BORDER)==DB_BORDER)
  333. #define DB_ISWINDOWDC(Style)    (((Style)&DB_WINDOWDC)==DB_WINDOWDC)
  334. #define DB_ISFLAT(Style)        (((Style)&DB_FLAT)==DB_FLAT)
  335. #define DB_ISPRESSED(Style)     (((Style)&(DB_PRESSED|DB_PRESSED2))!=0)
  336. #define DB_ISPRESSED1(Style)    (((Style)&DB_PRESSED)==DB_PRESSED)
  337. #define DB_ISPRESSED2(Style)    (((Style)&DB_PRESSED2)==DB_PRESSED2)
  338. #define DB_ISOVER(Style)        (((Style)&DB_OVER)==DB_OVER)
  339. #define DB_ISTRANSPARENT(Style) (((Style)&DB_TRANSPARENT)==DB_TRANSPARENT)
  340. /////////////////////////////////////////////////////////////////////////////
  341. static void _DrawTriangle (CDC* pDC, int x, int y, int nSize, bool bDown)
  342. {
  343.     for ( int i = 0; i < nSize; i++ )
  344.     {
  345.         pDC->MoveTo (x-i, bDown ? y-i : y+i);
  346.         pDC->LineTo (x+i+1, bDown ? y-i : y+i);
  347.     }
  348. }
  349. BOOL CRTDraw::RTDrawVerticalText(CDC* pDC,LPCRECT lpRect,LPCTSTR lpText,int length,UINT format,LOGFONT *lf)
  350. {
  351. char *ptr = (char *)lpText;
  352. char *start = (char *)lpText;
  353. char *end = (char *)(lpText + length - 1);
  354. char temp = NULL;
  355. BOOL IsUnicode = FALSE;
  356. while(ptr <= end)
  357. {
  358. if(*ptr & 0x80)
  359. {
  360. IsUnicode = TRUE;
  361. break;
  362. }
  363. }
  364. ptr = (char *)lpText;
  365. CRect rtText;
  366. CSize sz;
  367. int top = lpRect->top;
  368. if(!IsUnicode)
  369. {
  370. lf->lfEscapement = 900;
  371. lf->lfOrientation = 900;
  372. CFont font;
  373. font.CreateFontIndirect(lf);
  374. pDC->SelectObject(&font);
  375. sz = pDC->GetTextExtent(start,(int)(end - start));
  376. rtText.left = lpRect->left + (lpRect->right - lpRect->left - sz.cy)/2;
  377. rtText.top = top;
  378. rtText.bottom = rtText.top + sz.cx;
  379. rtText.right = lpRect->right;
  380. pDC->TextOut(rtText.left,rtText.bottom,start,(int)(end - start));
  381. return TRUE;
  382. }
  383. lf->lfEscapement = 0;
  384. lf->lfOrientation = 0;
  385. CFont font;
  386. font.CreateFontIndirect(lf);
  387. pDC->SelectObject(&font);
  388. while(ptr <= end)
  389. {
  390. //UNICODE 
  391. if(*ptr & 0x80)
  392. {
  393. if(ptr + 1 > end)break;
  394. start = ptr;
  395. ptr += 2;
  396. sz = pDC->GetTextExtent(start,(int)(ptr - start));
  397. CRect rtText;
  398. rtText.SetRect(lpRect->left + (lpRect->right - lpRect->left - sz.cx)/2,
  399. top,lpRect->right,lpRect->bottom);
  400. pDC->TextOut(rtText.left,rtText.top, start,(int)(ptr - start));
  401. top += sz.cy;
  402. }
  403. else
  404. {
  405. start = ptr;
  406. ptr += 1;
  407. sz = pDC->GetTextExtent(start,(int)(ptr - start));
  408. CRect rtText;
  409. rtText.SetRect(lpRect->left + (lpRect->right - lpRect->left - sz.cx)/2,
  410. top,lpRect->right,lpRect->bottom);
  411. pDC->TextOut(rtText.left,rtText.top, start,(int)(ptr - start));
  412. top += sz.cy;
  413. }
  414. }
  415. return TRUE;
  416. }
  417. //BITMAP Width and height > 9
  418. BOOL CRTDraw::RTDrawBitmap(CDC* pDC, LPCRECT lpRect, CBitmap* pBitmap,UINT Mode)
  419. {
  420. if(pDC == NULL)return FALSE;
  421. if(pBitmap == NULL)return FALSE;
  422. BITMAP bitmap;
  423. pBitmap->GetBitmap(&bitmap);
  424. if(bitmap.bmWidth < 9)return FALSE;
  425. if(bitmap.bmHeight < 9)return FALSE;
  426. CDC srcDC;
  427. srcDC.CreateCompatibleDC(pDC);
  428. CBitmap *pOldBitmap = srcDC.SelectObject(pBitmap);
  429. if(Mode == DrawModeState)
  430. {
  431. pDC->StretchBlt(lpRect->left,lpRect->top,bitmap.bmWidth,bitmap.bmHeight,
  432. &srcDC,0,0,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY);
  433. return TRUE;
  434. }
  435. if((DrawMode)Mode == DrawModeAllStretch)
  436. {
  437. pDC->StretchBlt(lpRect->left,lpRect->top,lpRect->right - lpRect->left,
  438. lpRect->bottom - lpRect->top,&srcDC,0,0,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY);
  439. srcDC.SelectObject(pOldBitmap);
  440. srcDC.DeleteDC();
  441. return TRUE;
  442. }
  443. int height;
  444. int width;
  445. if((DrawMode)Mode == DrawModeFill)
  446. {
  447. int left = lpRect->left;
  448. int top = lpRect->top;
  449. while(left < lpRect->right)
  450. {
  451. if(lpRect->right - left <= bitmap.bmWidth)
  452. {
  453. width = lpRect->right - left;
  454. if(lpRect->bottom - top <= bitmap.bmHeight)
  455. {
  456. height = lpRect->bottom - top;
  457. pDC->BitBlt(left,top,width,height,&srcDC,0,0,SRCCOPY);
  458. break;
  459. }
  460. else
  461. {
  462. height = bitmap.bmHeight;
  463. pDC->BitBlt(left,top,width,height,&srcDC,0,0,SRCCOPY);
  464. top += height;
  465. left = lpRect->left;
  466. }
  467. }
  468. else
  469. {
  470. width = bitmap.bmWidth;
  471. if(lpRect->bottom - top <= bitmap.bmHeight)
  472. {
  473. height = lpRect->bottom - top;
  474. pDC->BitBlt(left,top,width,height,&srcDC,0,0,SRCCOPY);
  475. }
  476. else
  477. {
  478. height = bitmap.bmHeight;
  479. pDC->BitBlt(left,top,width,height,&srcDC,0,0,SRCCOPY);
  480. }
  481. left += width;
  482. }
  483. }
  484. srcDC.SelectObject(pOldBitmap);
  485. srcDC.DeleteDC();
  486. return TRUE;
  487. }
  488. if(Mode == DrawModeHeightStretch)
  489. {
  490. height = lpRect->bottom - lpRect->top;
  491. int top = lpRect->top;
  492. int left = lpRect->left;
  493. int right = lpRect->right;
  494. while((right - left) >= bitmap.bmWidth)
  495. {
  496. pDC->StretchBlt(left,top,bitmap.bmWidth,height,
  497. &srcDC,0,0,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY);
  498. left += bitmap.bmWidth;
  499. }
  500. width = right - left;
  501. pDC->StretchBlt(left,top,width,height,
  502. &srcDC,0,0,width,bitmap.bmHeight,SRCCOPY);
  503. srcDC.SelectObject(&pOldBitmap);
  504. srcDC.DeleteDC();
  505. return TRUE;
  506. }
  507. if(Mode == DrawModeWidthStretch)
  508. {
  509. height = lpRect->bottom - lpRect->top;
  510. int top = lpRect->top;
  511. width = lpRect->right - lpRect->left;
  512. int left = lpRect->left;
  513. int bottom = lpRect->bottom;
  514. while((bottom - top) >= bitmap.bmHeight)
  515. {
  516. pDC->StretchBlt(left,top,width,bitmap.bmHeight,
  517. &srcDC,0,0,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY);
  518. top += bitmap.bmHeight;
  519. }
  520. height = bottom - top;
  521. pDC->StretchBlt(left,top,width,height,
  522. &srcDC,4,0,bitmap.bmWidth,height,SRCCOPY);
  523. srcDC.SelectObject(&pOldBitmap);
  524. srcDC.DeleteDC();
  525. }
  526. if(Mode == DrawMode3D)
  527. {
  528. int width = bitmap.bmWidth/3;
  529. int height = bitmap.bmHeight/3;
  530. int x = lpRect->left + width;
  531. int y = lpRect->top + height;
  532. //fill center
  533. while( x + width < lpRect->right)
  534. {
  535. while(y + height < lpRect->bottom)
  536. {
  537. pDC->BitBlt(x,y,width,height,&srcDC,width,height,SRCCOPY);
  538. y += height;
  539. }
  540. y = lpRect->top + height;
  541. x += width;
  542. }
  543. //draw top border
  544. x = lpRect->left + width;
  545. y = lpRect->top;
  546. pDC->BitBlt(lpRect->left,y,width,height,&srcDC,0,0,SRCCOPY);
  547. while( x + width < lpRect->right)
  548. {
  549. pDC->BitBlt(x,y,width,height,&srcDC,width,0,SRCCOPY);
  550. x += width;
  551. }
  552. pDC->BitBlt(lpRect->right - width,y,width,height,&srcDC,width + width,0,SRCCOPY);
  553. //draw left border
  554. x = lpRect->left;
  555. y = lpRect->top + height;
  556. while( y + height < lpRect->bottom)
  557. {
  558. pDC->BitBlt(x,y,width,height,&srcDC,0,height,SRCCOPY);
  559. y += height;
  560. }
  561. //draw right border
  562. x = lpRect->right - width;
  563. y = lpRect->top + height;
  564. while( y + height < lpRect->bottom)
  565. {
  566. pDC->BitBlt(x,y,width,height,&srcDC,width + width,height,SRCCOPY);
  567. y += height;
  568. }
  569. //draw bottom border
  570. x = lpRect->left + width;
  571. y = lpRect->bottom - height;
  572. pDC->BitBlt(lpRect->left,y,width,height,&srcDC,0,height + height,SRCCOPY);
  573. while( x + width < lpRect->right)
  574. {
  575. pDC->BitBlt(x,y,width,height,&srcDC,width,height + height,SRCCOPY);
  576. x += width;
  577. }
  578. pDC->BitBlt(lpRect->right - width,y,width,height,&srcDC,width + width,height + height,SRCCOPY);
  579. srcDC.SelectObject(&pOldBitmap);
  580. srcDC.DeleteDC();
  581. return TRUE;
  582. }
  583. if(Mode == DrawModeHeightStretch3D)
  584. {
  585. int width = bitmap.bmWidth / 3;
  586. int height = lpRect->bottom - lpRect->top;
  587. int x = lpRect->left;
  588. int y = lpRect->top;
  589. int right = lpRect->right;
  590. pDC->StretchBlt(x,y,width,height,&srcDC,0,0,width,bitmap.bmHeight,SRCCOPY);
  591. while((x + width) < right)
  592. {
  593. pDC->StretchBlt(x,y,width,height,&srcDC,width,0,width,bitmap.bmHeight,SRCCOPY);
  594. x += width;
  595. }
  596. pDC->StretchBlt(right - width,y,width,height,&srcDC,width + width,0,width,bitmap.bmHeight,SRCCOPY);
  597. srcDC.SelectObject(&pOldBitmap);
  598. srcDC.DeleteDC();
  599. return TRUE;
  600. }
  601. if(Mode == DrawModeHeightCenter3D)
  602. {
  603. int width = bitmap.bmWidth / 3;
  604. int height = lpRect->bottom - lpRect->top;
  605. int x = lpRect->left;
  606. int y = lpRect->top;
  607. int right = lpRect->right;
  608. while((x + width) < right)
  609. {
  610. pDC->StretchBlt(x,y,width,height,&srcDC,width,0,width,bitmap.bmHeight,SRCCOPY);
  611. x += width;
  612. }
  613. pDC->StretchBlt(right - width,y,width,height,&srcDC,width,0,width,bitmap.bmHeight,SRCCOPY);
  614. srcDC.SelectObject(&pOldBitmap);
  615. srcDC.DeleteDC();
  616. return TRUE;
  617. }
  618. srcDC.SelectObject(&pOldBitmap);
  619. srcDC.DeleteDC();
  620. return TRUE;
  621. }
  622. HRGN CRTDraw::BitmapToRegion (HBITMAP hBmp, COLORREF cTransparentColor, COLORREF cTolerance)
  623. {
  624.     HRGN hRgn = NULL;
  625.     if (hBmp)
  626.     {
  627.         // Create a memory DC inside which we will scan the bitmap content
  628.         HDC hMemDC = CreateCompatibleDC(NULL);
  629.         if (hMemDC)
  630.         {
  631.             // Get bitmap size
  632.             BITMAP bm;
  633.             GetObject(hBmp, sizeof(bm), &bm);
  634.             // Create a 32 bits depth bitmap and select it into the memory DC 
  635.             BITMAPINFOHEADER RGB32BITSBITMAPINFO = {    
  636.                     sizeof(BITMAPINFOHEADER),    // biSize 
  637.                     bm.bmWidth,                    // biWidth; 
  638.                     bm.bmHeight,                // biHeight; 
  639.                     1,                            // biPlanes; 
  640.                     32,                            // biBitCount 
  641.                     BI_RGB,                        // biCompression; 
  642.                     0,                            // biSizeImage; 
  643.                     0,                            // biXPelsPerMeter; 
  644.                     0,                            // biYPelsPerMeter; 
  645.                     0,                            // biClrUsed; 
  646.                     0                            // biClrImportant; 
  647.             };
  648.             VOID * pbits32; 
  649.             HBITMAP hbm32 = CreateDIBSection(hMemDC, (BITMAPINFO *)&RGB32BITSBITMAPINFO, DIB_RGB_COLORS, &pbits32, NULL, 0);
  650.             if (hbm32)
  651.             {
  652.                 HBITMAP holdBmp = (HBITMAP)SelectObject(hMemDC, hbm32);
  653.                 // Create a DC just to copy the bitmap into the memory DC
  654.                 HDC hDC = CreateCompatibleDC(hMemDC);
  655.                 if (hDC)
  656.                 {
  657.                     // Get how many bytes per row we have for the bitmap bits (rounded up to 32 bits)
  658.                     BITMAP bm32;
  659.                     GetObject(hbm32, sizeof(bm32), &bm32);
  660.                     while (bm32.bmWidthBytes % 4)
  661.                         bm32.bmWidthBytes++;
  662.                     // Copy the bitmap into the memory DC
  663.                     HBITMAP holdBmp = (HBITMAP)SelectObject(hDC, hBmp);
  664.                     BitBlt(hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, hDC, 0, 0, SRCCOPY);
  665.                     // For better performances, we will use the ExtCreateRegion() function to create the
  666.                     // region. This function take a RGNDATA structure on entry. We will add rectangles by
  667.                     // amount of ALLOC_UNIT number in this structure.
  668.                     #define ALLOC_UNIT    100
  669.                     DWORD maxRects = ALLOC_UNIT;
  670.                     HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects));
  671.                     RGNDATA *pData = (RGNDATA *)GlobalLock(hData);
  672.                     pData->rdh.dwSize = sizeof(RGNDATAHEADER);
  673.                     pData->rdh.iType = RDH_RECTANGLES;
  674.                     pData->rdh.nCount = pData->rdh.nRgnSize = 0;
  675.                     SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
  676.                     // Keep on hand highest and lowest values for the "transparent" pixels
  677.                     BYTE lr = GetRValue(cTransparentColor);
  678.                     BYTE lg = GetGValue(cTransparentColor);
  679.                     BYTE lb = GetBValue(cTransparentColor);
  680.                     BYTE hr = min(0xff, lr + GetRValue(cTolerance));
  681.                     BYTE hg = min(0xff, lg + GetGValue(cTolerance));
  682.                     BYTE hb = min(0xff, lb + GetBValue(cTolerance));
  683.                     // Scan each bitmap row from bottom to top (the bitmap is inverted vertically)
  684.                     BYTE *p32 = (BYTE *)bm32.bmBits + (bm32.bmHeight - 1) * bm32.bmWidthBytes;
  685.                     for (int y = 0; y < bm.bmHeight; y++)
  686.                     {
  687. TRACE("n");
  688.                         // Scan each bitmap pixel from left to right
  689.                         for (int x = 0; x < bm.bmWidth; x++)
  690.                         {
  691.                             // Search for a continuous range of "non transparent pixels"
  692.                             int x0 = x;
  693.                             LONG *p = (LONG *)p32 + x;
  694.                             while (x < bm.bmWidth)
  695.                             {
  696. TRACE("1");
  697.                                 BYTE b = GetRValue(*p);
  698.                                 if (b >= lr && b <= hr)
  699.                                 {
  700.                                     b = GetGValue(*p);
  701.                                     if (b >= lg && b <= hg)
  702.                                     {
  703.                                         b = GetBValue(*p);
  704.                                         if (b >= lb && b <= hb)
  705. {
  706. TRACE("0");
  707.                                             // This pixel is "transparent"
  708. break;
  709. }
  710.                                     }
  711.                                 }
  712.                                 p++;
  713.                                 x++;
  714.                             }
  715.                             if (x > x0)
  716.                             {
  717.                                 // Add the pixels (x0, y) to (x, y+1) as a new rectangle in the region
  718.                                 if (pData->rdh.nCount >= maxRects)
  719.                                 {
  720.                                     GlobalUnlock(hData);
  721.                                     maxRects += ALLOC_UNIT;
  722.                                     hData = GlobalReAlloc(hData, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), GMEM_MOVEABLE);
  723.                                     pData = (RGNDATA *)GlobalLock(hData);
  724.                                 }
  725.                                 RECT *pr = (RECT *)&pData->Buffer;
  726.                                 SetRect(&pr[pData->rdh.nCount], x0, y, x, y+1);
  727.                                 if (x0 < pData->rdh.rcBound.left)
  728.                                     pData->rdh.rcBound.left = x0;
  729.                                 if (y < pData->rdh.rcBound.top)
  730.                                     pData->rdh.rcBound.top = y;
  731.                                 if (x > pData->rdh.rcBound.right)
  732.                                     pData->rdh.rcBound.right = x;
  733.                                 if (y+1 > pData->rdh.rcBound.bottom)
  734.                                     pData->rdh.rcBound.bottom = y+1;
  735.                                 pData->rdh.nCount++;
  736.                                 // On Windows98, ExtCreateRegion() may fail if the number of rectangles is too
  737.                                 // large (ie: > 4000). Therefore, we have to create the region by multiple steps.
  738.                                 if (pData->rdh.nCount == 2000)
  739.                                 {
  740.                                     HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);
  741.                                     if (hRgn)
  742.                                     {
  743.                                         CombineRgn(hRgn, hRgn, h, RGN_OR);
  744.                                         DeleteObject(h);
  745.                                     }
  746.                                     else
  747.                                         hRgn = h;
  748.                                     pData->rdh.nCount = 0;
  749.                                     SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
  750.                                 }
  751.                             }
  752.                         }
  753.                         // Go to next row (remember, the bitmap is inverted vertically)
  754.                         p32 -= bm32.bmWidthBytes;
  755.                     }
  756.                     // Create or extend the region with the remaining rectangles
  757.                     HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);
  758.                     if (hRgn)
  759.                     {
  760.                         CombineRgn(hRgn, hRgn, h, RGN_OR);
  761.                         DeleteObject(h);
  762.                     }
  763.                     else
  764.                         hRgn = h;
  765.                     // Clean up
  766.                     GlobalFree(hData);
  767.                     SelectObject(hDC, holdBmp);
  768.                     DeleteDC(hDC);
  769.                 }
  770.                 DeleteObject(SelectObject(hMemDC, holdBmp));
  771.             }
  772.             DeleteDC(hMemDC);
  773.         }    
  774.     }
  775.     return hRgn;