📄 colorpickerdlg.cpp.svn-base
字号:
/**
* ColorPickerDlg.cpp
*
* Copyright (C) 2008 David Andrs <pda@jasnapaka.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "../StdAfx.h"
#include "../prssr.h"
#include "ColorPickerDlg.h"
#include "../../share/UIHelper.h"
#ifdef MYDEBUG
#undef THIS_FILE
static TCHAR THIS_FILE[] = _T(__FILE__);
#include "../debug/crtdbg.h"
#define new MYDEBUG_NEW
#endif
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define SELECT_COLOR_MESSAGE (WM_USER + 100)
#define SELECT_LIGHTNESS_MESSAGE (WM_USER + 101)
//
COLORREF hsl2rgb(double h, double sl, double l) {
double v;
double r, g, b;
r = l; // default to gray
g = l;
b = l;
v = (l <= 0.5) ? (l * (1.0 + sl)) : (l + sl - l * sl);
if (v > 0) {
double m;
double sv;
int sextant;
double fract, vsf, mid1, mid2;
m = l + l - v;
sv = (v - m ) / v;
h *= 6.0;
sextant = (int) h;
fract = h - sextant;
vsf = v * sv * fract;
mid1 = m + vsf;
mid2 = v - vsf;
switch (sextant) {
case 0:
r = v;
g = mid1;
b = m;
break;
case 1:
r = mid2;
g = v;
b = m;
break;
case 2:
r = m;
g = v;
b = mid1;
break;
case 3:
r = m;
g = mid2;
b = v;
break;
case 4:
r = mid1;
g = m;
b = v;
break;
case 5:
r = v;
g = m;
b = mid2;
break;
}
}
return RGB((BYTE) (r * 255.0f), (BYTE) (g * 255.0f), (BYTE) (b * 255.0f));
}
void rgb2hsl(COLORREF rgb, double &h, double &s, double &l) {
double r = GetRValue(rgb) / 255.0;
double g = GetGValue(rgb) / 255.0;
double b = GetBValue(rgb) / 255.0;
double v;
double m;
double vm;
double r2, g2, b2;
h = 0; // default to black
s = 0;
l = 0;
v = max(r, g);
v = max(v, b);
m = min(r, g);
m = min(m, b);
l = (m + v) / 2.0;
if (l <= 0.0) {
return;
}
vm = v - m;
s = vm;
if (s > 0.0) {
s /= (l <= 0.5) ? (v + m ) : (2.0 - v - m);
}
else {
return;
}
r2 = (v - r) / vm;
g2 = (v - g) / vm;
b2 = (v - b) / vm;
if (r == v) {
h = (g == m ? 5.0 + b2 : 1.0 - g2);
}
else if (g == v) {
h = (b == m ? 1.0 + r2 : 3.0 - b2);
}
else {
h = (r == m ? 3.0 + g2 : 5.0 - r2);
}
h /= 6.0;
}
/////////////////////////////////////////////////////////////////////////////
// CColorCtl Control
CColorCtl::CColorCtl() {
}
CColorCtl::~CColorCtl() {
}
BEGIN_MESSAGE_MAP(CColorCtl, CStatic)
//{{AFX_MSG_MAP(CColorCtl)
ON_WM_PAINT()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CColorCtl::SetColor(COLORREF clrColor) {
m_clrColor = clrColor;
}
void CColorCtl::OnPaint() {
CPaintDC dc(this); // device context for painting
CRect rc;
GetClientRect(&rc);
// space
dc.FrameRect(&rc, &CBrush(::GetSysColor(COLOR_WINDOW)));
// fill
// rc.DeflateRect(SCALEX(1), SCALEY(1), SCALEX(1), SCALEY(1));
rc.DeflateRect(1, 1, 1, 1);
dc.FillSolidRect(&rc, m_clrColor);
ValidateRect(NULL);
}
/////////////////////////////////////////////////////////////////////////////
// CLightnessCtl Control
CLightnessCtl::CLightnessCtl() {
m_dL = 0.5;
m_bmp = NULL;
m_dcMem = NULL;
}
CLightnessCtl::~CLightnessCtl() {
if (m_dcMem != NULL && m_bmp != NULL)
m_dcMem->SelectObject(m_bmp); // select original bitmap
delete m_dcMem;
}
BEGIN_MESSAGE_MAP(CLightnessCtl, CStatic)
//{{AFX_MSG_MAP(CLightnessCtl)
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CLightnessCtl::SetColor(COLORREF color) {
double l;
rgb2hsl(color, m_dH, m_dS, l);
PrepareGradient();
}
void CLightnessCtl::SetColor(double h, double s, double l) {
m_dH = h;
m_dS = s;
m_dL = l;
PrepareGradient();
}
#define THUMB_WD SCALEX(10)
void CLightnessCtl::PrepareGradient() {
if (m_dcMem != NULL) {
CRect rc;
GetClientRect(&rc);
CRect rcFrame = CRect(rc.left, rc.top, rc.right - THUMB_WD, rc.bottom);
CPen blackPen(PS_SOLID, SCALEY(1), RGB(0, 0, 0));
m_dcMem->SelectObject(&blackPen);
HIDPI_BorderRectangle(m_dcMem->GetSafeHdc(), rcFrame.left, rcFrame.top, rcFrame.right, rcFrame.bottom);
// fill
rcFrame.DeflateRect(SCALEX(1), SCALEY(1), SCALEX(2), SCALEY(1));
for (int i = 0; i < rc.Height(); i += SCALEY(3)) {
double l = 1.0 - ((double) (i) / rc.Height());
COLORREF rgb = hsl2rgb(m_dH, m_dS, l);
m_dcMem->FillSolidRect(rcFrame.left, rcFrame.top + i, rcFrame.right, rcFrame.top + (i + SCALEY(3)), rgb);
}
i -= SCALEY(3);
double l = 0.0;
COLORREF rgb = hsl2rgb(m_dH, m_dS, l);
m_dcMem->FillSolidRect(rcFrame.left, rcFrame.top + i, rcFrame.right, rcFrame.bottom, rgb);
}
}
void CLightnessCtl::OnPaint() {
CPaintDC dc(this); // device context for painting
int save = dc.SaveDC();
CRect rc;
GetClientRect(&rc);
if (m_dcMem == NULL) {
m_dcMem = new CDC;
CDC *pDC = GetDC();
CBitmap bmp;
bmp.CreateCompatibleBitmap(pDC, rc.Width() - THUMB_WD, rc.Height());
m_dcMem->CreateCompatibleDC(pDC);
m_bmp = m_dcMem->SelectObject(&bmp);
PrepareGradient();
ReleaseDC(pDC);
}
// copy gradient to screen
dc.BitBlt(0, 0, rc.Width() - THUMB_WD, rc.Height(), m_dcMem, 0, 0, SRCCOPY);
// thumb
dc.FillSolidRect(rc.right - THUMB_WD, rc.top, rc.right, rc.bottom, GetSysColor(COLOR_WINDOW));
int y = (int) ((1.0 - m_dL) * rc.Height());
CPen blackPen(PS_SOLID, SCALEY(1), RGB(0, 0, 0));
dc.SelectObject(&blackPen);
dc.MoveTo(rc.right - THUMB_WD + SCALEX(1), y);
dc.LineTo(rc.right, y);
for (int i = 1; i<= SCALEY(2); i++) {
dc.MoveTo(rc.right - THUMB_WD + SCALEX(1) + (2 * i), y - i);
dc.LineTo(rc.right, y - i);
dc.MoveTo(rc.right - THUMB_WD + SCALEX(1) + (2 * i), y + i);
dc.LineTo(rc.right, y + i);
}
dc.RestoreDC(save);
ValidateRect(NULL);
}
void CLightnessCtl::SetLFromPoint(CPoint &point) {
CRect rc;
GetClientRect(&rc);
m_dL = (double) (rc.bottom - point.y) / rc.Height();
}
void CLightnessCtl::UpdateMe(CPoint &point) {
SetLFromPoint(point);
CRect rc;
GetClientRect(&rc);
rc.left = rc.right - THUMB_WD;
InvalidateRect(&rc);
UpdateWindow();
}
void CLightnessCtl::OnLButtonDown(UINT nFlags, CPoint point) {
SetCapture();
UpdateMe(point);
GetParent()->SendMessage(SELECT_LIGHTNESS_MESSAGE);
}
void CLightnessCtl::OnMouseMove(UINT nFlags, CPoint point) {
CRect rc;
GetClientRect(&rc);
if (point.y < rc.top)
point.y = rc.top;
else if (point.y > rc.bottom)
point.y = rc.bottom;
UpdateMe(point);
GetParent()->SendMessage(SELECT_LIGHTNESS_MESSAGE);
}
void CLightnessCtl::OnLButtonUp(UINT nFlags, CPoint point) {
ReleaseCapture();
}
/////////////////////////////////////////////////////////////////////////////
// CHSCtl Control
CHSCtl::CHSCtl() {
m_dcMem = NULL;
m_bmp = NULL;
}
CHSCtl::~CHSCtl() {
if (m_dcMem != NULL && m_bmp != NULL)
m_dcMem->SelectObject(m_bmp); // select original bitmap
delete m_dcMem;
}
BEGIN_MESSAGE_MAP(CHSCtl, CStatic)
//{{AFX_MSG_MAP(CHSCtl)
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CHSCtl::SetColor(double h, double s, double l) {
m_dH = h;
m_dS = s;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -