www.pudn.com > fractal.rar > ColorPopup.cpp


//贵州省安顺市第二高级中学 高二一班 蒋伟	 
//2002.7.1 
//请勿修改版权信息 谢谢 
//Neil 
// 
 
#include "stdafx.h" 
#include  
 
#include "ColorPopup.h" 
 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
#define DEFAULT_BOX_VALUE -3 
#define CUSTOM_BOX_VALUE  -2 
#define INVALID_COLOUR    -1 
 
#define MAX_COLOURS      100 
 
#define MAX_OFFSET  5          // X direction offset 
#define MAX_BOTTOM  15         // Y direction offset and to the bottom  
#define MAX_TEXTRECT -5        // Width of the default text rect and the onwer text rect     
 
ColorTableEntry CColorPopup::m_crColors[] =  
{ 
    { RGB(0x01, 0x00, 0x00),    _T("黑色")              }, 
    { RGB(0xA5, 0x2A, 0x00),    _T("褐色")              }, 
    { RGB(0x00, 0x40, 0x40),    _T("橄榄绿")            }, 
    { RGB(0x00, 0x55, 0x00),    _T("深绿")              }, 
    { RGB(0x00, 0x00, 0x5E),    _T("深灰蓝")            }, 
    { RGB(0x00, 0x00, 0x8B),    _T("深蓝")              }, 
    { RGB(0x4B, 0x00, 0x82),    _T("靛蓝")              }, 
    { RGB(0x33, 0x33, 0x33),    _T("深灰-80%")          }, 
 
    { RGB(0x8B, 0x00, 0x00),    _T("深红")	            }, 
    { RGB(0xFF, 0x68, 0x20),    _T("桔黄")              }, 
    { RGB(0x8B, 0x8B, 0x00),    _T("深黄")              }, 
    { RGB(0x00, 0x93, 0x00),    _T("绿色")              }, 
    { RGB(0x38, 0x8E, 0x8E),    _T("青色")              }, 
    { RGB(0x00, 0x00, 0xFF),    _T("蓝色")              }, 
    { RGB(0x7B, 0x7B, 0xC0),    _T("蓝灰")              }, 
    { RGB(0x7F, 0x7F, 0x7F),    _T("灰色-50%")          }, 
 
    { RGB(0xFF, 0x00, 0x00),    _T("红色")              }, 
    { RGB(0xFF, 0xAD, 0x5B),    _T("浅桔色")            }, 
    { RGB(0x32, 0xCD, 0x32),    _T("酸桔色")            },  
    { RGB(0x3C, 0xB3, 0x71),    _T("海绿")              }, 
    { RGB(0x7F, 0xFF, 0xD4),    _T("宝石蓝")            }, 
    { RGB(0x7D, 0x9E, 0xC0),    _T("浅蓝")              }, 
    { RGB(0x80, 0x00, 0x80),    _T("紫色")              }, 
    { RGB(0x99, 0x99, 0x99),    _T("灰色-40%")          }, 
 
    { RGB(0xFF, 0xC0, 0xCB),    _T("粉红")              }, 
    { RGB(0xFF, 0xD7, 0x00),    _T("金色")              }, 
    { RGB(0xFF, 0xFF, 0x00),    _T("黄色")              },     
    { RGB(0x00, 0xFF, 0x00),    _T("鲜绿")              }, 
    { RGB(0x40, 0xE0, 0xD0),    _T("青绿")              }, 
    { RGB(0xC0, 0xFF, 0xFF),    _T("天蓝")              }, 
    { RGB(0x48, 0x00, 0x48),    _T("梅红")              }, 
    { RGB(0xBF, 0xBF, 0xBF),    _T("灰色-25%")          }, 
 
    { RGB(0xFF, 0xE4, 0xE1),    _T("玫瑰红")            }, 
    { RGB(0xD2, 0xB4, 0x8C),    _T("棕色")              }, 
    { RGB(0xFF, 0xFF, 0xE0),    _T("浅黄")              }, 
    { RGB(0x98, 0xFB, 0x98),    _T("浅绿 ")             }, 
    { RGB(0xAF, 0xEE, 0xEE),    _T("浅青绿")            }, 
    { RGB(0x68, 0x83, 0x8B),    _T("淡蓝")              }, 
    { RGB(0xE6, 0xE6, 0xFA),    _T("紫色")              }, 
    { RGB(0xFF, 0xFF, 0xFF),    _T("白色")              } 
}; 
 
///////////////////////////////////////////////////////////////////////////// 
// CColorPopup 
 
CColorPopup::CColorPopup() 
{ 
    Initialise(); 
} 
 
CColorPopup::CColorPopup(CPoint p, COLORREF crColor, CWnd* pParentWnd, 
                           LPCTSTR szDefaultText /* = NULL */, 
                           LPCTSTR szCustomText  /* = NULL */) 
{ 
    Initialise(); 
 
    m_crColor        = m_crInitialColor = crColor; 
    m_pParent        = pParentWnd; 
    m_strDefaultText = (szDefaultText)? szDefaultText : _T(""); 
    m_strCustomText  = (szCustomText)?  szCustomText  : _T(""); 
	m_crDefaultColor = ::GetSysColor(COLOR_BTNTEXT); 
 
	CColorPopup::Create(p, crColor, pParentWnd, szDefaultText, szCustomText); 
} 
 
//////////////////////////////////////////////////////////////////// 
void CColorPopup::Initialise() 
{ 
    m_nNumColors       = sizeof(m_crColors)/sizeof(ColorTableEntry); 
    ASSERT(m_nNumColors <= MAX_COLOURS); 
    if (m_nNumColors > MAX_COLOURS) 
        m_nNumColors = MAX_COLOURS; 
 
    m_nNumColumns       = 0; 
    m_nNumRows          = 0; 
    m_nBoxSize          = 18; 
    m_nMargin           = ::GetSystemMetrics(SM_CXEDGE); 
    m_nCurrentSel       = INVALID_COLOUR; 
    m_nChosenColorSel   = INVALID_COLOUR; 
    m_pParent           = NULL; 
    m_crColor           = m_crInitialColor = RGB(0,0,0); 
 
    // Make sure the colour square is at least 5 x 5; 
    if (m_nBoxSize - 2*m_nMargin - 2 < 5) m_nBoxSize = 5 + 2*m_nMargin + 2; 
 
    // Create the font 
    NONCLIENTMETRICS ncm; 
    ncm.cbSize = sizeof(NONCLIENTMETRICS); 
    VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS,  
								sizeof(NONCLIENTMETRICS), &ncm, 0)); 
    m_Font.CreateFontIndirect(&(ncm.lfMessageFont)); 
 
    // Create the palette 
    struct { 
        LOGPALETTE    LogPalette; 
        PALETTEENTRY  PalEntry[MAX_COLOURS]; 
    } pal; 
 
    LOGPALETTE* pLogPalette = (LOGPALETTE*) &pal; 
    pLogPalette->palVersion    = 0x300; 
    pLogPalette->palNumEntries = (WORD) m_nNumColors;  
 
    for (int i = 0; i < m_nNumColors; i++) 
    { 
        pLogPalette->palPalEntry[i].peRed   = GetRValue(m_crColors[i].crColor); 
        pLogPalette->palPalEntry[i].peGreen = GetGValue(m_crColors[i].crColor); 
        pLogPalette->palPalEntry[i].peBlue  = GetBValue(m_crColors[i].crColor); 
        pLogPalette->palPalEntry[i].peFlags = 0; 
    } 
 
    m_Palette.CreatePalette(pLogPalette); 
} 
 
//////////////////////////////////////////////////////////////////// 
CColorPopup::~CColorPopup() 
{ 
    m_Font.DeleteObject(); 
    m_Palette.DeleteObject(); 
} 
 
////////////////////////////////////////////////////////////////////// 
BOOL CColorPopup::Create(CPoint p, COLORREF crColor, CWnd* pParentWnd, 
                          LPCTSTR szDefaultText, 
                          LPCTSTR szCustomText ) 
{ 
    ASSERT(pParentWnd && ::IsWindow(pParentWnd->GetSafeHwnd())); 
    //ASSERT(pParentWnd->IsKindOf(RUNTIME_CLASS(CColorButton))); 
 
    m_pParent  = pParentWnd; 
    m_crColor = m_crInitialColor = crColor; 
 
    // Get the class name and create the window 
    CString szClassName = AfxRegisterWndClass(CS_CLASSDC|CS_SAVEBITS|CS_HREDRAW| 
											  CS_VREDRAW, 0, 
											  (HBRUSH)GetStockObject(LTGRAY_BRUSH),0); 
		 
    if (!CWnd::CreateEx(0, szClassName, _T(""), WS_VISIBLE|WS_POPUP,  
			p.x, p.y, 100, 100, // size updated soon 
			pParentWnd->GetSafeHwnd(), 0, NULL)) 
			return FALSE; 
 
    // Store the Custom text 
    if (szCustomText != NULL)  
        m_strCustomText = szCustomText; 
 
    // Store the Default Area text 
    if (szDefaultText != NULL)  
        m_strDefaultText = szDefaultText; 
         
    // Set the window size 
    SetWindowSize(); 
 
    // Create the tooltips 
    CreateToolTips(); 
 
    // Find which cell corresponds to the initial color 
    FindCellFromColor(crColor); 
 
    // Capture all mouse events for the life of this window 
    SetCapture(); 
 
    return TRUE; 
} 
 
BEGIN_MESSAGE_MAP(CColorPopup, CWnd) 
    //{{AFX_MSG_MAP(CColorPopup) 
    ON_WM_NCDESTROY() 
    ON_WM_LBUTTONUP() 
    ON_WM_PAINT() 
    ON_WM_MOUSEMOVE() 
    ON_WM_KEYDOWN() 
    ON_WM_QUERYNEWPALETTE() 
    ON_WM_PALETTECHANGED() 
	ON_WM_KILLFOCUS() 
	ON_WM_ACTIVATEAPP() 
	ON_WM_ERASEBKGND() 
	ON_WM_LBUTTONDOWN() 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CColorPopup message handlers 
// For tooltips 
BOOL CColorPopup::PreTranslateMessage(MSG* pMsg)  
{ 
    m_ToolTip.RelayEvent(pMsg); 
    return CWnd::PreTranslateMessage(pMsg); 
} 
 
/////////////////////////////////////////////////////////////////// 
// If an arrow key is pressed, then move the selection 
void CColorPopup::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)  
{ 
    int row = GetRow(m_nCurrentSel); 
    int col = GetColumn(m_nCurrentSel); 
    int nSelection = m_nCurrentSel; 
 
    if (nChar == VK_DOWN)  
    { 
        if (row == DEFAULT_BOX_VALUE)  
            row = col = 0;  
        else if (row == CUSTOM_BOX_VALUE) 
        { 
            if (m_strDefaultText.GetLength()) 
                row = col = DEFAULT_BOX_VALUE; 
            else 
                row = col = 0; 
        } 
        else 
        { 
            row++; 
            if (GetIndex(row,col) < 0) 
            { 
                if (m_strCustomText.GetLength()) 
                    row = col = CUSTOM_BOX_VALUE; 
                else if (m_strDefaultText.GetLength()) 
                    row = col = DEFAULT_BOX_VALUE; 
                else 
                    row = col = 0; 
            } 
        } 
        ChangeSelection(GetIndex(row, col)); 
    } 
 
    if (nChar == VK_UP)  
    { 
        if (row == DEFAULT_BOX_VALUE) 
        { 
            if (m_strCustomText.GetLength()) 
                row = col = CUSTOM_BOX_VALUE; 
            else 
           {  
                row = GetRow(m_nNumColors-1);  
                col = GetColumn(m_nNumColors-1);  
            } 
        } 
        else if (row == CUSTOM_BOX_VALUE) 
        {  
            row = GetRow(m_nNumColors-1);  
            col = GetColumn(m_nNumColors-1);  
        } 
        else if (row > 0) row--; 
        else  
        { 
            if (m_strDefaultText.GetLength()) 
                row = col = DEFAULT_BOX_VALUE; 
            else if (m_strCustomText.GetLength()) 
                row = col = CUSTOM_BOX_VALUE; 
            else 
            {  
                row = GetRow(m_nNumColors-1);  
                col = GetColumn(m_nNumColors-1);  
            } 
        } 
        ChangeSelection(GetIndex(row, col)); 
    } 
 
    if (nChar == VK_RIGHT)  
    { 
        if (row == DEFAULT_BOX_VALUE)  
            row = col = 0;  
        else if (row == CUSTOM_BOX_VALUE) 
        { 
            if (m_strDefaultText.GetLength()) 
                row = col = DEFAULT_BOX_VALUE; 
            else 
                row = col = 0; 
        } 
        else if (col < m_nNumColumns-1)  
            col++; 
        else  
        {  
            col = 0; row++; 
        } 
 
        if (GetIndex(row,col) == INVALID_COLOUR) 
        { 
            if (m_strCustomText.GetLength()) 
                row = col = CUSTOM_BOX_VALUE; 
            else if (m_strDefaultText.GetLength()) 
                row = col = DEFAULT_BOX_VALUE; 
            else 
                row = col = 0; 
        } 
 
        ChangeSelection(GetIndex(row, col)); 
    } 
 
    if (nChar == VK_LEFT)  
    { 
        if (row == DEFAULT_BOX_VALUE) 
        { 
            if (m_strCustomText.GetLength()) 
                row = col = CUSTOM_BOX_VALUE; 
            else 
           {  
                row = GetRow(m_nNumColors-1);  
                col = GetColumn(m_nNumColors-1);  
            } 
        } 
        else if (row == CUSTOM_BOX_VALUE) 
        {  
            row = GetRow(m_nNumColors-1);  
            col = GetColumn(m_nNumColors-1);  
        } 
        else if (col > 0) col--; 
        else /* col == 0 */ 
        { 
            if (row > 0) { row--; col = m_nNumColumns-1; } 
            else  
            { 
                if (m_strDefaultText.GetLength()) 
                    row = col = DEFAULT_BOX_VALUE; 
                else if (m_strCustomText.GetLength()) 
                    row = col = CUSTOM_BOX_VALUE; 
                else 
                {  
                    row = GetRow(m_nNumColors-1);  
                    col = GetColumn(m_nNumColors-1);  
                } 
            } 
        } 
        ChangeSelection(GetIndex(row, col)); 
    } 
 
    if (nChar == VK_ESCAPE)  
    { 
        m_crColor = m_crInitialColor; 
        EndSelection(CPN_SELENDCANCEL); 
        return; 
    } 
 
    if (nChar == VK_RETURN || nChar == VK_SPACE) 
    { 
        EndSelection(CPN_SELENDOK); 
        return; 
    } 
 
    CWnd::OnKeyDown(nChar, nRepCnt, nFlags); 
} 
 
/////////////////////////////////////////////////////////////////// 
// auto-deletion 
void CColorPopup::OnNcDestroy()  
{ 
    CWnd::OnNcDestroy(); 
    delete this; 
} 
///////////////////////////////////////////////////////////////////// 
//Paint the Dialog's background 
BOOL CColorPopup::OnEraseBkgnd(CDC* pDC)  
{ 
	CBrush br(GetSysColor(COLOR_3DFACE)); 
	CRect rc; 
	pDC->GetClipBox(rc); 
	CBrush* pOldBrush = pDC->SelectObject(&br); 
	 
	pDC->PatBlt(rc.left,rc.top,rc.Width(),rc.Height(),PATCOPY); 
 
	pDC->SelectObject(pOldBrush); 
 
	return TRUE; 
} 
 
