home *** CD-ROM | disk | FTP | other *** search
/ ftp.funduc.com / 2014.08.ftp.funduc.com.tar / ftp.funduc.com / fshedcode-072212.zip / colorbtn.cpp < prev    next >
C/C++ Source or Header  |  2010-09-13  |  16KB  |  672 lines

  1. // ColorBtn.cpp : implementation file
  2.  
  3. #include "stdafx.h"
  4. #include "ColorBtn.h"
  5.  
  6. #ifdef _DEBUG
  7. #define new DEBUG_NEW
  8. #undef THIS_FILE
  9. static char THIS_FILE[] = __FILE__;
  10. #endif
  11.  
  12. // The color table, initialized to windows' 20 static colors
  13. COLORREF CColorBtnDlg::colors[20] =
  14. {
  15.     RGB(0,0,0),
  16.     RGB(128,0,0),
  17.     RGB(0,128,0),
  18.     RGB(128,128,0),
  19.     RGB(0,0,128),
  20.     RGB(128,0,128),
  21.     RGB(0,128,128),
  22.     RGB(192,192,192),
  23.     RGB(192,220,192),
  24.     RGB(166,202,240),
  25.     RGB(255,251,240),
  26.     RGB(160,160,164),
  27.     RGB(128,128,128),
  28.     RGB(255,0,0),
  29.     RGB(0,255,0),
  30.     RGB(255,255,0),
  31.     RGB(0,0,255),
  32.     RGB(255,0,255),
  33.     RGB(0,255,255),
  34.     RGB(255,255,255)
  35. };
  36.  
  37. // MRU table. See notes for Reset()
  38.  
  39. BYTE CColorBtnDlg::used[20] =
  40. {    
  41.     1,3,5,7,9,11,13,15,17,19,20,18,16,14,12,10,8,6,4,2    
  42. };
  43.  
  44. /////////////////////////////////////////////////////////////////////////////
  45. // CColorBtn
  46.  
  47. CColorBtn::CColorBtn()
  48. {
  49.     currentcolor = RGB(255,255,255);
  50.  
  51.     dlg.parent = this;   // This will allow the dialog to position itself
  52.  
  53.     // Create the pens and brushes that we'll need to draw the button
  54.  
  55.     nullpen.CreateStockObject(NULL_PEN);
  56.     blackpen.CreateStockObject(BLACK_PEN);
  57.     whitepen.CreateStockObject(WHITE_PEN);
  58.  
  59.     nullbrush.CreateStockObject(NULL_BRUSH);
  60.     backbrush.CreateSolidBrush(GetSysColor(COLOR_3DFACE));
  61.     dkgray.CreatePen(PS_SOLID,1,RGB(128,128,128));         
  62. }
  63.  
  64.  
  65. CColorBtn::~CColorBtn()
  66. {
  67. }
  68.  
  69.  
  70. BEGIN_MESSAGE_MAP(CColorBtn, CButton)
  71.     //{{AFX_MSG_MAP(CColorBtn)    
  72.     ON_CONTROL_REFLECT(BN_CLICKED, OnClicked)
  73.     //}}AFX_MSG_MAP
  74. END_MESSAGE_MAP()
  75.  
  76. /////////////////////////////////////////////////////////////////////////////
  77. // CColorBtn message handlers
  78.  
  79.  
  80. void CColorBtn::DrawItem(LPDRAWITEMSTRUCT lpd)
  81. {
  82.     // Draw the button
  83.  
  84.     CBrush colorbrush;
  85.  
  86.     CDC DC;
  87.  
  88.     DC.Attach(lpd->hDC);
  89.     
  90.     int top,left,bottom,right;
  91.  
  92.     // Store this for convinience
  93.  
  94.     top    = lpd->rcItem.top;
  95.     left   = lpd->rcItem.left;
  96.     bottom = lpd->rcItem.bottom;
  97.     right  = lpd->rcItem.right;
  98.                 
  99.     colorbrush.CreateSolidBrush(currentcolor);
  100.     
  101.     oldpen   = DC.SelectObject(&nullpen);
  102.     oldbrush = DC.SelectObject(&backbrush);
  103.  
  104.     // Clear the background using the 3DFACE color.
  105.  
  106.     DC.Rectangle(&lpd->rcItem);
  107.  
  108.     // Draw the border
  109.  
  110.     if (!(lpd->itemState & ODS_SELECTED))
  111.     {
  112.         // Button is up
  113.  
  114.         DC.SelectObject(&blackpen);
  115.  
  116.         DC.MoveTo(left,bottom-1);
  117.         DC.LineTo(right-1,bottom-1);
  118.         DC.LineTo(right-1,top);
  119.  
  120.         DC.SelectObject(&dkgray);
  121.  
  122.         DC.MoveTo(left+1,bottom-2);
  123.         DC.LineTo(right-2,bottom-2);
  124.         DC.LineTo(right-2,top+1);
  125.  
  126.         DC.SelectObject(&whitepen);
  127.  
  128.         DC.LineTo(left+1,top+1);
  129.         DC.LineTo(left+1,bottom-2);
  130.         
  131.     }
  132.     else
  133.     {
  134.         // Button is down
  135.  
  136.         DC.SelectObject(&dkgray);            
  137.  
  138.         DC.MoveTo(left,bottom-1);
  139.  
  140.         DC.LineTo(left,top);
  141.         DC.LineTo(right-1,top);
  142.  
  143.         DC.SelectObject(&whitepen);
  144.  
  145.         DC.MoveTo(right-1,top-1);
  146.  
  147.         DC.LineTo(right-1,bottom-1);
  148.         DC.LineTo(left+1,bottom-1);
  149.  
  150.         DC.SelectObject(&blackpen);
  151.  
  152.         DC.MoveTo(left+1,bottom-2);
  153.         DC.LineTo(left+1,top+1);
  154.         DC.LineTo(right-2,top+1);
  155.  
  156.         // by moving this, we get the things inside the button
  157.         // to draw themselves one pixel down and one to the right.
  158.         // This completes the "pushed" effect
  159.  
  160.         left++;
  161.         right++;
  162.         bottom++;
  163.         top++;
  164.  
  165.     }
  166.  
  167.     // The division
  168.  
  169.     DC.SelectObject(&whitepen);
  170.     
  171.     DC.MoveTo(right-10,top+4);
  172.     DC.LineTo(right-10,bottom-4);
  173.  
  174.     DC.SelectObject(dkgray);
  175.  
  176.     DC.MoveTo(right-11,top+4);
  177.     DC.LineTo(right-11,bottom-4);
  178.  
  179.     // The triangle
  180.  
  181.     if (lpd->itemState & ODS_DISABLED)
  182.         DC.SelectObject(dkgray);
  183.     else
  184.         DC.SelectObject(blackpen);
  185.     
  186.     DC.MoveTo(right-4,(bottom/2)-1);
  187.     DC.LineTo(right-9,(bottom/2)-1);
  188.  
  189.     DC.MoveTo(right-5,(bottom/2));
  190.     DC.LineTo(right-8,(bottom/2));
  191.  
  192.     if (lpd->itemState & ODS_DISABLED)    
  193.     {
  194.         DC.SetPixel(right-4,(bottom/2)-1,RGB(255,255,255));
  195.         DC.SetPixel(right-5,(bottom/2),RGB(255,255,255));
  196.         DC.SetPixel(right-6,(bottom/2)+1,RGB(255,255,255));
  197.     }
  198.     else
  199.     {
  200.         DC.SetPixel(right-6,(bottom/2)+1,RGB(0,0,0));
  201.     }
  202.  
  203.     if (!(lpd->itemState & ODS_DISABLED))
  204.     {
  205.         // The color rectangle, only if enabled
  206.  
  207.         DC.SelectObject(&colorbrush);
  208.  
  209.         DC.Rectangle(left+5,top+4,right-15,bottom-4);    
  210.     }
  211.  
  212.     if (lpd->itemState & ODS_FOCUS)
  213.     {
  214.         // Draw the focus
  215.         //
  216.         // It would have been nice just to
  217.         // draw a rectangle using a pen created
  218.         // with the PS_ALTERNATE style, but
  219.         // this is not supported by WIN95
  220.  
  221.         int i;
  222.  
  223.         for (i=left+3;i<right-4;i+=2)
  224.         {
  225.             DC.SetPixel(i,top+3,RGB(0,0,0));
  226.             DC.SetPixel(i,bottom-4,RGB(0,0,0));
  227.         }
  228.  
  229.         for (i=top+3;i<bottom-4;i+=2)
  230.         {
  231.             DC.SetPixel(left+3,i,RGB(0,0,0));
  232.             DC.SetPixel(right-4,i,RGB(0,0,0));
  233.         }       
  234.     }
  235.         
  236.     DC.SelectObject(oldpen);
  237.     DC.SelectObject(oldbrush);
  238.  
  239.  
  240.     DC.Detach();    
  241. }
  242.  
  243.  
  244. void CColorBtn::OnClicked() 
  245. {
  246.     // When the button is clicked, show the dialog.
  247.     if (dlg.colorindex == -1)
  248.     {
  249.         for (int i=0;i<20;i++)
  250.         {
  251.             if (dlg.colors[i] == currentcolor)
  252.             {
  253.                 dlg.colorindex = i;
  254.                 break;
  255.             }
  256.         }
  257.     }
  258.     if (dlg.DoModal() == IDOK)
  259.     {
  260.         currentcolor = CColorBtnDlg::colors[dlg.colorindex];
  261.         InvalidateRect(NULL);
  262.     }    
  263. }
  264.  
  265. // Store and Load use an undocumented CWinApp function
  266.  
  267. BOOL CColorBtn::Store()
  268. {
  269.     return (AfxGetApp()->WriteProfileBinary(_T("ColorData"), _T("ColorTable"),(LPBYTE)CColorBtnDlg::colors,sizeof(COLORREF)*20) &&
  270.             AfxGetApp()->WriteProfileBinary(_T("ColorData"), _T("MRU"),(LPBYTE)CColorBtnDlg::used,sizeof(BYTE)*20));
  271.  
  272. }
  273.  
  274. BOOL CColorBtn::Load()
  275. {
  276.     BYTE *data = NULL;
  277.     UINT size;
  278.  
  279.     // This function allocates the memory it needs
  280.  
  281.     AfxGetApp()->GetProfileBinary(_T("ColorData"), _T("ColorTable"),&data,&size);    
  282.  
  283.     if (data)
  284.     {
  285.         // Copy the data into our table and get rid of the buffer
  286.  
  287.         memcpy((void *)CColorBtnDlg::colors,(void *)data,size);
  288.         free((void *)data);
  289.  
  290.         AfxGetApp()->GetProfileBinary(_T("ColorData"), _T("MRU"),&data,&size);    
  291.  
  292.         if (data)
  293.         {
  294.             memcpy((void *)CColorBtnDlg::used,(void *)data,size);
  295.             free((void *)data);
  296.             return TRUE;
  297.         }
  298.         
  299.     }
  300.  
  301.     // If the loading fails, back to the defaults
  302.     
  303.     Reset();
  304.  
  305.     return FALSE;
  306. }
  307.  
  308.  
  309. void CColorBtn::Reset()
  310. {
  311.     CColorBtnDlg::colors[0]  = RGB(0,0,0);
  312.     CColorBtnDlg::colors[1]  = RGB(128,0,0);
  313.     CColorBtnDlg::colors[2]  = RGB(0,128,0);
  314.     CColorBtnDlg::colors[3]  = RGB(128,128,0);
  315.     CColorBtnDlg::colors[4]  = RGB(0,0,128);
  316.     CColorBtnDlg::colors[5]  = RGB(128,0,128);
  317.     CColorBtnDlg::colors[6]  = RGB(0,128,128);
  318.     CColorBtnDlg::colors[7]  = RGB(192,192,192);
  319.     CColorBtnDlg::colors[8]  = RGB(192,220,192);
  320.     CColorBtnDlg::colors[9]  = RGB(166,202,240);
  321.     CColorBtnDlg::colors[10] = RGB(255,251,240);
  322.     CColorBtnDlg::colors[11] = RGB(160,160,164);
  323.     CColorBtnDlg::colors[12] = RGB(128,128,128);
  324.     CColorBtnDlg::colors[13] = RGB(255,0,0);
  325.     CColorBtnDlg::colors[14] = RGB(0,255,0);
  326.     CColorBtnDlg::colors[15] = RGB(255,255,0);
  327.     CColorBtnDlg::colors[16] = RGB(0,0,255);
  328.     CColorBtnDlg::colors[17] = RGB(255,0,255);
  329.     CColorBtnDlg::colors[18] = RGB(0,255,255);
  330.     CColorBtnDlg::colors[19] = RGB(255,255,255);
  331.  
  332.     // This "colorful" (no pun intended) order ensures
  333.     // that the colors at the center of the color table
  334.     // will get replaced first. This preserves the white
  335.     // and black colors even if they're not used (They'll
  336.     // get replaced last).
  337.     
  338.     CColorBtnDlg::used[0]= 1;
  339.     CColorBtnDlg::used[1]= 3;
  340.     CColorBtnDlg::used[2]= 5;
  341.     CColorBtnDlg::used[3]= 7;
  342.     CColorBtnDlg::used[4]= 9;
  343.     CColorBtnDlg::used[5]= 11;
  344.     CColorBtnDlg::used[6]= 13;
  345.     CColorBtnDlg::used[7]= 15;
  346.     CColorBtnDlg::used[8]= 17;
  347.     CColorBtnDlg::used[9]= 19;
  348.     CColorBtnDlg::used[10]= 20;
  349.     CColorBtnDlg::used[11]= 18;
  350.     CColorBtnDlg::used[12]= 16;
  351.     CColorBtnDlg::used[13]= 14;
  352.     CColorBtnDlg::used[14]= 12;
  353.     CColorBtnDlg::used[15]= 10;
  354.     CColorBtnDlg::used[16]= 8;
  355.     CColorBtnDlg::used[17]= 6;
  356.     CColorBtnDlg::used[18]= 4;
  357.     CColorBtnDlg::used[19]= 2;
  358. }
  359.  
  360.  
  361. //void CColorBtn::Serialize( CArchive& ar )
  362. //{
  363. //    if (ar.IsStoring())
  364. //    {
  365. //        ar.Write((void *)CColorBtnDlg::colors,sizeof(COLORREF)*20);
  366. //        ar.Write((void *)CColorBtnDlg::used,sizeof(BYTE)*20);
  367. //    }
  368. //    else
  369. //    {
  370. //        ar.Read((void *)CColorBtnDlg::colors,sizeof(COLORREF)*20);
  371. //        ar.Read((void *)CColorBtnDlg::used,sizeof(BYTE)*20);
  372. //    }
  373. //}
  374.  
  375.  
  376.  
  377.  
  378. /////////////////////////////////////////////////////////////////////////////
  379. // CColorBtnDlg dialog
  380.  
  381.  
  382. CColorBtnDlg::CColorBtnDlg(CWnd* pParent /*=NULL*/)
  383.     : CDialog(CColorBtnDlg::IDD, pParent)
  384. {
  385.     //{{AFX_DATA_INIT(CColorBtnDlg)
  386.         // NOTE: the ClassWizard will add member initialization here
  387.     //}}AFX_DATA_INIT
  388.     colorindex = -1;
  389. }
  390.  
  391.  
  392. void CColorBtnDlg::DoDataExchange(CDataExchange* pDX)
  393. {
  394.     CDialog::DoDataExchange(pDX);
  395.     //{{AFX_DATA_MAP(CColorBtnDlg)
  396.         // NOTE: the ClassWizard will add DDX and DDV calls here
  397.     //}}AFX_DATA_MAP
  398. }
  399.  
  400.  
  401. BEGIN_MESSAGE_MAP(CColorBtnDlg, CDialog)
  402.     //{{AFX_MSG_MAP(CColorBtnDlg)
  403.     ON_BN_CLICKED(IDC_OTHER, OnOther)
  404.     ON_WM_LBUTTONDOWN()    
  405.     ON_WM_LBUTTONUP()
  406.     ON_WM_DRAWITEM()    
  407.     //}}AFX_MSG_MAP
  408.     ON_COMMAND_RANGE(IDC_COLOR1,IDC_COLOR20,OnColor)
  409. END_MESSAGE_MAP()
  410.  
  411.  
  412. /////////////////////////////////////////////////////////////////////////////
  413. // CColorBtnDlg message handlers
  414.  
  415. BOOL CColorBtnDlg::OnInitDialog() 
  416. {
  417.     CDialog::OnInitDialog();
  418.  
  419.     RECT r,r2;
  420.     
  421.     parent->GetWindowRect(&r);
  422.     
  423.     // Move the dialog to be below the button
  424.  
  425.     SetWindowPos(NULL,r.left,r.bottom,0,0,SWP_NOSIZE|SWP_NOZORDER);
  426.  
  427.     GetWindowRect(&r2);
  428.  
  429.     // Check to see if the dialog has a portion outside the
  430.     // screen, if so, adjust.
  431.     
  432.     if (r2.bottom > GetSystemMetrics(SM_CYSCREEN))
  433.     {   
  434.         r2.top = r.top-(r2.bottom-r2.top);        
  435.     }
  436.  
  437.     if (r2.right > GetSystemMetrics(SM_CXSCREEN))
  438.     {
  439.         r2.left = GetSystemMetrics(SM_CXSCREEN) - (r2.right-r2.left);
  440.     }
  441.  
  442.     SetWindowPos(NULL,r2.left,r2.top,0,0,SWP_NOSIZE|SWP_NOZORDER);
  443.  
  444.     // Capture the mouse, this allows the dialog to close when
  445.     // the user clicks outside.
  446.  
  447.     // Remember that the dialog has no "close" button.
  448.  
  449.     SetCapture();
  450.  
  451.     if (colorindex != -1)
  452.     {
  453.         CWnd *pCtl = GetDlgItem(IDC_COLOR1 + colorindex);
  454.         if (pCtl)
  455.         {
  456.             pCtl->SetFocus();
  457.             return FALSE;
  458.         }
  459.     }
  460.     
  461.     return TRUE; 
  462. }
  463.  
  464.  
  465.  
  466. void CColorBtnDlg::EndDialog( int nResult )
  467. {
  468.     ReleaseCapture();
  469.  
  470.     CDialog::EndDialog(nResult);
  471. }
  472.  
  473.  
  474. void CColorBtnDlg::OnLButtonDown(UINT nFlags, CPoint point) 
  475. {
  476.     RECT r;
  477.  
  478.     POINT p;
  479.     p.x = point.x;
  480.     p.y = point.y;
  481.  
  482.     ClientToScreen(&p);
  483.  
  484.     GetWindowRect(&r);
  485.  
  486.     // The user clicked...
  487.  
  488.     if (!PtInRect(&r,p))
  489.     {
  490.         //  ...outside the dialog, close.
  491.  
  492.         EndDialog(IDCANCEL);
  493.     }
  494.     else
  495.     {
  496.         //  ...inside the dialog. Since this window
  497.         //     has the mouse captured, its children
  498.         //     get no messages. So, check to see
  499.         //     if the click was in one of its children
  500.         //     and tell him.
  501.  
  502.         //     If the user clicks inside the dialog
  503.         //     but not on any of the controls,
  504.         //     ChildWindowFromPoint returns a
  505.         //     pointer to the dialog. In this
  506.         //     case we do not resend the message
  507.         //     (obviously) because it would cause
  508.         //     a stack overflow.
  509.         
  510.         CWnd *child = ChildWindowFromPoint(point);
  511.  
  512.         if (child && child != this)
  513.             child->SendMessage(WM_LBUTTONDOWN,0,0l);
  514.     }
  515.     
  516.     CDialog::OnLButtonDown(nFlags, point);
  517. }
  518.  
  519.  
  520. void CColorBtnDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpd) 
  521. {
  522.     CDC dc;
  523.     CPen nullpen;
  524.     CBrush brush;
  525.     CPen *oldpen;
  526.     CBrush *oldbrush;
  527.  
  528.     // Draw the wells using the current color table
  529.  
  530.     nullpen.CreateStockObject(NULL_PEN);
  531.     brush.CreateSolidBrush(colors[nIDCtl-IDC_COLOR1]);
  532.  
  533.     dc.Attach(lpd->hDC);
  534.  
  535.     oldpen = dc.SelectObject(&nullpen);
  536.     oldbrush = dc.SelectObject(&brush);
  537.  
  538.     lpd->rcItem.right++;
  539.     lpd->rcItem.bottom++;
  540.  
  541.     dc.Rectangle(&lpd->rcItem);
  542.     if (lpd->itemState & ODS_FOCUS)
  543.     {
  544.         CRect rcFocus(lpd->rcItem);
  545.         rcFocus.DeflateRect(1, 1);
  546.         dc.DrawFocusRect(rcFocus);
  547.     }
  548.  
  549.     dc.SelectObject(oldpen);
  550.     dc.SelectObject(oldbrush);
  551.  
  552.     dc.Detach();
  553.     
  554.     CDialog::OnDrawItem(nIDCtl, lpd);
  555. }
  556.  
  557.  
  558. void CColorBtnDlg::OnColor(UINT id)
  559. {
  560.  
  561.     // A well has been clicked, set the color index
  562.     // and close.
  563.  
  564.     colorindex = id-IDC_COLOR1;
  565.     
  566.     int i;
  567.  
  568.     // This color is now the MRU
  569.  
  570.     for (i=0;i<20;i++)
  571.     {
  572.         if (used[colorindex] > used[i])
  573.         {
  574.             used[i]++;
  575.         }
  576.     }
  577.  
  578.     used[colorindex] = 1;
  579.  
  580.     EndDialog(IDOK);
  581.  
  582. }
  583.  
  584. void CColorBtnDlg::OnOther() 
  585. {
  586. int i;
  587. COLORREF newcolor;
  588.  
  589.     // The "Other" button.
  590.  
  591.     ReleaseCapture();
  592.  
  593.     CColorDialog dlg;
  594.  
  595.     dlg.m_cc.Flags |= CC_FULLOPEN;
  596.  
  597.  
  598.     if (dlg.DoModal() == IDOK)
  599.     {
  600.         // The user clicked OK.
  601.         // set the color and close
  602.         
  603.         newcolor = dlg.GetColor();            
  604.  
  605.         // Check to see if the selected color is
  606.         // already in the table.
  607.  
  608.         colorindex = -1;
  609.  
  610.         for (i=0;i<20;i++)
  611.         {
  612.             if (colors[i] == newcolor)
  613.             {
  614.                 colorindex = i;
  615.                 break;
  616.             }
  617.         }
  618.  
  619.         // If the color was not found,
  620.         // replace the LRU with this color
  621.  
  622.         if (colorindex == -1)
  623.         {
  624.             for (i=0;i<20;i++)
  625.             {
  626.                 if (used[i] == 20)
  627.                 {
  628.                     colors[i] = newcolor;
  629.                     colorindex = i;                                 
  630.                     break;
  631.                 }
  632.             }
  633.         }
  634.  
  635.         // This is the new MRU
  636.  
  637.         for (i=0;i<20;i++)
  638.         {
  639.             if (used[colorindex] > used[i])
  640.             {
  641.                 used[i]++;
  642.             }         
  643.         }
  644.  
  645.         used[colorindex] = 1;
  646.  
  647.         EndDialog(IDOK);
  648.  
  649.         return;
  650.     }
  651.  
  652.     // If the user clicked "Cancel" reclaim the mouse capture.
  653.  
  654.     SetCapture();            
  655. }
  656.  
  657.  
  658. void CColorBtnDlg::OnLButtonUp(UINT nFlags, CPoint point) 
  659. {
  660.  
  661.     // See notes for OnLButtonDown.
  662.     
  663.     CWnd *child = ChildWindowFromPoint(point,CWP_ALL);
  664.     
  665.     if (child && child != this)
  666.         child->SendMessage(WM_LBUTTONDOWN,0,0l);    
  667.     
  668.     CDialog::OnLButtonUp(nFlags, point);
  669. }
  670.  
  671.  
  672.