📄 cjcolorpicker.cpp
字号:
// CJColorPicker.cpp : implementation file
//
// CJColorPicker is a drop-in Color picker control. Check out the
// header file or the accompanying HTML doc file for details.
//
// Written by Chris Maunder (chrismaunder@codeguru.com)
// Extended by Alexander Bischofberger (bischofb@informatik.tu-muenchen.de)
// Copyright (c) 1998.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name is included. If
// the source code in this file is used in any commercial application
// then a simple email would be nice.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability if it causes any damage to your
// computer, causes your pet cat to fall ill, increases baldness or
// makes you car start emitting strange noises when you start it up.
//
// Expect bugs.
//
// Please use and enjoy. Please let me know of any bugs/mods/improvements
// that you have found/implemented and I will fix/incorporate them into this
// file.
//
// Updated 16 May 1998
// 31 May 1998 - added Default text (CJM)
// 9 Jan 1999 - minor vis update
//
/////////////////////////////////////////////////////////////////////////////
/****************************************************************************
*
* $Date: 1999/11/30 21:45:48 $
* $Revision: 1.1.1.3 $
* $Archive: /CodeJock/CJLibrary/CJColorPicker.cpp $
*
* $History: CJColorPicker.cpp $
*
* ***************** Version 5 *****************
* User: Kirk Stowell Date: 10/31/99 Time: 11:49p
* Updated in $/CodeJock/CJLibrary
* Overrode OnEraseBkgnd(...), OnPaint() and made modifications to
* DrawItem(...) for flicker free drawing.
*
* Modified resource include for static builds.
*
* Added method CheckTextColor(...) which tests if the intensity of the
* color is greater as 128. If the intensity < 128 => color is dark, so
* the text must be light. Stephane Routelous
* [routelous@cad-cam-concept.de]
*
* Fixed potential resource and memory leak problems.
*
* Removed un-necessary calls to GetParent(), a call is made only once at
* initialization, to ensure we are working with a valid handle.
*
* Made class methods virtual for inheritance purposes.
*
* ***************** Version 4 *****************
* User: Kirk Stowell Date: 10/14/99 Time: 12:22p
* Updated in $/CodeJock/CJLibrary
* Added source control history to file header.
*
***************************************************************************/
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "CJColorPopup.h"
#include "CJColorPicker.h"
#include "CJResource.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
void AFXAPI DDX_CJColorPicker(CDataExchange *pDX, int nIDC, COLORREF& crColor)
{
HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
ASSERT (hWndCtrl != NULL);
CCJColorPicker* pColorPicker = (CCJColorPicker*) CWnd::FromHandle(hWndCtrl);
if (pDX->m_bSaveAndValidate)
{
crColor = pColorPicker->GetColor();
}
else // initializing
{
pColorPicker->SetColor(crColor);
}
}
/////////////////////////////////////////////////////////////////////////////
// CCJColorPicker
CCJColorPicker::CCJColorPicker()
{
SetBkColor(GetSysColor(COLOR_3DFACE));
SetTextColor(GetSysColor(COLOR_BTNTEXT));
m_bTrackSelection = FALSE;
m_nSelectionMode = CP_MODE_BK;
m_bActive = FALSE;
// 1999-06-11 begin mods KStowell
m_strDefaultText.LoadString( IDS_COLOR_AUTO );
m_strCustomText.LoadString( IDS_COLOR_CUST );
// 1999-06-11 end mods KStowell
// 10-14-1999 - Kirk Stowell
m_pParentWnd = NULL;
}
CCJColorPicker::~CCJColorPicker()
{
}
IMPLEMENT_DYNCREATE(CCJColorPicker, CButton)
BEGIN_MESSAGE_MAP(CCJColorPicker, CButton)
//{{AFX_MSG_MAP(CCJColorPicker)
ON_CONTROL_REFLECT_EX(BN_CLICKED, OnClicked)
ON_WM_CREATE()
ON_WM_ERASEBKGND()
ON_WM_PAINT()
//}}AFX_MSG_MAP
ON_MESSAGE(CPN_SELENDOK, OnSelEndOK)
ON_MESSAGE(CPN_SELENDCANCEL, OnSelEndCancel)
ON_MESSAGE(CPN_SELCHANGE, OnSelChange)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CCJColorPicker message handlers
LONG CCJColorPicker::OnSelEndOK(UINT lParam, LONG /*wParam*/)
{
COLORREF crNewColor = (COLORREF) lParam;
m_bActive = FALSE;
SetColor(crNewColor);
//BEGIN SRO
CheckTextColor(crNewColor);
//END SRO
// 10-14-1999 - Kirk Stowell - Removed redundant calls to GetParent().
if (m_pParentWnd) {
m_pParentWnd->SendMessage(CPN_CLOSEUP, lParam, (WPARAM) GetDlgCtrlID());
m_pParentWnd->SendMessage(CPN_SELENDOK, lParam, (WPARAM) GetDlgCtrlID());
}
if (crNewColor != GetColor()) {
if (m_pParentWnd) {
m_pParentWnd->SendMessage(CPN_SELCHANGE, lParam, (WPARAM) GetDlgCtrlID());
}
}
return TRUE;
}
LONG CCJColorPicker::OnSelEndCancel(UINT lParam, LONG /*wParam*/)
{
m_bActive = FALSE;
SetColor((COLORREF) lParam);
//BEGIN SRO
CheckTextColor((COLORREF) lParam);
//END SRO
// 10-14-1999 - Kirk Stowell - Removed redundant calls to GetParent().
if (m_pParentWnd) {
m_pParentWnd->SendMessage(CPN_CLOSEUP, lParam, (WPARAM) GetDlgCtrlID());
m_pParentWnd->SendMessage(CPN_SELENDCANCEL, lParam, (WPARAM) GetDlgCtrlID());
}
return TRUE;
}
LONG CCJColorPicker::OnSelChange(UINT lParam, LONG /*wParam*/)
{
if (m_bTrackSelection) {
SetColor((COLORREF) lParam);
//BEGIN SRO
CheckTextColor((COLORREF) lParam);
//END SRO
}
// 10-14-1999 - Kirk Stowell - Removed redundant calls to GetParent().
if (m_pParentWnd) {
m_pParentWnd->SendMessage(CPN_SELCHANGE, lParam, (WPARAM) GetDlgCtrlID());
}
return TRUE;
}
int CCJColorPicker::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CButton::OnCreate(lpCreateStruct) == -1)
return -1;
SetWindowSize(); // resize appropriately
return 0;
}
// On mouse click, create and show a CJColorPopup window for Color selection
BOOL CCJColorPicker::OnClicked()
{
m_bActive = TRUE;
CRect rect;
GetWindowRect(rect);
new CCJColorPopup(CPoint(rect.left, rect.bottom), // Point to display popup
GetColor(), // Selected Color
this, // parent
m_strDefaultText, // "Default" text area
m_strCustomText); // Custom Text
// 10-14-1999 - Kirk Stowell - Removed redundant calls to GetParent().
if (m_pParentWnd) {
m_pParentWnd->SendMessage(CPN_DROPDOWN, (LPARAM)GetColor(), (WPARAM) GetDlgCtrlID());
}
// Docs say I should return FALSE to stop the parent also getting the message.
// HA! What a joke.
return TRUE;
}
// 1999-06-11 begin mods KStowell
void CCJColorPicker::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
ASSERT(lpDrawItemStruct != NULL);
// define some temporary variables.
CDC* pDC = CDC::FromHandle( lpDrawItemStruct->hDC );
CRect rcItem = lpDrawItemStruct->rcItem;
int nState = lpDrawItemStruct->itemState;
DWORD dwState = EDGE_RAISED;
DWORD dwArrow = DFCS_SCROLLDOWN;
// Paint the background.
pDC->FillSolidRect(rcItem, ::GetSysColor(COLOR_3DFACE));
// set display flags based on state.
if((nState & ODS_SELECTED) || (m_bActive == TRUE)) {
dwState = EDGE_SUNKEN;
dwArrow = DFCS_SCROLLDOWN|DFCS_PUSHED;
}
if(nState & ODS_DISABLED) {
dwArrow = DFCS_SCROLLDOWN|DFCS_INACTIVE;
}
// Draw the drop arrow.
CRect rcArrow( rcItem );
rcArrow.left = rcArrow.Width()-::GetSystemMetrics( SM_CXHTHUMB );
pDC->DrawFrameControl( &rcArrow, DFC_SCROLL, dwArrow );
pDC->Draw3dRect( rcArrow, ::GetSysColor( COLOR_3DFACE ), ::GetSysColor( COLOR_3DFACE ));
rcArrow.DeflateRect( 1,1 );
pDC->Draw3dRect( rcArrow, ::GetSysColor( COLOR_3DFACE ), ::GetSysColor( COLOR_3DFACE ));
if((nState & ODS_SELECTED) || (m_bActive == TRUE))
rcArrow.OffsetRect( 1,1 );
// draw the seperator line.
CPen penShadow( PS_SOLID, 1, ::GetSysColor( COLOR_3DSHADOW ));
CPen* pOldPen = pDC->SelectObject( &penShadow );
pDC->MoveTo( rcArrow.left-1, rcArrow.top+2 );
pDC->LineTo( rcArrow.left-1, rcArrow.bottom-2 );
CPen penHilite( PS_SOLID, 1, ::GetSysColor( COLOR_3DHILIGHT ));
pDC->SelectObject( &penHilite );
pDC->MoveTo( rcArrow.left, rcArrow.top+2 );
pDC->LineTo( rcArrow.left, rcArrow.bottom-2 );
// draw the control border.
pDC->DrawEdge( rcItem, dwState, BF_RECT );
// draw the focus rect.
rcItem.DeflateRect( 2, 2 );
pDC->Draw3dRect( rcItem, ::GetSysColor( COLOR_3DFACE ), ::GetSysColor( COLOR_3DFACE ) );
if( nState & ODS_FOCUS ) {
pDC->DrawFocusRect( rcItem );
}
// draw the color box.
if((nState & ODS_SELECTED) || (m_bActive == TRUE))
rcItem.OffsetRect( 1,1 );
rcItem.DeflateRect( 2, 2 );
rcItem.right = rcArrow.left-4;
CBrush brush( ((nState & ODS_DISABLED) || m_crColorBk == CLR_DEFAULT)?
::GetSysColor(COLOR_3DFACE) : m_crColorBk);
CBrush* pOldBrush = (CBrush*)pDC->SelectObject( &brush );
pDC->SelectStockObject(( nState & ODS_DISABLED )?WHITE_PEN:BLACK_PEN );
pDC->Rectangle( rcItem );
// Draw the window text (if any)
CString strText;
GetWindowText(strText);
if (strText.GetLength())
{
pDC->SetBkMode(TRANSPARENT);
if (nState & ODS_DISABLED)
{
rcItem.OffsetRect(1,1);
pDC->SetTextColor(::GetSysColor(COLOR_3DHILIGHT));
pDC->DrawText(strText, rcItem, DT_CENTER|DT_SINGLELINE|DT_VCENTER);
rcItem.OffsetRect(-1,-1);
pDC->SetTextColor(::GetSysColor(COLOR_3DSHADOW));
pDC->DrawText(strText, rcItem, DT_CENTER|DT_SINGLELINE|DT_VCENTER);
}
else
{
pDC->SetTextColor((m_crColorText == CLR_DEFAULT)? 0 : m_crColorText);
pDC->DrawText(strText, rcItem, DT_CENTER|DT_SINGLELINE|DT_VCENTER);
}
}
// fix potential resource leak - KStowell - 10-21-99
pDC->SelectObject( pOldPen );
pDC->SelectObject( pOldBrush );
brush.DeleteObject();
penHilite.DeleteObject();
penHilite.DeleteObject();
}
// 1999-06-11 end mods KStowell
/////////////////////////////////////////////////////////////////////////////
// CCJColorPicker overrides
void CCJColorPicker::PreSubclassWindow()
{
ModifyStyle(0, BS_OWNERDRAW); // Make it owner drawn
CButton::PreSubclassWindow();
SetWindowSize(); // resize appropriately
}
/////////////////////////////////////////////////////////////////////////////
// CCJColorPicker attributes
COLORREF CCJColorPicker::GetColor()
{
return (m_nSelectionMode == CP_MODE_TEXT)?
GetTextColor(): GetBkColor();
}
void CCJColorPicker::SetColor(COLORREF crColor)
{
(m_nSelectionMode == CP_MODE_TEXT)?
SetTextColor(crColor): SetBkColor(crColor);
}
void CCJColorPicker::SetBkColor(COLORREF crColorBk)
{
m_crColorBk = crColorBk;
//BEGIN SRO
CheckTextColor(crColorBk);
//END SRO
if (IsWindow(m_hWnd)) RedrawWindow();
}
void CCJColorPicker::SetTextColor(COLORREF crColorText)
{
m_crColorText = crColorText;
if (IsWindow(m_hWnd)) RedrawWindow();
}
void CCJColorPicker::SetDefaultText(LPCTSTR szDefaultText)
{
m_strDefaultText = (szDefaultText)? szDefaultText : _T("");
}
void CCJColorPicker::SetCustomText(LPCTSTR szCustomText)
{
m_strCustomText = (szCustomText)? szCustomText : _T("");
}
/////////////////////////////////////////////////////////////////////////////
// CCJColorPicker implementation
void CCJColorPicker::SetWindowSize()
{
// 10-14-1999 - Kirk Stowell - Added to help reduce flicker, we only need to make
// a call to GetParent() once at initialization.
m_pParentWnd = GetParent();
// Get size dimensions of edges
CSize MarginSize(::GetSystemMetrics(SM_CXEDGE), ::GetSystemMetrics(SM_CYEDGE));
// Get size of dropdown arrow
int nArrowWidth = max(::GetSystemMetrics(SM_CXHTHUMB), 5*MarginSize.cx);
int nArrowHeight = max(::GetSystemMetrics(SM_CYVTHUMB), 5*MarginSize.cy);
CSize ArrowSize(max(nArrowWidth, nArrowHeight), max(nArrowWidth, nArrowHeight));
// Get window size
CRect rect;
GetWindowRect(rect);
if (m_pParentWnd) {
m_pParentWnd->ScreenToClient(rect);
}
// Set window size at least as wide as 2 arrows, and as high as arrow + margins
int nWidth = max(rect.Width(), 2*ArrowSize.cx + 2*MarginSize.cx);
MoveWindow(rect.left, rect.top, nWidth, ArrowSize.cy+2*MarginSize.cy, TRUE);
// Get the new coords of this window
GetWindowRect(rect);
ScreenToClient(rect);
// Get the rect where the arrow goes, and convert to client coords.
m_ArrowRect.SetRect(rect.right - ArrowSize.cx - MarginSize.cx,
rect.top + MarginSize.cy, rect.right - MarginSize.cx,
rect.bottom - MarginSize.cy);
}
void CCJColorPicker::CheckTextColor(COLORREF crColor)
{
int R = GetRValue(crColor);
int G = GetGValue(crColor);
int B = GetBValue(crColor);
double Intensity = .299 * R + .587 * G + .114 * B ;
if ( Intensity >= 127 ) {
SetTextColor(RGB(0,0,0));
} else {
SetTextColor(RGB(255,255,255));
}
}
BOOL CCJColorPicker::OnEraseBkgnd(CDC* pDC)
{
// overridden for flicker-free drawing.
UNUSED_ALWAYS(pDC);
return TRUE;
}
void CCJColorPicker::OnPaint()
{
CPaintDC dc(this); // device context for painting
// KStowell - Get the client rect.
CRect rcClient, rcClip;
dc.GetClipBox( &rcClip );
GetClientRect( &rcClient );
// KStowell - Create a memory device-context. This is done to help reduce
// screen flicker, since we will paint the entire control to the
// off screen device context first.
CDC memDC;
CBitmap bitmap;
memDC.CreateCompatibleDC(&dc);
bitmap.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height());
CBitmap* pOldBitmap = memDC.SelectObject(&bitmap);
// KStowell - Repaint the background.
memDC.FillSolidRect( rcClient, ::GetSysColor(COLOR_WINDOW) );
// let the control do its default drawing.
CWnd::DefWindowProc( WM_PAINT, (WPARAM)memDC.m_hDC, 0 );
// KStowell - Copy the memory device context back into the original DC via BitBlt().
dc.BitBlt( rcClip.left, rcClip.top, rcClip.Width(), rcClip.Height(), &memDC,
rcClip.left, rcClip.top, SRCCOPY );
// KStowell - Cleanup resources.
memDC.SelectObject(pOldBitmap);
memDC.DeleteDC();
bitmap.DeleteObject();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -