ColourPopup.cpp
上传用户:wujian85
上传日期:2010-04-08
资源大小:227k
文件大小:21k
源码类别:

对话框与窗口

开发平台:

Visual C++

  1. // ColourPopup.cpp : implementation file
  2. //
  3. // Written by Chris Maunder (Chris.Maunder@cbr.clw.csiro.au)
  4. // Extended by Alexander Bischofberger (bischofb@informatik.tu-muenchen.de)
  5. // Copyright (c) 1998.
  6. //
  7. // ColourPopup is a helper class for the colour picker control
  8. // CColourPicker. Check out the header file or the accompanying 
  9. // HTML doc file for details.
  10. //
  11. // This code may be used in compiled form in any way you desire. This
  12. // file may be redistributed unmodified by any means PROVIDING it is 
  13. // not sold for profit without the authors written consent, and 
  14. // providing that this notice and the authors name is included. 
  15. //
  16. // This file is provided "as is" with no expressed or implied warranty.
  17. // The author accepts no liability if it causes any damage to you or your
  18. // computer whatsoever. It's free, so don't hassle me about it.
  19. //
  20. // Expect bugs.
  21. // 
  22. // Please use and enjoy. Please let me know of any bugs/mods/improvements 
  23. // that you have found/implemented and I will fix/incorporate them into this
  24. // file. 
  25. #include "stdafx.h"
  26. #include <math.h>
  27. #include "ColourPicker.h"
  28. #include "ColourPopup.h"
  29. extern bool bLockingProperty;
  30. #ifdef _DEBUG
  31. #define new DEBUG_NEW
  32. #undef THIS_FILE
  33. static char THIS_FILE[] = __FILE__;
  34. #endif
  35. #define TEXT_BOX_VALUE -2        // Sorry about this hack...
  36. #define MAX_COLOURS    100
  37. ColourTableEntry CColourPopup::m_crColours[] = 
  38. {
  39.     { RGB(0x00, 0x00, 0x00),    _T("Black")             },
  40.     { RGB(0xA5, 0x2A, 0x00),    _T("Brown")             },
  41.     { RGB(0x00, 0x40, 0x40),    _T("Dark Olive Green")  },
  42.     { RGB(0x00, 0x55, 0x00),    _T("Dark Green")        },
  43.     { RGB(0x00, 0x00, 0x5E),    _T("Dark Teal")         },
  44.     { RGB(0x00, 0x00, 0x8B),    _T("Dark blue")         },
  45.     { RGB(0x4B, 0x00, 0x82),    _T("Indigo")            },
  46.     { RGB(0x28, 0x28, 0x28),    _T("Dark grey")         },
  47.     { RGB(0x8B, 0x00, 0x00),    _T("Dark red")          },
  48.     { RGB(0xFF, 0x68, 0x20),    _T("Orange")            },
  49.     { RGB(0x8B, 0x8B, 0x00),    _T("Dark yellow")       },
  50.     { RGB(0x00, 0x93, 0x00),    _T("Green")             },
  51.     { RGB(0x38, 0x8E, 0x8E),    _T("Teal")              },
  52.     { RGB(0x00, 0x00, 0xFF),    _T("Blue")              },
  53.     { RGB(0x7B, 0x7B, 0xC0),    _T("Blue-grey")         },
  54.     { RGB(0x66, 0x66, 0x66),    _T("Grey - 40")         },
  55.     { RGB(0xFF, 0x00, 0x00),    _T("Red")               },
  56.     { RGB(0xFF, 0xAD, 0x5B),    _T("Light orange")      },
  57.     { RGB(0x32, 0xCD, 0x32),    _T("Lime")              }, 
  58.     { RGB(0x3C, 0xB3, 0x71),    _T("Sea green")         },
  59.     { RGB(0x7F, 0xFF, 0xD4),    _T("Aqua")              },
  60.     { RGB(0x7D, 0x9E, 0xC0),    _T("Light blue")        },
  61.     { RGB(0x80, 0x00, 0x80),    _T("Violet")            },
  62.     { RGB(0x7F, 0x7F, 0x7F),    _T("Grey - 50")         },
  63.     { RGB(0xFF, 0xC0, 0xCB),    _T("Pink")              },
  64.     { RGB(0xFF, 0xD7, 0x00),    _T("Gold")              },
  65.     { RGB(0xFF, 0xFF, 0x00),    _T("Yellow")            },    
  66.     { RGB(0x00, 0xFF, 0x00),    _T("Bright green")      },
  67.     { RGB(0x40, 0xE0, 0xD0),    _T("Turquoise")         },
  68.     { RGB(0xC0, 0xFF, 0xFF),    _T("Skyblue")           },
  69.     { RGB(0x48, 0x00, 0x48),    _T("Plum")              },
  70.     { RGB(0xC0, 0xC0, 0xC0),    _T("Light grey")        },
  71.     { RGB(0xFF, 0xE4, 0xE1),    _T("Rose")              },
  72.     { RGB(0xD2, 0xB4, 0x8C),    _T("Tan")               },
  73.     { RGB(0xFF, 0xFF, 0xE0),    _T("Light yellow")      },
  74.     { RGB(0x98, 0xFB, 0x98),    _T("Pale green ")       },
  75.     { RGB(0xAF, 0xEE, 0xEE),    _T("Pale turquoise")    },
  76.     { RGB(0x68, 0x83, 0x8B),    _T("Pale blue")         },
  77.     { RGB(0xE6, 0xE6, 0xFA),    _T("Lavender")          },
  78.     { RGB(0xFF, 0xFF, 0xFF),    _T("White")             }
  79. };
  80. /////////////////////////////////////////////////////////////////////////////
  81. // CColourPopup
  82. CColourPopup::CColourPopup()
  83. {
  84.     Initialise();
  85. }
  86. CColourPopup::CColourPopup(CPoint p, COLORREF crColour, CWnd* pParentWnd, UINT nID, 
  87.                            LPCTSTR szCustomText /* = NULL */)
  88. {
  89.     Initialise();
  90.     m_crColour = m_crInitialColour = crColour;
  91.     if (szCustomText != NULL)
  92.     {
  93.         m_bShowCustom   = TRUE;
  94.         m_strCustomText = szCustomText;
  95.     } else
  96.         m_bShowCustom = FALSE;
  97.     m_pParent           = pParentWnd;
  98.     CColourPopup::Create(p, crColour, pParentWnd, nID, szCustomText);
  99. }
  100. void CColourPopup::Initialise()
  101. {
  102.     m_nNumColours       = sizeof(m_crColours)/sizeof(ColourTableEntry);
  103.     ASSERT(m_nNumColours <= MAX_COLOURS);
  104.     if (m_nNumColours > MAX_COLOURS)
  105.         m_nNumColours = MAX_COLOURS;
  106.     m_nNumColumns       = 0;
  107.     m_nNumRows          = 0;
  108.     m_nBoxSize          = 18;
  109.     m_nMargin           = ::GetSystemMetrics(SM_CXEDGE);
  110.     m_nCurrentRow       = -1;
  111.     m_nCurrentCol       = -1;
  112.     m_nChosenColourRow  = -1;
  113.     m_nChosenColourCol  = -1;
  114.     m_strCustomText     = _T("More...");
  115.     m_bShowCustom       = TRUE;
  116.     m_pParent           = NULL;
  117.     m_crColour          = m_crInitialColour = RGB(0,0,0);
  118.     // Idiot check: Make sure the colour square is at least 5 x 5;
  119.     if (m_nBoxSize - 2*m_nMargin - 2 < 5) m_nBoxSize = 5 + 2*m_nMargin + 2;
  120.     // Create the font
  121.     NONCLIENTMETRICS ncm;
  122.     ncm.cbSize = sizeof(NONCLIENTMETRICS);
  123.     VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0));
  124.     m_Font.CreateFontIndirect(&(ncm.lfMessageFont));
  125.     // Create the palette
  126.     struct {
  127.         LOGPALETTE    LogPalette;
  128.         PALETTEENTRY  PalEntry[MAX_COLOURS];
  129.     } pal;
  130.     LOGPALETTE* pLogPalette = (LOGPALETTE*) &pal;
  131.     pLogPalette->palVersion    = 0x300;
  132.     pLogPalette->palNumEntries = m_nNumColours; 
  133.     for (int i = 0; i < m_nNumColours; i++)
  134.     {
  135.         pLogPalette->palPalEntry[i].peRed   = GetRValue(m_crColours[i].crColour);
  136.         pLogPalette->palPalEntry[i].peGreen = GetGValue(m_crColours[i].crColour);
  137.         pLogPalette->palPalEntry[i].peBlue  = GetBValue(m_crColours[i].crColour);
  138.         pLogPalette->palPalEntry[i].peFlags = 0;
  139.     }
  140.     m_Palette.CreatePalette(pLogPalette);
  141. }
  142. CColourPopup::~CColourPopup()
  143. {
  144.     m_Font.DeleteObject();
  145.     m_Palette.DeleteObject();
  146. }
  147. BOOL CColourPopup::Create(CPoint p, COLORREF crColour, CWnd* pParentWnd, UINT nID, 
  148.                           LPCTSTR szCustomText /* = NULL */)
  149. {
  150.     ASSERT(pParentWnd && ::IsWindow(pParentWnd->GetSafeHwnd()));
  151.     ASSERT(pParentWnd->IsKindOf(RUNTIME_CLASS(CColourPicker)));
  152.     m_pParent  = pParentWnd;
  153.     m_crColour = m_crInitialColour = crColour;
  154.     // Get the class name and create the window
  155.     CString szClassName = AfxRegisterWndClass(CS_CLASSDC|CS_SAVEBITS|CS_HREDRAW|CS_VREDRAW,
  156.                                               0, (HBRUSH)GetStockObject(LTGRAY_BRUSH),0);
  157.     if (!CWnd::CreateEx(0, szClassName, _T(""), WS_VISIBLE|WS_POPUP, 
  158.                         p.x, p.y, 100, 100, // size updated soon
  159.                         pParentWnd->GetSafeHwnd(), 0, NULL))
  160.         return FALSE;
  161.     // Store the Custom text
  162.     if (szCustomText != NULL) 
  163.         m_strCustomText = szCustomText;
  164.     // Set the window size
  165.     SetWindowSize();
  166.     // Create the tooltips
  167.     CreateToolTips();
  168.     // Find which cell (if any) corresponds to the initial colour
  169.     FindCellFromColour(crColour);
  170.     // Capture all mouse events for the life of this window
  171.     SetCapture();
  172.     return TRUE;
  173. }
  174. BEGIN_MESSAGE_MAP(CColourPopup, CWnd)
  175.     //{{AFX_MSG_MAP(CColourPopup)
  176.     ON_WM_NCDESTROY()
  177.     ON_WM_LBUTTONUP()
  178.     ON_WM_PAINT()
  179.     ON_WM_MOUSEMOVE()
  180.     ON_WM_KEYDOWN()
  181.     ON_WM_QUERYNEWPALETTE()
  182.     ON_WM_PALETTECHANGED()
  183.     //}}AFX_MSG_MAP
  184. END_MESSAGE_MAP()
  185. /////////////////////////////////////////////////////////////////////////////
  186. // CColourPopup message handlers
  187. // For tooltips
  188. BOOL CColourPopup::PreTranslateMessage(MSG* pMsg) 
  189. {
  190.     m_ToolTip.RelayEvent(pMsg);
  191.     return CWnd::PreTranslateMessage(pMsg);
  192. }
  193. // If an arrow key is pressed, then move the selection
  194. void CColourPopup::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
  195. {
  196.     int row = m_nCurrentRow,
  197.         col = m_nCurrentCol;
  198.     if (nChar == VK_DOWN) 
  199.     {
  200.         if (row < 0) { row = 0; col = 0; }
  201.         else if (row < m_nNumRows-1) row++;
  202.         else { row = TEXT_BOX_VALUE; col = TEXT_BOX_VALUE; }
  203.         ChangeSelection(row, col);
  204.     }
  205.       if (nChar == VK_UP) 
  206.     {
  207.         if (row < 0) { row = m_nNumRows-1; col = 0; }
  208.         else if (row > 0) row--;
  209.         else { row = TEXT_BOX_VALUE; col = TEXT_BOX_VALUE; }
  210.         ChangeSelection(row, col);
  211.     }
  212.     if (nChar == VK_RIGHT) 
  213.     {
  214.         if (col < 0) { row = 0; col = 0; }
  215.         else if (col < m_nNumColumns-1) col++;
  216.         else col = 0;
  217.         ChangeSelection(row, col);
  218.     }
  219.     if (nChar == VK_LEFT) 
  220.     {
  221.         if (col < 0) { row = m_nNumRows-1; col = m_nNumColumns-1; }
  222.         else if (col > 0) col--;
  223.         else col = m_nNumColumns-1;
  224.         ChangeSelection(row, col);
  225.     }
  226.     if (nChar == VK_ESCAPE) 
  227.     {
  228.         m_crColour = m_crInitialColour;
  229.         EndSelection(CPN_SELENDCANCEL);
  230.         return;
  231.     }
  232.     if (nChar == VK_RETURN)
  233.     {
  234.         EndSelection(CPN_SELENDOK);
  235.         return;
  236.     }
  237.     CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
  238. }
  239. // auto-deletion
  240. void CColourPopup::OnNcDestroy() 
  241. {
  242.     CWnd::OnNcDestroy();
  243.     delete this;
  244. bLockingProperty = false;
  245. }
  246. void CColourPopup::OnPaint() 
  247. {
  248.     CPaintDC dc(this); // device context for painting
  249.     // Draw colour cells
  250.     for (int row = 0; row < m_nNumRows; row++)
  251.         for (int col = 0; col < m_nNumColumns; col++)
  252.             DrawCell(&dc, row, col);
  253.     
  254.     // Draw custom text
  255.     if (m_bShowCustom)
  256.         DrawCell(&dc, TEXT_BOX_VALUE, TEXT_BOX_VALUE);
  257.     // Draw raised window edge (ex-window style WS_EX_WINDOWEDGE is sposed to do this,
  258.     // but for some reason isn't
  259.     CRect rect;
  260.     GetClientRect(rect);
  261.     dc.DrawEdge(rect, EDGE_RAISED, BF_RECT);
  262. }
  263. void CColourPopup::OnMouseMove(UINT nFlags, CPoint point) 
  264. {
  265.     int row, col;
  266.     // Translate points to be relative raised window edge
  267.     point.x -= m_nMargin;
  268.     point.y -= m_nMargin;
  269.     // First check we aren't in text box
  270.     if (m_bShowCustom && m_TextRect.PtInRect(point))
  271.         row = col = TEXT_BOX_VALUE;        // Special value meaning Text Box (hack!)
  272.     else
  273.     {
  274.         // Take into account text box
  275.         if (m_bShowCustom) 
  276.             point.y -= m_TextRect.Height();  
  277.         // Get the row and column
  278.         row = point.y / m_nBoxSize,
  279.         col = point.x / m_nBoxSize;
  280.         // In range? If not, default and exit
  281.         if (row < 0 || row >= m_nNumRows ||
  282.             col < 0 || col >= m_nNumColumns)
  283.         {
  284.             CWnd::OnMouseMove(nFlags, point);
  285.             return;
  286.         }
  287.     }
  288.     // OK - we have the row and column of the current selection (may be TEXT_BOX_VALUE)
  289.     // Has the row/col selection changed? If yes, then redraw old and new cells.
  290.     if (row != m_nCurrentRow || col != m_nCurrentCol)
  291.     {
  292.         ChangeSelection(row, col);
  293.     }
  294.     CWnd::OnMouseMove(nFlags, point);
  295. }
  296. // End selection on LButtonUp
  297. void CColourPopup::OnLButtonUp(UINT nFlags, CPoint point) 
  298. {    
  299.     CWnd::OnLButtonUp(nFlags, point);
  300.     DWORD pos = GetMessagePos();
  301.     point = CPoint(LOWORD(pos), HIWORD(pos));
  302.     if (m_WindowRect.PtInRect(point))
  303.         EndSelection(CPN_SELENDOK);
  304.     else
  305.         EndSelection(CPN_SELENDCANCEL);
  306. }
  307. /////////////////////////////////////////////////////////////////////////////
  308. // CColourPopup implementation
  309. void CColourPopup::FindCellFromColour(COLORREF crColour)
  310. {
  311.     for (int row = 0; row < m_nNumRows; row++)
  312.         for (int col = 0; col < m_nNumColumns; col++)
  313.         {
  314.             if (GetColour(row, col) == crColour)
  315.             {
  316.                 m_nChosenColourRow  = row;
  317.                 m_nChosenColourCol  = col;
  318.                 return;
  319.             }
  320.         }
  321.     m_nChosenColourRow  = TEXT_BOX_VALUE;
  322.     m_nChosenColourCol  = TEXT_BOX_VALUE;
  323. }
  324. // Gets the dimensions of the colour cell given by (row,col)
  325. BOOL CColourPopup::GetCellRect(int row, int col, const LPRECT& rect)
  326. {
  327.     if (row < 0 || row >= m_nNumRows || col < 0 || col >= m_nNumColumns)
  328.         return FALSE;
  329.     rect->left = col*m_nBoxSize + m_nMargin;
  330.     rect->top  = row*m_nBoxSize + m_nMargin;
  331.     // Move everything down if we are displaying text
  332.     if (m_bShowCustom) 
  333.         rect->top += (m_nMargin + m_TextRect.Height());
  334.     rect->right = rect->left + m_nBoxSize;
  335.     rect->bottom = rect->top + m_nBoxSize;
  336.     return TRUE;
  337. }
  338. // Works out an appropriate size and position of this window
  339. void CColourPopup::SetWindowSize()
  340. {
  341.     CSize TextSize;
  342.     // If we are showing a custom text area, get the font and text size.
  343.     if (m_bShowCustom)
  344.     {
  345.         // Get the size of the custom text
  346.         CClientDC dc(this);
  347.         CFont* pOldFont = (CFont*) dc.SelectObject(&m_Font);
  348.         TextSize = dc.GetTextExtent(m_strCustomText) + CSize(2*m_nMargin,2*m_nMargin);
  349.         dc.SelectObject(pOldFont);
  350.         // Add even more space to draw the horizontal line
  351.         TextSize.cy += 2*m_nMargin + 2;
  352.     }
  353.     // Get the number of columns and rows
  354.     //m_nNumColumns = (int) sqrt((double)m_nNumColours);    // for a square window (yuk)
  355.     m_nNumColumns = 8;
  356.     m_nNumRows = m_nNumColours / m_nNumColumns;
  357.     if (m_nNumColours % m_nNumColumns) m_nNumRows++;
  358.     // Get the current window position, and set the new size
  359.     CRect rect;
  360.     GetWindowRect(rect);
  361.     m_WindowRect.SetRect(rect.left, rect.top, 
  362.                          rect.left + m_nNumColumns*m_nBoxSize + 2*m_nMargin,
  363.                          rect.top  + m_nNumRows*m_nBoxSize + 2*m_nMargin);
  364.     // if custom text, then expand window if necessary, and set text width as
  365.     // window width
  366.     if (m_bShowCustom) 
  367.     {
  368.         m_WindowRect.bottom += (m_nMargin + TextSize.cy);
  369.         if (TextSize.cx > m_WindowRect.Width())
  370.             m_WindowRect.right = m_WindowRect.left + TextSize.cx;
  371.         TextSize.cx = m_WindowRect.Width()-2*m_nMargin;
  372.         // Work out the text area
  373.         m_TextRect.SetRect(m_nMargin, m_nMargin, 
  374.                            m_nMargin+TextSize.cx, m_nMargin+TextSize.cy);
  375.     }
  376.     // Need to check it'll fit on screen: Too far right?
  377.     CSize ScreenSize(::GetSystemMetrics(SM_CXSCREEN), ::GetSystemMetrics(SM_CYSCREEN));
  378.     if (m_WindowRect.right > ScreenSize.cx)
  379.         m_WindowRect.OffsetRect(-(m_WindowRect.right - ScreenSize.cx), 0);
  380.     // Too far left?
  381.     if (m_WindowRect.left < 0)
  382.         m_WindowRect.OffsetRect( -m_WindowRect.left, 0);
  383.     // Bottom falling out of screen?
  384.     if (m_WindowRect.bottom > ScreenSize.cy)
  385.     {
  386.         CRect ParentRect;
  387.         m_pParent->GetWindowRect(ParentRect);
  388.         m_WindowRect.OffsetRect(0, -(ParentRect.Height() + m_WindowRect.Height()));
  389.     }
  390.     // Set the window size and position
  391.     MoveWindow(m_WindowRect, TRUE);
  392. }
  393. void CColourPopup::CreateToolTips()
  394. {
  395.     // Create the tool tip
  396.     if (!m_ToolTip.Create(this)) return;
  397.     // Add a tool for each cell
  398.     for (int row = 0; row < m_nNumRows; row++)
  399.         for (int col = 0; col < m_nNumColumns; col++)
  400.         {
  401.             CRect rect;
  402.             if (!GetCellRect(row, col, rect)) continue;
  403.             m_ToolTip.AddTool(this, GetColourName(row, col), rect, 1);
  404.         }
  405. }
  406. void CColourPopup::ChangeSelection(int row, int col)
  407. {
  408.     CClientDC dc(this);        // device context for drawing
  409.     if ((m_nCurrentRow >= 0 && m_nCurrentRow < m_nNumRows &&
  410.          m_nCurrentCol >= 0 && m_nCurrentCol < m_nNumColumns) ||
  411.         (m_nCurrentCol == TEXT_BOX_VALUE && m_nCurrentCol == TEXT_BOX_VALUE))
  412.     {
  413.         // Set Current selection as invalid and redraw old selection (this way
  414.         // the old selection will be drawn unselected)
  415.         int OldRow = m_nCurrentRow, OldCol = m_nCurrentCol;
  416.         m_nCurrentRow = m_nCurrentCol = -1;
  417.         DrawCell(&dc, OldRow, OldCol);
  418.     }
  419.     // Set the current selection as row/col and draw (it will be drawn selected)
  420.     m_nCurrentRow = row; m_nCurrentCol = col;
  421.     DrawCell(&dc, m_nCurrentRow, m_nCurrentCol);
  422.     // Store the current colour
  423.     if (m_nCurrentRow == TEXT_BOX_VALUE && m_nCurrentCol == TEXT_BOX_VALUE)
  424.         m_pParent->SendMessage(CPN_SELCHANGE, (WPARAM) m_crInitialColour, 0);
  425.     else
  426.     {
  427.         m_crColour = GetColour(m_nCurrentRow, m_nCurrentCol);
  428.         m_pParent->SendMessage(CPN_SELCHANGE, (WPARAM) m_crColour, 0);
  429.     }
  430. }
  431. void CColourPopup::EndSelection(int nMessage)
  432. {
  433.     ReleaseCapture();
  434.     // If custom text selected, perform a custom colour selection
  435.     if (nMessage != CPN_SELENDCANCEL && 
  436.         m_nCurrentCol == TEXT_BOX_VALUE && m_nCurrentRow == TEXT_BOX_VALUE)
  437.     {
  438.         CColorDialog dlg(m_crInitialColour, CC_FULLOPEN | CC_ANYCOLOR, this);
  439.         if (dlg.DoModal() == IDOK)
  440.             m_crColour = dlg.GetColor();
  441.         else
  442.             m_crColour = m_crInitialColour;
  443.    } 
  444.     if (nMessage == CPN_SELENDCANCEL)
  445.         m_crColour = m_crInitialColour;
  446.     m_pParent->SendMessage(nMessage, (WPARAM) m_crColour, 0);
  447.     
  448.     DestroyWindow();
  449. }
  450. void CColourPopup::DrawCell(CDC* pDC, int row, int col)
  451. {
  452.     // This is a special hack for the text box
  453.     if (m_bShowCustom && row == TEXT_BOX_VALUE && row == TEXT_BOX_VALUE)
  454.     {
  455.         // The extent of the actual text button
  456.          CRect TextButtonRect = m_TextRect;
  457.         TextButtonRect.bottom -= (2*m_nMargin+2);
  458.         // Fill background
  459.         //if ( (m_nChosenColourRow == row && m_nChosenColourCol == col)
  460.         //    && !(m_nCurrentRow == row && m_nCurrentCol == col) )
  461.         //    pDC->FillSolidRect(m_TextRect, ::GetSysColor(COLOR_3DHILIGHT));
  462.         //else
  463.             pDC->FillSolidRect(m_TextRect, ::GetSysColor(COLOR_3DFACE));
  464.         // Draw button
  465.         //if (m_nChosenColourRow == row && m_nChosenColourCol == col)
  466.         //    pDC->DrawEdge(TextButtonRect, EDGE_SUNKEN, BF_RECT);
  467.         //else 
  468.         if (m_nCurrentRow == row && m_nCurrentCol == col) 
  469.             pDC->DrawEdge(TextButtonRect, EDGE_RAISED, BF_RECT);
  470.         // Draw custom text
  471.         CFont *pOldFont = (CFont*) pDC->SelectObject(&m_Font);
  472.         pDC->DrawText(m_strCustomText, TextButtonRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  473.         pDC->SelectObject(pOldFont);
  474.         // Draw horizontal line
  475.         pDC->FillSolidRect(m_TextRect.left+2*m_nMargin, m_TextRect.bottom-m_nMargin-2,
  476.                            m_TextRect.Width()-4*m_nMargin, 1, ::GetSysColor(COLOR_3DSHADOW));
  477.         pDC->FillSolidRect(m_TextRect.left+2*m_nMargin, m_TextRect.bottom-m_nMargin-1,
  478.                            m_TextRect.Width()-4*m_nMargin, 1, ::GetSysColor(COLOR_3DHILIGHT));
  479.         return;
  480.     }        
  481.     // row/col in range?
  482.     ASSERT(row >= 0 && row < m_nNumRows);
  483.     ASSERT(col >= 0 && col < m_nNumColumns);
  484.     // Select and realize the palette
  485.     CPalette* pOldPalette;
  486.     if (pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE)
  487.     {
  488.         pOldPalette = pDC->SelectPalette(&m_Palette, FALSE);
  489.         pDC->RealizePalette();
  490.     }
  491.     CRect rect;
  492.     if (!GetCellRect(row, col, rect)) return;
  493.     // fill background
  494.     if ( (m_nChosenColourRow == row && m_nChosenColourCol == col)
  495.         && !(m_nCurrentRow == row && m_nCurrentCol == col) )
  496.         pDC->FillSolidRect(rect, ::GetSysColor(COLOR_3DHILIGHT));
  497.     else
  498.         pDC->FillSolidRect(rect, ::GetSysColor(COLOR_3DFACE));
  499.     // Draw button
  500.     if (m_nChosenColourRow == row && m_nChosenColourCol == col)
  501.         pDC->DrawEdge(rect, EDGE_SUNKEN, BF_RECT);
  502.     else if (m_nCurrentRow == row && m_nCurrentCol == col) 
  503.         pDC->DrawEdge(rect, EDGE_RAISED, BF_RECT);
  504.     // Draw raised edge if selected
  505.     if (m_nCurrentRow == row && m_nCurrentCol == col)
  506.         pDC->DrawEdge(rect, EDGE_RAISED, BF_RECT);
  507.     CBrush brush(PALETTERGB(GetRValue(GetColour(row, col)), 
  508.                             GetGValue(GetColour(row, col)), 
  509.                             GetBValue(GetColour(row, col)) ));
  510.     CPen   pen;
  511.     pen.CreatePen(PS_SOLID, 1, ::GetSysColor(COLOR_3DSHADOW));
  512.     CBrush* pOldBrush = (CBrush*) pDC->SelectObject(&brush);
  513.     CPen*   pOldPen   = (CPen*)   pDC->SelectObject(&pen);
  514.     // Draw the cell colour
  515.     rect.DeflateRect(m_nMargin+1, m_nMargin+1);
  516.     pDC->Rectangle(rect);
  517.     // restore DC and cleanup
  518.     pDC->SelectObject(pOldBrush);
  519.     pDC->SelectObject(pOldPen);
  520.     brush.DeleteObject();
  521.     pen.DeleteObject();
  522.     if (pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE)
  523.         pDC->SelectPalette(pOldPalette, FALSE);
  524. }
  525. BOOL CColourPopup::OnQueryNewPalette() 
  526. {
  527.     Invalidate();    
  528.     return CWnd::OnQueryNewPalette();
  529. }
  530. void CColourPopup::OnPaletteChanged(CWnd* pFocusWnd) 
  531. {
  532.     CWnd::OnPaletteChanged(pFocusWnd);
  533.     if (pFocusWnd->GetSafeHwnd() != GetSafeHwnd())
  534.         Invalidate();
  535. }