///////////////////////////////////////////////////////////////////// 
void CColorPopup::OnPaint()  
{ 
    // device context for painting 
	CPaintDC dc(this);  
	 
	// Draw the title with my name 
	CRect rectName(4, 1, 154, 17); 
	dc.SetBkMode(TRANSPARENT); 
	DrawName(&dc,rectName); 
		 
	// Draw the Default Area text 
    DrawCell(&dc, DEFAULT_BOX_VALUE); 
	 
    // Draw colour cells 
    for (int i = 0; i < m_nNumColors; i++) 
        DrawCell(&dc, i); 
     
    // Draw custom text 
    DrawCell(&dc, CUSTOM_BOX_VALUE); 
 
    // Draw raised window edge  
    CRect rect; 
    GetClientRect(rect); 
    dc.DrawEdge(rect, EDGE_RAISED, BF_RECT); 
} 
 
///////////////////////////////////////////////////////////////////// 
void CColorPopup::OnMouseMove(UINT nFlags, CPoint point)  
{ 
    int nNewSelection = INVALID_COLOUR; 
 
    // Translate points to be relative raised window edge 
    point.x -= m_nMargin; 
    point.y -= m_nMargin; 
 
    // First check whether in text box 
    if (m_CustomTextRect.PtInRect(point)) 
        nNewSelection = CUSTOM_BOX_VALUE; 
    else if (m_DefaultTextRect.PtInRect(point)) 
        nNewSelection = DEFAULT_BOX_VALUE; 
    else 
    { 
        // Take into account text box 
        if (m_strDefaultText.GetLength())  
            point.y -= m_DefaultTextRect.Height();   
 
        // Get the row and column 
        nNewSelection = GetIndex((point.y - MAX_BOTTOM) / m_nBoxSize, 
			                      (point.x - MAX_OFFSET) / m_nBoxSize); 
 
        // In range? If not, default and exit 
        if (nNewSelection < 0 || nNewSelection >= m_nNumColors) 
        { 
            CWnd::OnMouseMove(nFlags, point); 
            return; 
        } 
    } 
	 
 
    // the row and column of the current selection have been found there,   
    // and if the row/col selection has changed? then redraw old and new cells. 
    if (nNewSelection != m_nCurrentSel) 
        ChangeSelection(nNewSelection); 
 
    CWnd::OnMouseMove(nFlags, point); 
} 
 
