Draw.cpp
上传用户:ckg1000
上传日期:2013-01-26
资源大小:630k
文件大小:26k
源码类别:

CAD

开发平台:

Visual C++

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Draw.cpp : implementation file
  4. //
  5. ///////////////////////////////////////////////////////////////////////////////
  6. #include "stdafx.h"
  7. #include "Tools.h"
  8. #include "Draw.h"
  9. #ifdef _DEBUG
  10. #define new DEBUG_NEW
  11. #undef THIS_FILE
  12. static char THIS_FILE[] = __FILE__;
  13. #endif
  14. ///////////////////////////////////////////////////////////////////////////////
  15. HLSCOLOR RGB2HLS (COLORREF rgb)
  16. {
  17.     unsigned char minval = min(GetRValue(rgb), min(GetGValue(rgb), GetBValue(rgb)));
  18.     unsigned char maxval = max(GetRValue(rgb), max(GetGValue(rgb), GetBValue(rgb)));
  19.     float mdiff  = float(maxval) - float(minval);
  20.     float msum   = float(maxval) + float(minval);
  21.    
  22.     float luminance = msum / 510.0f;
  23.     float saturation = 0.0f;
  24.     float hue = 0.0f; 
  25.     if ( maxval != minval )
  26.     { 
  27.         float rnorm = (maxval - GetRValue(rgb)  ) / mdiff;      
  28.         float gnorm = (maxval - GetGValue(rgb)) / mdiff;
  29.         float bnorm = (maxval - GetBValue(rgb) ) / mdiff;   
  30.         saturation = (luminance <= 0.5f) ? (mdiff / msum) : (mdiff / (510.0f - msum));
  31.         if (GetRValue(rgb) == maxval) hue = 60.0f * (6.0f + bnorm - gnorm);
  32.         if (GetGValue(rgb) == maxval) hue = 60.0f * (2.0f + rnorm - bnorm);
  33.         if (GetBValue(rgb) == maxval) hue = 60.0f * (4.0f + gnorm - rnorm);
  34.         if (hue > 360.0f) hue = hue - 360.0f;
  35.     }
  36.     return HLS ((hue*255)/360, luminance*255, saturation*255);
  37. }
  38. ///////////////////////////////////////////////////////////////////////////////
  39. static BYTE _ToRGB (float rm1, float rm2, float rh)
  40. {
  41.   if      (rh > 360.0f) rh -= 360.0f;
  42.   else if (rh <   0.0f) rh += 360.0f;
  43.  
  44.   if      (rh <  60.0f) rm1 = rm1 + (rm2 - rm1) * rh / 60.0f;   
  45.   else if (rh < 180.0f) rm1 = rm2;
  46.   else if (rh < 240.0f) rm1 = rm1 + (rm2 - rm1) * (240.0f - rh) / 60.0f;      
  47.                    
  48.   return (BYTE)(rm1 * 255);
  49. }
  50. ///////////////////////////////////////////////////////////////////////////////
  51. COLORREF HLS2RGB (HLSCOLOR hls)
  52. {
  53.     float hue        = ((int)HLS_H(hls)*360)/255.0f;
  54.     float luminance  = HLS_L(hls)/255.0f;
  55.     float saturation = HLS_S(hls)/255.0f;
  56.     if ( saturation == 0.0f )
  57.     {
  58.         return RGB (HLS_L(hls), HLS_L(hls), HLS_L(hls));
  59.     }
  60.     float rm1, rm2;
  61.      
  62.     if ( luminance <= 0.5f ) rm2 = luminance + luminance * saturation;  
  63.     else                     rm2 = luminance + saturation - luminance * saturation;
  64.     rm1 = 2.0f * luminance - rm2;   
  65.     BYTE red   = _ToRGB (rm1, rm2, hue + 120.0f);   
  66.     BYTE green = _ToRGB (rm1, rm2, hue);
  67.     BYTE blue  = _ToRGB (rm1, rm2, hue - 120.0f);
  68.     return RGB (red, green, blue);
  69. }
  70. ///////////////////////////////////////////////////////////////////////////////
  71. COLORREF HLS_TRANSFORM (COLORREF rgb, int percent_L, int percent_S)
  72. {
  73.     HLSCOLOR hls = RGB2HLS (rgb);
  74.     BYTE h = HLS_H(hls);
  75.     BYTE l = HLS_L(hls);
  76.     BYTE s = HLS_S(hls);
  77.     if ( percent_L > 0 )
  78.     {
  79.         l = BYTE(l + ((255 - l) * percent_L) / 100);
  80.     }
  81.     else if ( percent_L < 0 )
  82.     {
  83.         l = BYTE((l * (100+percent_L)) / 100);
  84.     }
  85.     if ( percent_S > 0 )
  86.     {
  87.         s = BYTE(s + ((255 - s) * percent_S) / 100);
  88.     }
  89.     else if ( percent_S < 0 )
  90.     {
  91.         s = BYTE((s * (100+percent_S)) / 100);
  92.     }
  93.     return HLS2RGB (HLS(h, l, s));
  94. }
  95. /////////////////////////////////////////////////////////////////////////////
  96. HBITMAP WINAPI GetScreenBitmap (LPCRECT pRect)
  97. {
  98.     HDC     hDC;
  99.     HDC     hMemDC;
  100.     HBITMAP hNewBitmap = NULL;
  101.     if ( (hDC = ::GetDC (NULL)) != NULL )
  102.     {
  103.         if ( (hMemDC = ::CreateCompatibleDC (hDC)) != NULL )
  104.         {
  105.             if ( (hNewBitmap = ::CreateCompatibleBitmap (hDC, pRect->right - pRect->left, pRect->bottom - pRect->top)) != NULL )
  106.             {
  107.                 HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hMemDC, hNewBitmap);
  108.                 ::BitBlt (hMemDC, 0, 0, pRect->right - pRect->left, pRect->bottom - pRect->top,
  109.                           hDC, pRect->left, pRect->top, SRCCOPY);
  110.                 ::SelectObject (hMemDC, (HGDIOBJ) hOldBitmap);
  111.             }
  112.             ::DeleteDC (hMemDC);
  113.         }
  114.         ::ReleaseDC (NULL, hDC);
  115.     }
  116.     return hNewBitmap;
  117. }
  118. ///////////////////////////////////////////////////////////////////////////////
  119. ///////////////////////////////////////////////////////////////////////////////
  120. CBufferDC::CBufferDC (HDC hDestDC, const CRect& rcPaint) : m_hDestDC (hDestDC)
  121. {
  122.     if ( rcPaint.IsRectEmpty() )
  123.     {
  124.         ::GetClipBox (m_hDestDC, m_rect);
  125.     }
  126.     else
  127.     {
  128.         m_rect = rcPaint;
  129.     }
  130.     VERIFY(Attach (::CreateCompatibleDC (m_hDestDC)));
  131.     m_bitmap.Attach (::CreateCompatibleBitmap (m_hDestDC, m_rect.right, m_rect.bottom));
  132.     m_hOldBitmap = ::SelectObject (m_hDC, m_bitmap);
  133.     if ( m_rect.top > 0 )
  134.     {
  135.         ExcludeClipRect (0, 0, m_rect.right, m_rect.top);
  136.     }
  137.     if ( m_rect.left > 0 )
  138.     {
  139.         ExcludeClipRect (0, m_rect.top, m_rect.left, m_rect.bottom);
  140.     }
  141. }
  142. ///////////////////////////////////////////////////////////////////////////////
  143. CBufferDC::~CBufferDC ()
  144. {
  145.     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));
  146.     ::SelectObject (m_hDC, m_hOldBitmap);
  147. }
  148. ///////////////////////////////////////////////////////////////////////////////
  149. ///////////////////////////////////////////////////////////////////////////////
  150. CPenDC::CPenDC (HDC hDC, COLORREF crColor) : m_hDC (hDC)
  151. {
  152.     VERIFY(m_pen.CreatePen (PS_SOLID, 1, crColor));
  153.     m_hOldPen = (HPEN)::SelectObject (m_hDC, m_pen);
  154. }
  155. ///////////////////////////////////////////////////////////////////////////////
  156. CPenDC::~CPenDC ()
  157. {
  158.     ::SelectObject (m_hDC, m_hOldPen);
  159. }
  160. ///////////////////////////////////////////////////////////////////////////////
  161. void CPenDC::Color (COLORREF crColor)
  162. {
  163.     ::SelectObject (m_hDC, m_hOldPen);
  164.     VERIFY(m_pen.DeleteObject());
  165.     VERIFY(m_pen.CreatePen (PS_SOLID, 1, crColor));
  166.     m_hOldPen = (HPEN)::SelectObject (m_hDC, m_pen);
  167. }
  168. ///////////////////////////////////////////////////////////////////////////////
  169. COLORREF CPenDC::Color () const
  170. {
  171.     LOGPEN logPen;
  172.     ((CPenDC*)this)->m_pen.GetLogPen (&logPen);
  173.     return logPen.lopnColor;
  174. }
  175. ///////////////////////////////////////////////////////////////////////////////
  176. ///////////////////////////////////////////////////////////////////////////////
  177. CBrushDC::CBrushDC (HDC hDC, COLORREF crColor) : m_hDC (hDC)
  178. {
  179.     if ( crColor == CLR_NONE ) VERIFY(m_brush.CreateStockObject (NULL_BRUSH));
  180.     else                       VERIFY(m_brush.CreateSolidBrush (crColor));
  181.     m_hOldBrush = (HBRUSH)::SelectObject (m_hDC, m_brush);
  182. }
  183. ///////////////////////////////////////////////////////////////////////////////
  184. CBrushDC::~CBrushDC ()
  185. {
  186.     ::SelectObject (m_hDC, m_hOldBrush);
  187. }
  188. ///////////////////////////////////////////////////////////////////////////////
  189. void CBrushDC::Color (COLORREF crColor)
  190. {
  191.     ::SelectObject (m_hDC, m_hOldBrush);
  192.     VERIFY(m_brush.DeleteObject());
  193.     if ( crColor == CLR_NONE ) VERIFY(m_brush.CreateStockObject (NULL_BRUSH));
  194.     else                       VERIFY(m_brush.CreateSolidBrush (crColor));
  195.     m_hOldBrush = (HBRUSH)::SelectObject (m_hDC, m_brush);
  196. }
  197. ///////////////////////////////////////////////////////////////////////////////
  198. COLORREF CBrushDC::Color () const
  199. {
  200.     LOGBRUSH logBrush;
  201.     ((CBrushDC*)this)->m_brush.GetLogBrush (&logBrush);
  202.     return logBrush.lbColor;
  203. }
  204. /////////////////////////////////////////////////////////////////////////////
  205. /////////////////////////////////////////////////////////////////////////////
  206. CFontDC::CFontDC (HDC hDC, LPCTSTR sFaceName, COLORREF crText)
  207.         : m_hDC (hDC), m_hFont (NULL), m_hDefFont (NULL), m_crTextOld (CLR_NONE)
  208. {
  209.     *this = sFaceName;
  210.     if ( crText != CLR_DEFAULT )
  211.     {
  212.         *this = crText;
  213.     }
  214. }
  215. /////////////////////////////////////////////////////////////////////////////
  216. CFontDC::CFontDC (HDC hDC, BYTE nStockFont, COLORREF crText)
  217.         : m_hDC (hDC), m_hFont (NULL), m_hDefFont (NULL), m_crTextOld (CLR_NONE)
  218. {
  219.     *this = nStockFont;
  220.     if ( crText != CLR_DEFAULT )
  221.     {
  222.         *this = crText;
  223.     }
  224. }
  225. /////////////////////////////////////////////////////////////////////////////
  226. CFontDC::CFontDC (HDC hDC, HFONT hFont, COLORREF crText)
  227.         : m_hDC (hDC), m_hFont (NULL), m_hDefFont (NULL), m_crTextOld (CLR_NONE)
  228. {
  229.     *this = hFont;
  230.     if ( crText != CLR_DEFAULT )
  231.     {
  232.         *this = crText;
  233.     }
  234. }
  235. /////////////////////////////////////////////////////////////////////////////
  236. CFontDC::~CFontDC ()
  237. {
  238.     if ( m_hDefFont != NULL )
  239.     {
  240.         ::SelectObject (m_hDC, m_hDefFont);
  241.         DeleteObject (m_hFont);
  242.     }
  243.     if ( m_crTextOld != CLR_NONE )
  244.     {
  245.         ::SetTextColor (m_hDC, m_crTextOld);
  246.     }
  247. }
  248. /////////////////////////////////////////////////////////////////////////////
  249. const CFontDC& CFontDC::operator = (LPCTSTR sFaceName)
  250. {
  251.     LOGFONT lf;
  252. ::GetObject (::GetCurrentObject (m_hDC, OBJ_FONT), sizeof(LOGFONT), &lf);
  253.     if ( _tcsicmp (sFaceName, lf.lfFaceName) )
  254.     {
  255.         if ( m_hDefFont != NULL )
  256.         {
  257.             ::SelectObject (m_hDC, m_hDefFont);
  258.             DeleteObject (m_hFont);
  259.         }
  260.         _tcscpy (lf.lfFaceName, sFaceName);
  261.         m_hFont = ::CreateFontIndirect (&lf);
  262.         m_hDefFont = (HFONT)::SelectObject (m_hDC, m_hFont);
  263.     }
  264. return *this;
  265. }
  266. /////////////////////////////////////////////////////////////////////////////
  267. const CFontDC& CFontDC::operator = (BYTE nStockFont)
  268. {
  269.     if ( m_hDefFont != NULL )
  270.     {
  271.         ::SelectObject (m_hDC, m_hDefFont);
  272.         DeleteObject (m_hFont);
  273.     }
  274.     m_hFont = (HFONT)::GetStockObject (nStockFont);
  275.     m_hDefFont = (HFONT)::SelectObject (m_hDC, m_hFont);
  276. return *this;
  277. }
  278. /////////////////////////////////////////////////////////////////////////////
  279. const CFontDC& CFontDC::operator = (HFONT hFont)
  280. {
  281.     if ( m_hDefFont != NULL )
  282.     {
  283.         ::SelectObject (m_hDC, m_hDefFont);
  284.         DeleteObject (m_hFont);
  285.     }
  286.     m_hFont = hFont;
  287.     m_hDefFont = (HFONT)::SelectObject (m_hDC, m_hFont);
  288. return *this;
  289. }
  290. /////////////////////////////////////////////////////////////////////////////
  291. const CFontDC& CFontDC::operator = (COLORREF crText)
  292. {
  293.     if ( m_crTextOld == CLR_NONE )
  294.     {
  295.         m_crTextOld = ::GetTextColor (m_hDC);
  296.     }
  297.     ::SetTextColor (m_hDC, crText);
  298. return *this;
  299. }
  300. /////////////////////////////////////////////////////////////////////////////
  301. CFontDC::operator LPCTSTR ()
  302. {
  303.     LOGFONT lf;
  304. ::GetObject (::GetCurrentObject (m_hDC, OBJ_FONT), sizeof(LOGFONT), &lf);
  305.     return lf.lfFaceName;
  306. }
  307. /////////////////////////////////////////////////////////////////////////////
  308. CFontDC::operator COLORREF ()
  309. {
  310.     return ::GetTextColor (m_hDC);
  311. }
  312. /////////////////////////////////////////////////////////////////////////////
  313. /////////////////////////////////////////////////////////////////////////////
  314. CBoldDC::CBoldDC (HDC hDC, bool bBold) : m_hDC (hDC), m_hDefFont (NULL)
  315. {
  316.     LOGFONT lf;
  317.     CFont::FromHandle((HFONT)::GetCurrentObject(m_hDC, OBJ_FONT))->GetLogFont (&lf);
  318.     if ( ( bBold && lf.lfWeight != FW_BOLD) ||
  319.          (!bBold && lf.lfWeight == FW_BOLD) )
  320.     {
  321.         lf.lfWeight = bBold ? FW_BOLD : FW_NORMAL;
  322.         m_fontBold.CreateFontIndirect (&lf);
  323.         m_hDefFont = (HFONT)::SelectObject (m_hDC, m_fontBold);
  324.     }
  325. }
  326. /////////////////////////////////////////////////////////////////////////////
  327. CBoldDC::~CBoldDC ()
  328. {
  329.     if ( m_hDefFont != NULL )
  330.     {
  331.         ::SelectObject (m_hDC, m_hDefFont);
  332.     }
  333. }
  334. /////////////////////////////////////////////////////////////////////////////
  335. /////////////////////////////////////////////////////////////////////////////
  336. #define DB_GETTYPE(Style)       ((Style)&0x00FF)
  337. #define DB_ISENABLED(Style)     (!((Style)&DB_DISABLED))
  338. #define DB_ISBORDER(Style)      (((Style)&DB_BORDER)==DB_BORDER)
  339. #define DB_ISWINDOWDC(Style)    (((Style)&DB_WINDOWDC)==DB_WINDOWDC)
  340. #define DB_ISFLAT(Style)        (((Style)&DB_FLAT)==DB_FLAT)
  341. #define DB_ISPRESSED(Style)     (((Style)&(DB_PRESSED|DB_PRESSED2))!=0)
  342. #define DB_ISPRESSED1(Style)    (((Style)&DB_PRESSED)==DB_PRESSED)
  343. #define DB_ISPRESSED2(Style)    (((Style)&DB_PRESSED2)==DB_PRESSED2)
  344. #define DB_ISOVER(Style)        (((Style)&DB_OVER)==DB_OVER)
  345. #define DB_ISTRANSPARENT(Style) (((Style)&DB_TRANSPARENT)==DB_TRANSPARENT)
  346. /////////////////////////////////////////////////////////////////////////////
  347. static void _DrawTriangle (CDC* pDC, int x, int y, int nSize, bool bDown)
  348. {
  349.     for ( int i = 0; i < nSize; i++ )
  350.     {
  351.         pDC->MoveTo (x-i, bDown ? y-i : y+i);
  352.         pDC->LineTo (x+i+1, bDown ? y-i : y+i);
  353.     }
  354. }
  355. /////////////////////////////////////////////////////////////////////////////
  356. void CDrawButton::Draw (CDC* pDC, DWORD wStyle) const
  357. {
  358.     if ( wStyle == DB_DEFAULT )
  359.     {
  360.         wStyle = m_wStyle;
  361.     }
  362.     ASSERT (pDC != NULL);
  363.     CRect rc (m_Rect);
  364.     CPenDC pen (pDC->m_hDC, ::GetSysColor (COLOR_3DFACE));
  365.     CBrushDC brush (pDC->m_hDC, ::GetSysColor (COLOR_3DFACE));
  366.     if ( DB_ISBORDER(m_wStyle) && !DB_ISFLAT(wStyle) )
  367.     {
  368.         pDC->MoveTo (rc.right-1, rc.top);
  369.         pDC->LineTo (rc.left, rc.top);
  370.         pDC->LineTo (rc.left, rc.bottom);
  371.         pDC->SetPixel (rc.right-1, rc.top, ::GetSysColor (COLOR_3DDKSHADOW));
  372.         rc.left++;
  373.         rc.top++;
  374.     }
  375.     COLORREF crBorder = 0, crPressed = 0, crOver = 0, crText = 0;
  376.     if ( DB_ISFLAT(wStyle) )
  377.     {
  378.         crBorder = ::GetSysColor (COLOR_HIGHLIGHT);
  379.         crPressed = HLS_TRANSFORM (crBorder, +50, -50);
  380.         crOver = HLS_TRANSFORM (crBorder, +70, -57);
  381.     }
  382.     if ( DB_GETTYPE(wStyle) == DB_UPDOWN )
  383.     {
  384.         if ( !DB_ISPRESSED2(wStyle) )
  385.         {
  386.             if ( DB_ISFLAT(wStyle) )
  387.             {
  388.                 CRect rcBtn (rc.left, rc.top, rc.right, (rc.top+rc.bottom)/2+1);
  389.                 if ( DB_ISENABLED(wStyle) && DB_ISOVER(wStyle) )
  390.                 {
  391.                     pen.Color (crBorder);
  392.                     brush.Color (DB_ISPRESSED(wStyle) ? crPressed : crOver);
  393.                     pDC->Rectangle (rcBtn);
  394.                 }
  395.                 else if ( !DB_ISTRANSPARENT(wStyle) )
  396.                 {
  397.                     pen.Color (::GetSysColor (DB_ISBORDER(m_wStyle) ? COLOR_3DSHADOW : COLOR_WINDOW));
  398.                     pDC->Rectangle (rcBtn);
  399.                 }
  400.             }
  401.             else
  402.             {
  403.                 CRect rcBtn (rc.left, rc.top, rc.right, (rc.top+rc.bottom)/2);
  404.                 pDC->DrawFrameControl (rcBtn, DFC_BUTTON, DFCS_BUTTONPUSH|(DB_ISPRESSED1(wStyle) ? DFCS_PUSHED : 0));
  405.             }
  406.         }
  407.         if ( !DB_ISPRESSED(wStyle) && !DB_ISFLAT(wStyle) )
  408.         {
  409.             pDC->MoveTo (rc.left, (rc.top+rc.bottom)/2);
  410.             pDC->LineTo (rc.right, (rc.top+rc.bottom)/2);
  411.         }
  412.         if ( !DB_ISPRESSED1(wStyle) )
  413.         {
  414.             if ( DB_ISFLAT(wStyle) )
  415.             {
  416.                 CRect rcBtn (rc.left, (rc.top+rc.bottom)/2/*+rc.Height()%2*/, rc.right, rc.bottom);
  417.                 if ( DB_ISENABLED(wStyle) && DB_ISOVER(wStyle) )
  418.                 {
  419.                     pen.Color (crBorder);
  420.                     brush.Color (DB_ISPRESSED(wStyle) ? crPressed : crOver);
  421.                     pDC->Rectangle (rcBtn);
  422.                 }
  423.                 else if ( !DB_ISTRANSPARENT(wStyle) )
  424.                 {
  425.                     pen.Color (::GetSysColor (DB_ISBORDER(m_wStyle) ? COLOR_3DSHADOW : COLOR_WINDOW));
  426.                     pDC->Rectangle (rcBtn);
  427.                 }
  428.             }
  429.             else
  430.             {
  431.                 CRect rcBtn (rc.left, (rc.top+rc.bottom)/2+rc.Height()%2, rc.right, rc.bottom);
  432.                 pDC->DrawFrameControl (rcBtn, DFC_BUTTON, DFCS_BUTTONPUSH|(DB_ISPRESSED2(wStyle) ? DFCS_PUSHED : 0));
  433.             }
  434.         }
  435.         if ( DB_ISFLAT(wStyle) )
  436.         {
  437.             crText = DB_ISENABLED(wStyle) && pDC->GetPixel (rc.left+1, rc.top+1) == crOver ? RGB(0,0,0) : ::GetSysColor (COLOR_BTNTEXT);
  438.             pen.Color (DB_ISPRESSED(wStyle) ? RGB(240,240,240) : DB_ISENABLED(wStyle) ? crText : ::GetSysColor (COLOR_GRAYTEXT));
  439.         }
  440.         else
  441.         {
  442.             pen.Color (::GetSysColor (DB_ISENABLED(wStyle) ? COLOR_BTNTEXT : COLOR_GRAYTEXT));
  443.         }
  444.         if ( !DB_ISPRESSED2(wStyle) )
  445.         {
  446.             _DrawTriangle (pDC, (rc.left+rc.right)/2 + ((DB_ISPRESSED1(wStyle)&&!DB_ISFLAT(wStyle)) ? 1 : 0),
  447.                                 (rc.top*3+rc.bottom)/4 + ((DB_ISPRESSED1(wStyle)||DB_ISFLAT(wStyle)) ? 1 : 0) - 2, 3, false);
  448.         }
  449.         if ( !DB_ISPRESSED1(wStyle) )
  450.         {
  451.             _DrawTriangle (pDC, (rc.left+rc.right)/2 + ((DB_ISPRESSED2(wStyle)&&!DB_ISFLAT(wStyle)) ? 1 : 0),
  452.                                 (rc.top+rc.bottom*3)/4 + ((DB_ISPRESSED2(wStyle)&&!DB_ISFLAT(wStyle)) ? 1 : 0) + 1, 3, true);
  453.         }
  454.     }
  455.     else
  456.     {
  457.         if ( DB_ISFLAT(wStyle) )
  458.         {
  459.             if ( DB_ISENABLED(wStyle) && DB_ISOVER(wStyle) )
  460.             {
  461.                 pen.Color (crBorder);
  462.                 brush.Color (DB_ISPRESSED(wStyle) ? crPressed : crOver);
  463.                 pDC->Rectangle (rc);
  464.             }
  465.             else if ( !DB_ISTRANSPARENT(wStyle) )
  466.             {
  467.                 pen.Color (::GetSysColor (DB_ISBORDER(m_wStyle) ? COLOR_3DSHADOW : COLOR_WINDOW));
  468.                 pDC->Rectangle (rc);
  469.             }
  470.         }
  471.         else
  472.         {
  473.             pDC->DrawFrameControl (rc, DFC_BUTTON, DFCS_BUTTONPUSH|(DB_ISPRESSED(wStyle) ? DFCS_PUSHED : 0));
  474.         }
  475.         switch ( DB_GETTYPE(wStyle) )
  476.         {
  477.             case DB_3POINTS:
  478.                 if ( DB_ISFLAT(wStyle) )
  479.                 {
  480.                     crText = DB_ISENABLED(wStyle) && pDC->GetPixel (rc.left+1, rc.top+1) == crOver ? RGB(0,0,0) : ::GetSysColor (COLOR_BTNTEXT);
  481.                     crText = DB_ISPRESSED(wStyle) ? RGB(240,240,240) : DB_ISENABLED(wStyle) ? crText : ::GetSysColor (COLOR_GRAYTEXT);
  482.                 }
  483.                 else
  484.                 {
  485.                     crText = ::GetSysColor (DB_ISENABLED(wStyle) ? COLOR_BTNTEXT : COLOR_GRAYTEXT);
  486.                 }
  487.                 crText = pDC->SetTextColor (crText);
  488.                 pDC->SetBkMode (TRANSPARENT);
  489.                 pDC->DrawText (_T("..."), 3, CRect(rc.left + ((DB_ISPRESSED(wStyle)||DB_ISFLAT(wStyle)) ? 2 : 1),
  490.                                                    rc.top, rc.right, rc.bottom + ((DB_ISPRESSED(wStyle)&&!DB_ISFLAT(wStyle)) ? 1 : 0)),
  491.                                DT_LEFT|DT_BOTTOM|DT_SINGLELINE);
  492.                 pDC->SetTextColor (crText);
  493.                 break;
  494.             case DB_UP:
  495.             case DB_DOWN:
  496.                 if ( DB_ISFLAT(wStyle) )
  497.                 {
  498.                     crText = DB_ISENABLED(wStyle) && pDC->GetPixel (rc.left+1, rc.top+1) == crOver ? RGB(0,0,0) : ::GetSysColor (COLOR_BTNTEXT);
  499.                     pen.Color (DB_ISPRESSED(wStyle) ? RGB(240,240,240) : DB_ISENABLED(wStyle) ? crText : ::GetSysColor (COLOR_GRAYTEXT));
  500.                 }
  501.                 else
  502.                 {
  503.                     pen.Color (::GetSysColor (DB_ISENABLED(wStyle) ? COLOR_BTNTEXT : COLOR_GRAYTEXT));
  504.                 }
  505.                 _DrawTriangle (pDC, (rc.left+rc.right)/2 + ((DB_ISPRESSED(wStyle)&&!DB_ISFLAT(wStyle)) ? 1 : 0),
  506.                                     (rc.top+rc.bottom)/2 + ((DB_ISPRESSED(wStyle)||DB_ISFLAT(wStyle)) ? 2 : 1) - ((DB_GETTYPE(wStyle) == DB_UP) ? 3 : 0),
  507.                                     4, DB_GETTYPE(wStyle) == DB_DOWN);
  508.                 break;
  509.             case DB_CROSS:
  510.                 {
  511.                     int x1 = (rc.left*2+rc.right)/3-1;
  512.                     int x2 = (rc.left+rc.right*2)/3;
  513.                     int y1 = (rc.top*2+rc.bottom)/3-1;
  514.                     int y2 = (rc.top+rc.bottom*2)/3-1;
  515.                     if ( DB_ISFLAT(wStyle) )
  516.                     {
  517.                         x2++; y2++;
  518.                     }
  519.                     else if ( DB_ISPRESSED(wStyle) )
  520.                     {
  521.                         x1++; y1++;
  522.                         x2++; y2++;
  523.                     }
  524.                     if ( DB_ISFLAT(wStyle) )
  525.                     {
  526.                         crText = DB_ISENABLED(wStyle) && pDC->GetPixel (x1, y1+1) == crOver ? RGB(0,0,0) : ::GetSysColor (COLOR_BTNTEXT);
  527.                         pen.Color (DB_ISPRESSED(wStyle) ? RGB(240,240,240) : DB_ISENABLED(wStyle) ? crText : ::GetSysColor (COLOR_GRAYTEXT));
  528.                     }
  529.                     else
  530.                     {
  531.                         pen.Color (::GetSysColor (DB_ISENABLED(wStyle) ? COLOR_BTNTEXT : COLOR_GRAYTEXT));
  532.                     }
  533.                     pDC->MoveTo (x1, y1);
  534.                     pDC->LineTo (x2, y2+1);
  535.                     pDC->MoveTo (x1+1, y1);
  536.                     pDC->LineTo (x2+1, y2+1);
  537.                     pDC->MoveTo (x2-1, y1);
  538.                     pDC->LineTo (x1-1, y2+1);
  539.                     pDC->MoveTo (x2, y1);
  540.                     pDC->LineTo (x1, y2+1);
  541.                 }
  542.                 break;
  543.         }
  544.     }
  545. }
  546. /////////////////////////////////////////////////////////////////////////////
  547. static WORD s_wNotify = 0;
  548. void CALLBACK EXPORT CDrawButton_TimerProcRepeat (HWND hWnd, UINT, UINT, DWORD)
  549. {
  550.     ::SendMessage (::GetParent (hWnd), WM_COMMAND, MAKELONG (GetDlgCtrlID (hWnd), s_wNotify), (LPARAM)hWnd);
  551. }
  552. /////////////////////////////////////////////////////////////////////////////
  553. DWORD CDrawButton::Click (CWnd* pWnd, CPoint pt, UINT nIDRepeat) const
  554. {
  555.     // don't handle if capture already set
  556.     if ( ::GetCapture() != NULL || !DB_ISENABLED(m_wStyle) )
  557.     {
  558.         return DB_DEFAULT;
  559.     }
  560.     // set capture to the window which received this message
  561.     pWnd->SetCapture();
  562.     ASSERT(pWnd == CWnd::GetCapture());
  563.     bool  bDown = false, bClick = false;
  564.     int   nSpinType = DB_PRESSED;
  565.     CRect rcBtn(m_Rect);
  566.     if ( DB_GETTYPE(m_wStyle) == DB_UPDOWN )
  567.     {
  568.         if ( pt.y >= (rcBtn.top+rcBtn.bottom)/2 )
  569.         {
  570.             nSpinType = DB_PRESSED2;
  571.             rcBtn.top = (rcBtn.top+rcBtn.bottom)/2;
  572.         }
  573.         else
  574.         {
  575.             rcBtn.bottom = (rcBtn.top+rcBtn.bottom)/2;
  576.         }
  577.         if ( nIDRepeat != 0 )
  578.         {
  579.             s_wNotify = (nSpinType == DB_PRESSED) ? LOWORD(nIDRepeat) : HIWORD(nIDRepeat);
  580.             if ( !pWnd->SetTimer (nIDRepeat, 100, &CDrawButton_TimerProcRepeat) )
  581.             {
  582.                 nIDRepeat = 0;
  583.             }
  584.         }
  585.     }
  586.     // get messages until capture lost or cancelled/accepted
  587.     while ( true )
  588.     {
  589.         bool bNewDown = ::PtInRect (rcBtn, pt) != 0;
  590.         if ( bNewDown != bDown )
  591.         {
  592.             bDown = bNewDown;
  593.             if ( DB_ISWINDOWDC(m_wStyle) )
  594.             {
  595.                 CWindowDC cDC (pWnd);
  596.                 Draw (&cDC, m_wStyle|(bDown ? nSpinType : DB_DEFAULT));
  597.             }
  598.             else
  599.             {
  600.                 CClientDC cDC (pWnd);
  601.                 Draw (&cDC, m_wStyle|(bDown ? nSpinType : DB_DEFAULT));
  602.             }
  603.         }
  604.         MSG msg;
  605.         VERIFY(::GetMessage(&msg, NULL, 0, 0));
  606.         if ( CWnd::GetCapture() != pWnd )
  607.         {
  608.             DispatchMessage (&msg);
  609.             goto ExitLoop;
  610.         }
  611.         switch ( msg.message )
  612.         {
  613.             // handle movement messages
  614.             case WM_MOUSEMOVE:
  615.                 pt.x = (short signed)LOWORD(msg.lParam);
  616.                 pt.y = (short signed)HIWORD(msg.lParam);
  617.                 if ( DB_ISWINDOWDC(m_wStyle) )
  618.                 {
  619.                     pWnd->ClientToScreen (&pt);
  620.                     pt -= CWindowRect(pWnd).TopLeft();
  621.                 }
  622.                 break;
  623.             // handle accept messages
  624.             case WM_LBUTTONUP:
  625.                 bClick = bDown;
  626.                 goto ExitLoop;
  627.             // handle cancel messages
  628.             case WM_KEYDOWN:
  629.                 if ( msg.wParam != VK_ESCAPE )
  630.                 {
  631.                     break;
  632.                 }
  633.                 // continue...
  634.             case WM_CANCELMODE:
  635.             case WM_RBUTTONDOWN:
  636.                 goto ExitLoop;
  637.             case WM_TIMER:
  638.                 if ( msg.wParam == nIDRepeat && !bDown )
  639.                 {
  640.                     break;
  641.                 }
  642.                 // continue...
  643.             default:
  644.                 // just dispatch rest of the messages
  645.                 DispatchMessage (&msg);
  646.                 break;
  647.         }
  648.     }
  649. ExitLoop:
  650.     ReleaseCapture();
  651.     if ( DB_GETTYPE(m_wStyle) == DB_UPDOWN && nIDRepeat != 0 )
  652.     {
  653.         pWnd->KillTimer (nIDRepeat);
  654.     }
  655.     if ( bDown )
  656.     {
  657.         if ( DB_ISWINDOWDC(m_wStyle) )
  658.         {
  659.             CWindowDC cDC (pWnd);
  660.             Draw (&cDC);
  661.         }
  662.         else
  663.         {
  664.             CClientDC cDC (pWnd);
  665.             Draw (&cDC);
  666.         }
  667.     }
  668.     return bClick ? (DB_GETTYPE(m_wStyle)|nSpinType) : DB_DEFAULT;
  669. }
  670. /////////////////////////////////////////////////////////////////////////////
  671. void CALLBACK EXPORT CDrawButton_TimerProcMouseOver (HWND hWnd, UINT, UINT, DWORD)
  672. {
  673.     CPoint pt;
  674.     ::GetCursorPos (&pt);
  675.     // WM_MOUSEMOVE isn't necessary if pt is over the window !
  676.     
  677.     if ( ::WindowFromPoint (pt) != hWnd )
  678.     {
  679.         ::ScreenToClient (hWnd, &pt);
  680.         ::PostMessage (hWnd, WM_MOUSEMOVE, 0, MAKELPARAM(pt.x, pt.y));
  681.     }
  682. }
  683. /////////////////////////////////////////////////////////////////////////////
  684. void CDrawButton::CheckForMouseOver (CWnd* pWnd, CPoint pt)
  685. {
  686.     if ( DB_ISFLAT(m_wStyle) )
  687.     {
  688.         if ( !DB_ISOVER(m_wStyle) && PtInRect (pt) )
  689.         {
  690.             if ( pWnd->SetTimer (54321, 300, &CDrawButton_TimerProcMouseOver) )
  691.             {
  692.                 m_wStyle |= DB_OVER;
  693.                 CClientDC cDC (pWnd);
  694.                 Draw (&cDC);
  695.             }
  696.         }
  697.         else if ( DB_ISOVER(m_wStyle) && !PtInRect (pt) )
  698.         {
  699.             pWnd->KillTimer (54321);
  700.             m_wStyle &= ~DB_OVER;
  701.             pWnd->InvalidateRect (m_Rect);
  702.         }
  703.     }
  704. }