/////////////////////////////////////////////////////////////////// 
// End selection on LButtonUp 
void CColorPopup::OnLButtonUp(UINT nFlags, CPoint point)  
{     
    CWnd::OnLButtonUp(nFlags, point); 
 
    DWORD pos = GetMessagePos(); 
    point = CPoint(LOWORD(pos), HIWORD(pos)); 
 
    if (m_WindowRect.PtInRect(point)) 
        EndSelection(CPN_SELENDOK); 
    else 
        EndSelection(CPN_SELENDCANCEL); 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// Get the index of clolor cell  
int CColorPopup::GetIndex(int row, int col) const 
{  
    if ((row == CUSTOM_BOX_VALUE || col == CUSTOM_BOX_VALUE) && m_strCustomText.GetLength()) 
        return CUSTOM_BOX_VALUE; 
    else if ((row == DEFAULT_BOX_VALUE || col == DEFAULT_BOX_VALUE) && m_strDefaultText.GetLength()) 
        return DEFAULT_BOX_VALUE; 
    else if (row < 0 || col < 0 || row >= m_nNumRows || col >= m_nNumColumns) 
        return INVALID_COLOUR; 
    else 
    { 
        if (row*m_nNumColumns + col >= m_nNumColors) 
            return INVALID_COLOUR; 
        else 
            return row*m_nNumColumns + col; 
    } 
} 
 
//////////////////////////////////////////////////////////////////////////// 
// Get the Row number 
int CColorPopup::GetRow(int nIndex) const                
{  
    if (nIndex == CUSTOM_BOX_VALUE && m_strCustomText.GetLength()) 
        return CUSTOM_BOX_VALUE; 
    else if (nIndex == DEFAULT_BOX_VALUE && m_strDefaultText.GetLength()) 
        return DEFAULT_BOX_VALUE; 
    else if (nIndex < 0 || nIndex >= m_nNumColors) 
        return INVALID_COLOUR; 
    else 
        return nIndex / m_nNumColumns;  
} 
 
///////////////////////////////////////////////////////////////// 
// Get the Column number 
int CColorPopup::GetColumn(int nIndex) const             
{  
    if (nIndex == CUSTOM_BOX_VALUE && m_strCustomText.GetLength()) 
        return CUSTOM_BOX_VALUE; 
    else if (nIndex == DEFAULT_BOX_VALUE && m_strDefaultText.GetLength()) 
        return DEFAULT_BOX_VALUE; 
    else if (nIndex < 0 || nIndex >= m_nNumColors) 
        return INVALID_COLOUR; 
    else 
        return nIndex % m_nNumColumns;  
} 
 
/////////////////////////////////////////////////////////////////// 
// 
void CColorPopup::FindCellFromColor(COLORREF crColor) 
{ 
    if (crColor == m_crDefaultColor && m_strDefaultText.GetLength()) 
    { 
        m_nChosenColorSel = DEFAULT_BOX_VALUE; 
        return; 
    } 
 
    for (int i = 0; i < m_nNumColors; i++) 
    { 
        if (GetColor(i) == crColor) 
        { 
            m_nChosenColorSel = i; 
            return; 
        } 
    } 
 
    if (m_strCustomText.GetLength()) 
        m_nChosenColorSel = CUSTOM_BOX_VALUE; 
    else 
        m_nChosenColorSel = INVALID_COLOUR; 
} 
 
/////////////////////////////////////////////////////////////////// 
// Gets the dimensions of the colour cell given by (row,col) 
BOOL CColorPopup::GetCellRect(int nIndex, const LPRECT& rect) 
{ 
    if (nIndex == CUSTOM_BOX_VALUE) 
    { 
        ::SetRect(rect,  
                  m_CustomTextRect.left,  m_CustomTextRect.top, 
                  m_CustomTextRect.right, m_CustomTextRect.bottom); 
        return TRUE; 
    } 
    else if (nIndex == DEFAULT_BOX_VALUE) 
    { 
        ::SetRect(rect,  
                  m_DefaultTextRect.left,  m_DefaultTextRect.top, 
                  m_DefaultTextRect.right, m_DefaultTextRect.bottom); 
        return TRUE; 
    } 
 
    if (nIndex < 0 || nIndex >= m_nNumColors) 
        return FALSE; 
 
    rect->left = MAX_OFFSET + GetColumn(nIndex) * m_nBoxSize + m_nMargin; 
    rect->top  = MAX_BOTTOM + GetRow(nIndex) * m_nBoxSize + m_nMargin; 
 
    // Move everything down if we are displaying a default text area 
    if (m_strDefaultText.GetLength())  
        rect->top += (m_nMargin + m_DefaultTextRect.Height()); 
 
    rect->right = rect->left + m_nBoxSize; 
    rect->bottom = rect->top + m_nBoxSize; 
 
    return TRUE; 
} 
 
//////////////////////////////////////////////////////////////// 
// Works out an appropriate size and position of this window 
void CColorPopup::SetWindowSize() 
{ 
    CSize TextSize; 
 
    // If we are showing a custom or default text area, get the font and text size. 
    if (m_strCustomText.GetLength() || m_strDefaultText.GetLength()) 
    { 
        CClientDC dc(this); 
        CFont* pOldFont = (CFont*) dc.SelectObject(&m_Font); 
 
        // Get the size of the custom text 
        TextSize = CSize(0,0); 
        if (m_strCustomText.GetLength()) 
            TextSize = dc.GetTextExtent(m_strCustomText); 
 
        // Get the size of the default text  
        if (m_strDefaultText.GetLength()) 
        { 
            CSize DefaultSize = dc.GetTextExtent(m_strDefaultText); 
            if (DefaultSize.cx > TextSize.cx) TextSize.cx = DefaultSize.cx; 
            if (DefaultSize.cy > TextSize.cy) TextSize.cy = DefaultSize.cy; 
        } 
 
        dc.SelectObject(pOldFont); 
        TextSize += CSize(2*m_nMargin,2*m_nMargin); 
 
        // Add even more space to draw the horizontal line 
        TextSize.cy += 2*m_nMargin + 2; 
    } 
 
    // Get the number of columns and rows 
    m_nNumColumns = 8; 
    m_nNumRows = m_nNumColors / m_nNumColumns; 
    if (m_nNumColors % m_nNumColumns) m_nNumRows++; 
	 
    // Get the current window position, and set the new size 
    CRect rect; 
    GetWindowRect(rect); 
 
    m_WindowRect.SetRect(rect.left, rect.top,  
                         rect.left + m_nNumColumns*m_nBoxSize + 2*m_nMargin+ 2* MAX_OFFSET, 
                         rect.top  + m_nNumRows*m_nBoxSize + 2*m_nMargin + MAX_BOTTOM ); 
 
    // if custom text, then expand window if necessary, and set text width as 
    // window width 
    if (m_strDefaultText.GetLength())  
    { 
        if (TextSize.cx > m_WindowRect.Width()) 
            m_WindowRect.right = m_WindowRect.left + TextSize.cx; 
        TextSize.cx = m_WindowRect.Width()-2*m_nMargin-20; 
 
        // Work out the text area 
        m_DefaultTextRect.SetRect(m_nMargin, m_nMargin,  
                                  m_nMargin+TextSize.cx+2 , 2*m_nMargin+TextSize.cy); 
        m_DefaultTextRect.OffsetRect ( 2 * MAX_OFFSET,MAX_BOTTOM); 
		m_WindowRect.bottom += m_DefaultTextRect.Height() + 2*m_nMargin; 
		 
    } 
	 
    // if custom text, then expand window if necessary, and set text width as 
    // window width 
    if (m_strCustomText.GetLength()){ 
        if (TextSize.cx > m_WindowRect.Width()) 
            m_WindowRect.right = m_WindowRect.left + TextSize.cx; 
        TextSize.cx = m_WindowRect.Width()-2*m_nMargin-20; 
 
        // Work out the text area 
        m_CustomTextRect.SetRect(m_nMargin, m_WindowRect.Height(),  
                                 m_nMargin+TextSize.cx ,  
                                 m_WindowRect.Height()+m_nMargin+TextSize.cy); 
        m_CustomTextRect.OffsetRect ( 2 * MAX_OFFSET , 0 ); 
		m_WindowRect.bottom += m_CustomTextRect.Height() + 2*m_nMargin + MAX_OFFSET; 
   } 
 
    // Need to check it'll fit on screen 
    CSize ScreenSize(::GetSystemMetrics(SM_CXSCREEN), ::GetSystemMetrics(SM_CYSCREEN)); 
    if (m_WindowRect.right > ScreenSize.cx) 
        m_WindowRect.OffsetRect(-(m_WindowRect.right - ScreenSize.cx), 0); 
 
    // Too far left? 
    if (m_WindowRect.left < 0) 
        m_WindowRect.OffsetRect( -m_WindowRect.left, 0); 
 
    // Bottom falling out of screen? 
    if (m_WindowRect.bottom > ScreenSize.cy) 
    { 
        CRect ParentRect; 
        m_pParent->GetWindowRect(ParentRect); 
        m_WindowRect.OffsetRect(0, -(ParentRect.Height() + m_WindowRect.Height())); 
    } 
 
    // Set the window size and position 
    MoveWindow(m_WindowRect, TRUE); 
} 
 
//////////////////////////////////////////////////////////////// 
void CColorPopup::CreateToolTips() 
{ 
    // Create the tool tip 
    if (!m_ToolTip.Create(this)) return; 
 
    // Add a tool for each cell 
    for (int i = 0; i < m_nNumColors; i++) 
    { 
        CRect rect; 
        if (!GetCellRect(i, rect)) continue; 
            m_ToolTip.AddTool(this, GetColorName(i), rect, 1); 
    } 
} 
 
////////////////////////////////////////////////////////////////// 
void CColorPopup::ChangeSelection(int nIndex) 
{ 
    CClientDC dc(this);        // device context for drawing 
 
    if (nIndex > m_nNumColors) 
        nIndex = CUSTOM_BOX_VALUE;  
 
    if ((m_nCurrentSel >= 0 && m_nCurrentSel < m_nNumColors) || 
        m_nCurrentSel == CUSTOM_BOX_VALUE || m_nCurrentSel == DEFAULT_BOX_VALUE) 
    { 
        // Set Current selection as invalid and redraw old selection (this way 
        // the old selection will be drawn unselected) 
        int OldSel = m_nCurrentSel; 
        m_nCurrentSel = INVALID_COLOUR; 
        DrawCell(&dc, OldSel); 
    } 
 
    // Set the current selection as row/col and draw (it will be drawn selected) 
    m_nCurrentSel = nIndex; 
    DrawCell(&dc, m_nCurrentSel); 
 
    // Store the current colour 
    if (m_nCurrentSel == CUSTOM_BOX_VALUE) 
        m_pParent->SendMessage(CPN_SELCHANGE, (WPARAM) m_crInitialColor, 0); 
    else if (m_nCurrentSel == DEFAULT_BOX_VALUE) 
    { 
        m_crColor = m_crDefaultColor; 
        m_pParent->SendMessage(CPN_SELCHANGE, (WPARAM) m_crDefaultColor, 0); 
    } 
    else 
    { 
        m_crColor = GetColor(m_nCurrentSel); 
        m_pParent->SendMessage(CPN_SELCHANGE, (WPARAM) m_crColor, 0); 
    } 
} 
 
/////////////////////////////////////////////////////////////////// 
/// Send the end message 
void CColorPopup::EndSelection(int nMessage) 
{ 
   
 
    // If custom text selected, perform a custom colour selection 
    if (nMessage != CPN_SELENDCANCEL && m_nCurrentSel == CUSTOM_BOX_VALUE) 
    { 
         
		CColorDialog dlg; 
		 
		if (dlg.DoModal() == IDOK) 
            m_crColor = dlg.GetColor(); 
        else 
            m_crColor = m_crInitialColor; 
		 
	 }  
 
    if (nMessage == CPN_SELENDCANCEL) 
        m_crColor = m_crInitialColor; 
 
    m_pParent->SendMessage(nMessage, (WPARAM) m_crColor, 0); 
     
	ReleaseCapture(); 
    DestroyWindow(); 
} 
 
//////////////////////////////////////////////////////////////// 
void CColorPopup::DrawCell(CDC* pDC, int nIndex) 
{ 
    CRect rect; 
	///////////////////////////////////// 
	// For the Custom Text area 
    if (m_strCustomText.GetLength() && nIndex == CUSTOM_BOX_VALUE) 
    { 
        // The extent of the actual text button 
        CRect TextButtonRect = m_CustomTextRect; 
        TextButtonRect.top += 2*m_nMargin; 
		TextButtonRect.DeflateRect(MAX_TEXTRECT,0); 
 
        // Fill background 
        pDC->FillSolidRect(TextButtonRect, ::GetSysColor(COLOR_3DFACE)); 
 
		 
        // Draw horizontal line 
        pDC->FillSolidRect(m_CustomTextRect.left+2*m_nMargin, m_CustomTextRect.top, 
                           m_CustomTextRect.Width()-4*m_nMargin, 1, 
						   ::GetSysColor(COLOR_3DSHADOW)); 
         
		pDC->FillSolidRect(m_CustomTextRect.left+2*m_nMargin, m_CustomTextRect.top+1, 
                           m_CustomTextRect.Width()-4*m_nMargin, 1, 
						   ::GetSysColor(COLOR_3DHILIGHT)); 
		 
        TextButtonRect.DeflateRect(1,1); 
 
        // fill background 
        if (m_nChosenColorSel == nIndex && m_nCurrentSel != nIndex) 
            pDC->FillSolidRect(TextButtonRect, ::GetSysColor(COLOR_3DLIGHT)); 
        else 
            pDC->FillSolidRect(TextButtonRect, ::GetSysColor(COLOR_3DFACE)); 
		 
		// fill Selected background 
		if (m_nChosenColorSel == nIndex) 
			pDC->FillSolidRect(TextButtonRect, RGB(0xE6,0xE6,0xE6)); 
		 
		// Draw button 
        if (m_nCurrentSel == nIndex){ 
				if (m_nChosenColorSel == nIndex){ 
					pDC->Draw3dRect(TextButtonRect, ::GetSysColor(COLOR_BTNSHADOW), 
									::GetSysColor(COLOR_BTNHILIGHT)); 
					rect = TextButtonRect; 
					rect.DeflateRect (1,1); 
					pDC->FillSolidRect(rect, ::GetSysColor(COLOR_3DFACE)); 
				}	 
				else 
 					pDC->Draw3dRect(TextButtonRect, ::GetSysColor(COLOR_BTNHILIGHT) , 
									::GetSysColor(COLOR_BTNSHADOW)); 
			} 
		else if (m_nChosenColorSel == nIndex) 
            pDC->Draw3dRect(TextButtonRect, ::GetSysColor(COLOR_BTNSHADOW),  
							::GetSysColor(COLOR_BTNHILIGHT)); 
		 
		 
		// Draw custom text 
        CFont *pOldFont = (CFont*) pDC->SelectObject(&m_Font); 
        pDC->SetBkMode(TRANSPARENT); 
        pDC->DrawText(m_strCustomText, TextButtonRect, DT_CENTER | 
					  DT_VCENTER | DT_SINGLELINE); 
        pDC->SelectObject(pOldFont); 
 
        return; 
    }         
	////////////////////////////////////////// 
    // For the Default Text area 
    if (nIndex == DEFAULT_BOX_VALUE) 
    { 
        // Fill background 
        pDC->FillSolidRect(m_DefaultTextRect, ::GetSysColor(COLOR_3DFACE)); 
 
        // The extent of the actual text button 
        CRect TextButtonRect = m_DefaultTextRect; 
        TextButtonRect.DeflateRect(1,1); 
		TextButtonRect.DeflateRect(MAX_TEXTRECT,0); 
		 
 
        // fill background 
        if (m_nChosenColorSel == nIndex && m_nCurrentSel != nIndex) 
            pDC->FillSolidRect(TextButtonRect, ::GetSysColor(COLOR_3DLIGHT)); 
        else 
            pDC->FillSolidRect(TextButtonRect, ::GetSysColor(COLOR_3DFACE)); 
				 
		// fill Selected background 
		if (m_nChosenColorSel == nIndex) 
			pDC->FillSolidRect(TextButtonRect, RGB(0xE6,0xE6,0xE6)); 
	 
        // Draw the line around text 
        CRect LineRect = TextButtonRect; 
        LineRect.DeflateRect(2*m_nMargin,2*m_nMargin); 
        CPen pen(PS_SOLID, 1, ::GetSysColor(COLOR_3DSHADOW)); 
        CPen* pOldPen = pDC->SelectObject(&pen); 
        pDC->SelectStockObject(NULL_BRUSH); 
        pDC->Rectangle(LineRect); 
        pDC->SelectObject(pOldPen); 
		 
	    // Draw button 
        if (m_nCurrentSel == nIndex){ 
				if (m_nChosenColorSel == nIndex){ 
					pDC->Draw3dRect(TextButtonRect, ::GetSysColor(COLOR_BTNSHADOW),  
									::GetSysColor(COLOR_BTNHILIGHT)); 
					//CRect rect; 
					rect = TextButtonRect; 
					rect.DeflateRect (1,1); 
					pDC->FillSolidRect(rect, ::GetSysColor(COLOR_3DFACE)); 
					pOldPen = pDC->SelectObject(&pen); 
					pDC->SelectStockObject(NULL_BRUSH); 
					pDC->Rectangle(LineRect); 
					pDC->SelectObject(pOldPen); 
				} 
				else 
 					pDC->Draw3dRect(TextButtonRect, ::GetSysColor(COLOR_BTNHILIGHT) , 
									::GetSysColor(COLOR_BTNSHADOW)); 
			} 
		else if (m_nChosenColorSel == nIndex) 
            pDC->Draw3dRect(TextButtonRect, ::GetSysColor(COLOR_BTNSHADOW),  
							::GetSysColor(COLOR_BTNHILIGHT)); 
		 
        // Draw the default demo color cell 
		CBrush brush(::GetSysColor(COLOR_BTNTEXT)); 
		CBrush* pOldBrush = (CBrush*) pDC->SelectObject(&brush); 
		CPen   penDefault; 
		penDefault.CreatePen(PS_SOLID, 1, ::GetSysColor(COLOR_3DSHADOW)); 
 
		CRect DefRect ; 
		DefRect = LineRect; 
		DefRect.DeflateRect(m_nMargin,m_nMargin); 
		CRect DefaltRect(DefRect.left+5 ,DefRect.top ,DefRect.left+15 ,DefRect.top+10); 
		 
        CBrush* pOldBrushDefault = (CBrush*) pDC->SelectObject(&brush); 
        CPen*   pOldPenDefault   = (CPen*)   pDC->SelectObject(&pen); 
	    pDC->Rectangle(DefaltRect); 
 
					 
		// Draw custom text 
        CFont *pOldFont = (CFont*) pDC->SelectObject(&m_Font); 
        pDC->SetBkMode(TRANSPARENT); 
        pDC->DrawText(m_strDefaultText, TextButtonRect, DT_CENTER | 
						DT_VCENTER | DT_SINGLELINE); 
        pDC->SelectObject(pOldFont); 
		 
		return; 
    }         
	 
	///////////////////////////////////////////// 
	//// For the color cells area 
    if (!GetCellRect(nIndex, rect)) return; 
 
    // Select and realize the palette 
    CPalette* pOldPalette; 
    if (pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE) 
    { 
        pOldPalette = pDC->SelectPalette(&m_Palette, FALSE); 
        pDC->RealizePalette(); 
    } 
 
 
    // fill background 
    if (m_nChosenColorSel == nIndex && m_nCurrentSel != nIndex) 
        pDC->FillSolidRect(rect, RGB(0xDC,0xDC,0xDC)); 
    else 
        pDC->FillSolidRect(rect, ::GetSysColor(COLOR_3DFACE)); 
	 
	if (m_nChosenColorSel == nIndex){ 
		pDC->FillSolidRect(rect, RGB(0xE6,0xE6,0xE6)); 
		pDC->Draw3dRect(rect, ::GetSysColor(COLOR_BTNSHADOW), ::GetSysColor(COLOR_BTNHILIGHT)); 
	}	 
	 
	 
	// Draw button 
    if (m_nCurrentSel == nIndex){ 
		if (m_nChosenColorSel == nIndex){ 
			pDC->Draw3dRect(rect, ::GetSysColor(COLOR_BTNSHADOW), ::GetSysColor(COLOR_BTNHILIGHT)); 
			CRect rectbtn; 
			rectbtn = rect; 
			rectbtn.DeflateRect (1,1); 
			pDC->FillSolidRect(rectbtn, ::GetSysColor(COLOR_3DFACE)); 
		}	 
		else 
 			pDC->Draw3dRect(rect, ::GetSysColor(COLOR_BTNHILIGHT) ,::GetSysColor(COLOR_BTNSHADOW)); 
	} 
	 
 
    CBrush brush(PALETTERGB(GetRValue(GetColor(nIndex)),  
                            GetGValue(GetColor(nIndex)),  
                            GetBValue(GetColor(nIndex)) )); 
    CPen   pen; 
    pen.CreatePen(PS_SOLID, 1, ::GetSysColor(COLOR_3DSHADOW)); 
 
    CBrush* pOldBrush = (CBrush*) pDC->SelectObject(&brush); 
    CPen*   pOldPen   = (CPen*)   pDC->SelectObject(&pen); 
 
    // Draw the cell colour 
    rect.DeflateRect(m_nMargin+1, m_nMargin+1); 
    pDC->Rectangle(rect); 
 
    // restore DC and cleanup 
    pDC->SelectObject(pOldBrush); 
    pDC->SelectObject(pOldPen); 
    brush.DeleteObject(); 
    pen.DeleteObject(); 
 
    if (pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE) 
        pDC->SelectPalette(pOldPalette, FALSE); 
} 
 
/////////////////////////////////////////////////////////////// 
BOOL CColorPopup::OnQueryNewPalette()  
{ 
    Invalidate();     
    return CWnd::OnQueryNewPalette(); 
} 
 
////////////////////////////////////////////////////////////////// 
void CColorPopup::OnPaletteChanged(CWnd* pFocusWnd)  
{ 
    CWnd::OnPaletteChanged(pFocusWnd); 
 
    if (pFocusWnd->GetSafeHwnd() != GetSafeHwnd()) 
        Invalidate(); 
} 
 
/////////////////////////////////////////////////////////////////// 
void CColorPopup::OnKillFocus(CWnd* pNewWnd)  
{ 
	CWnd::OnKillFocus(pNewWnd); 
	 
	//m_pParent->SendMessage(CPN_SELENDCANCEL, (WPARAM) m_crColor, 0); 
	//EndSelection(CPN_SELENDCANCEL); 
     
	//ReleaseCapture(); 
    //DestroyWindow();  
} 
 
///////////////////////////////////////////////////////////////////// 
// KillFocus  
void CColorPopup::OnActivateApp(BOOL bActive, HTASK hTask)  
{ 
	CWnd::OnActivateApp(bActive, hTask); 
 
	// If Deactivating App, cancel this selection 
	if (!bActive) 
		 EndSelection(CPN_SELENDCANCEL); 
} 
 
void CColorPopup::OnLButtonDown(UINT nFlags, CPoint point)  
{ 
	// TODO: Add your message handler code here and/or call default 
	//SendMessage(WM_SYSCOMMAND, 0xF012); 
 
	CWnd::OnLButtonDown(nFlags, point); 
	PostMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x,point.y)); 
 
	CWnd::OnLButtonDown(nFlags, point); 
} 
 
/////////////////////////////////////////////// 
void CColorPopup::DrawName (CDC *pDC,CRect rectName) 
{ 
	pDC->DrawText ("选择颜色",rectName, DT_CENTER | 
					  DT_VCENTER | DT_SINGLELINE); 
}