#include "StdAfx.h" #include namespace DuiLib { #define HSLMAX 255 /* H,L, and S vary over 0-HSLMAX */ #define RGBMAX 255 /* R,G, and B vary over 0-RGBMAX */ #define HSLUNDEFINED (HSLMAX*2/3) /* * Convert hue value to RGB */ static float HueToRGB(float v1, float v2, float vH) { if (vH < 0.0f) vH += 1.0f; if (vH > 1.0f) vH -= 1.0f; if ((6.0f * vH) < 1.0f) return (v1 + (v2 - v1) * 6.0f * vH); if ((2.0f * vH) < 1.0f) return (v2); if ((3.0f * vH) < 2.0f) return (v1 + (v2 - v1) * ((2.0f / 3.0f) - vH) * 6.0f); return (v1); } /* * Convert color RGB to HSL * pHue HSL hue value [0 - 1] * pSat HSL saturation value [0 - 1] * pLue HSL luminance value [0 - 1] */ static void RGBToHSL(DWORD clr, float *pHue, float *pSat, float *pLue) { float R = (float)(GetRValue(clr) / 255.0f); //RGB from 0 to 255 float G = (float)(GetGValue(clr) / 255.0f); float B = (float)(GetBValue(clr) / 255.0f); float H = 0, S = 0, L = 0; float fMin = min(R, min(G, B)); //Min. value of RGB float fMax = max(R, max(G, B)); //Max. value of RGB float fDelta = fMax - fMin; //Delta RGB value L = (fMax + fMin) / 2.0f; if (fDelta == 0) //This is a gray, no chroma... { H = 0.0f; //HSL results from 0 to 1 S = 0.0f; } else //Chromatic data... { float del_R, del_G, del_B; if (L < 0.5) S = fDelta / (fMax + fMin); else S = fDelta / (2.0f - fMax - fMin); del_R = (((fMax - R) / 6.0f) + (fDelta / 2.0f)) / fDelta; del_G = (((fMax - G) / 6.0f) + (fDelta / 2.0f)) / fDelta; del_B = (((fMax - B) / 6.0f) + (fDelta / 2.0f)) / fDelta; if (R == fMax) H = del_B - del_G; else if (G == fMax) H = (1.0f / 3.0f) + del_R - del_B; else if (B == fMax) H = (2.0f / 3.0f) + del_G - del_R; if (H < 0.0f) H += 1.0f; if (H > 1.0f) H -= 1.0f; } *pHue = H; *pSat = S; *pLue = L; } /* * Convert color HSL to RGB * H HSL hue value [0 - 1] * S HSL saturation value [0 - 1] * L HSL luminance value [0 - 1] */ static DWORD HSLToRGB(float H, float S, float L) { BYTE R, G, B; float var_1, var_2; if (S == 0) //HSL from 0 to 1 { R = G = B = (BYTE)(L * 255.0f); //RGB results from 0 to 255 } else { if (L < 0.5) var_2 = L * (1.0f + S); else var_2 = (L + S) - (S * L); var_1 = 2.0f * L - var_2; R = (BYTE)(255.0f * HueToRGB(var_1, var_2, H + (1.0f / 3.0f))); G = (BYTE)(255.0f * HueToRGB(var_1, var_2, H)); B = (BYTE)(255.0f * HueToRGB(var_1, var_2, H - (1.0f / 3.0f))); } return RGB(R, G, B); } /* * _HSLToRGB color HSL value to RGB * clr RGB color value * nHue HSL hue value [0 - 360] * nSat HSL saturation value [0 - 200] * nLue HSL luminance value [0 - 200] */ #define _HSLToRGB(h,s,l) (0xFF << 24 | HSLToRGB((float)h / 360.0f,(float)s / 200.0f,l / 200.0f)) /////////////////////////////////////////////////////////////////////// // // IMPLEMENT_DUICONTROL(CColorPaletteUI) CColorPaletteUI::CColorPaletteUI() : m_uButtonState(0) , m_bIsInBar(false) , m_bIsInPallet(false) , m_nCurH(180) , m_nCurS(200) , m_nCurB(100) , m_nPalletHeight(200) , m_nBarHeight(10) , m_pBits(NULL) { memset(&m_bmInfo, 0, sizeof(m_bmInfo)); m_hMemBitmap=NULL; } CColorPaletteUI::~CColorPaletteUI() { if (m_pBits) free(m_pBits); if (m_hMemBitmap) { ::DeleteObject(m_hMemBitmap); } } DWORD CColorPaletteUI::GetSelectColor() { DWORD dwColor = _HSLToRGB(m_nCurH, m_nCurS, m_nCurB); return 0xFF << 24 | GetRValue(dwColor) << 16 | GetGValue(dwColor) << 8 | GetBValue(dwColor); } void CColorPaletteUI::SetSelectColor(DWORD dwColor) { float H = 0, S = 0, B = 0; COLORREF dwBkClr = RGB(GetBValue(dwColor),GetGValue(dwColor),GetRValue(dwColor)); RGBToHSL(dwBkClr, &H, &S, &B); m_nCurH = (int)(H*360); m_nCurS = (int)(S*200); m_nCurB = (int)(B*200); UpdatePalletData(); NeedUpdate(); } LPCTSTR CColorPaletteUI::GetClass() const { return _T("ColorPaletteUI"); } LPVOID CColorPaletteUI::GetInterface(LPCTSTR pstrName) { if (_tcscmp(pstrName, DUI_CTR_COLORPALETTE) == 0) return static_cast(this); return CControlUI::GetInterface(pstrName); } void CColorPaletteUI::SetPalletHeight(int nHeight) { m_nPalletHeight = nHeight; } int CColorPaletteUI::GetPalletHeight() const { return m_nPalletHeight; } void CColorPaletteUI::SetBarHeight(int nHeight) { if (nHeight>150) { nHeight = 150; //限制最大高度,由于当前设计,nheight超出190,程序会因越界访问崩溃 } m_nBarHeight = nHeight; } int CColorPaletteUI::GetBarHeight() const { return m_nBarHeight; } void CColorPaletteUI::SetThumbImage(LPCTSTR pszImage) { if (m_strThumbImage != pszImage) { m_strThumbImage = pszImage; NeedUpdate(); } } LPCTSTR CColorPaletteUI::GetThumbImage() const { return m_strThumbImage.GetData(); } void CColorPaletteUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue) { if (_tcscmp(pstrName, _T("palletheight")) == 0) SetPalletHeight(_ttoi(pstrValue)); else if (_tcscmp(pstrName, _T("barheight")) == 0) SetBarHeight(_ttoi(pstrValue)); else if (_tcscmp(pstrName, _T("thumbimage")) == 0) SetThumbImage(pstrValue); else CControlUI::SetAttribute(pstrName, pstrValue); } void CColorPaletteUI::DoInit() { m_MemDc = CreateCompatibleDC(GetManager()->GetPaintDC()); m_hMemBitmap = CreateCompatibleBitmap(GetManager()->GetPaintDC(), 400, 360); SelectObject(m_MemDc, m_hMemBitmap); ::GetObject(m_hMemBitmap, sizeof(m_bmInfo), &m_bmInfo); DWORD dwSize = m_bmInfo.bmHeight * m_bmInfo.bmWidthBytes; m_pBits = (BYTE *)malloc(dwSize); ::GetBitmapBits(m_hMemBitmap, dwSize, m_pBits); } void CColorPaletteUI::SetPos(RECT rc, bool bNeedInvalidate) { CControlUI::SetPos(rc, bNeedInvalidate); m_ptLastPalletMouse.x = m_nCurH * (m_rcItem.right - m_rcItem.left) / 360 + m_rcItem.left; m_ptLastPalletMouse.y = (200 - m_nCurB) * m_nPalletHeight / 200 + m_rcItem.top; UpdatePalletData(); UpdateBarData(); } void CColorPaletteUI::DoEvent(TEventUI& event) { CControlUI::DoEvent(event); if (event.Type == UIEVENT_BUTTONDOWN) { if (event.ptMouse.x >= m_rcItem.left && event.ptMouse.y >= m_rcItem.top && event.ptMouse.x < m_rcItem.right && event.ptMouse.y < m_rcItem.top + m_nPalletHeight) { int x = (event.ptMouse.x - m_rcItem.left) * 360 / (m_rcItem.right - m_rcItem.left); int y = (event.ptMouse.y - m_rcItem.top) * 200 / m_nPalletHeight; x = min(max(x, 0), 360); y = min(max(y, 0), 200); m_ptLastPalletMouse = event.ptMouse; if (m_ptLastPalletMouse.x < m_rcItem.left) m_ptLastPalletMouse.x = m_rcItem.left; if (m_ptLastPalletMouse.x > m_rcItem.right) m_ptLastPalletMouse.x = m_rcItem.right; if (m_ptLastPalletMouse.y < m_rcItem.top) m_ptLastPalletMouse.y = m_rcItem.top; if (m_ptLastPalletMouse.y > m_rcItem.top + m_nPalletHeight) m_ptLastPalletMouse.y = m_rcItem.top + m_nPalletHeight; m_nCurH = x; m_nCurB = 200 - y; m_uButtonState |= UISTATE_PUSHED; m_bIsInPallet = true; m_bIsInBar = false; UpdateBarData(); } if (event.ptMouse.x >= m_rcItem.left && event.ptMouse.y >= m_rcItem.bottom - m_nBarHeight && event.ptMouse.x < m_rcItem.right && event.ptMouse.y < m_rcItem.bottom) { m_nCurS = (event.ptMouse.x - m_rcItem.left) * 200 / (m_rcItem.right - m_rcItem.left); m_uButtonState |= UISTATE_PUSHED; m_bIsInBar = true; m_bIsInPallet = false; UpdatePalletData(); } Invalidate(); return; } if (event.Type == UIEVENT_BUTTONUP) { DWORD color=0; if ((m_uButtonState | UISTATE_PUSHED) && (IsEnabled())) { color = GetSelectColor(); m_pManager->SendNotify(this, DUI_MSGTYPE_COLORCHANGED, color, 0); } m_uButtonState &= ~UISTATE_PUSHED; m_bIsInPallet = false; m_bIsInBar = false; Invalidate(); return; } if (event.Type == UIEVENT_MOUSEMOVE) { if (!(m_uButtonState &UISTATE_PUSHED)) { m_bIsInBar = false; m_bIsInPallet = false; } if (m_bIsInPallet == true) { POINT pt = event.ptMouse; pt.x -= m_rcItem.left; pt.y -= m_rcItem.top; if (pt.x >= 0 && pt.y >= 0 && pt.x <= m_rcItem.right && pt.y <= m_rcItem.top + m_nPalletHeight) { int x = pt.x * 360 / (m_rcItem.right - m_rcItem.left); int y = pt.y * 200 / m_nPalletHeight; x = min(max(x, 0), 360); y = min(max(y, 0), 200); m_ptLastPalletMouse = event.ptMouse; if (m_ptLastPalletMouse.x < m_rcItem.left) m_ptLastPalletMouse.x = m_rcItem.left; if (m_ptLastPalletMouse.x > m_rcItem.right) m_ptLastPalletMouse.x = m_rcItem.right; if (m_ptLastPalletMouse.y < m_rcItem.top) m_ptLastPalletMouse.y = m_rcItem.top; if (m_ptLastPalletMouse.y >= m_rcItem.top + m_nPalletHeight) m_ptLastPalletMouse.y = m_rcItem.top + m_nPalletHeight; m_nCurH = x; m_nCurB = 200 - y; UpdateBarData(); } } else if (m_bIsInBar == true) { m_nCurS = (event.ptMouse.x - m_rcItem.left) * 200 / (m_rcItem.right - m_rcItem.left); m_nCurS = min(max(m_nCurS, 0), 200); UpdatePalletData(); } Invalidate(); return; } } void CColorPaletteUI::PaintBkColor(HDC hDC) { PaintPallet(hDC); } void CColorPaletteUI::PaintPallet(HDC hDC) { int nSaveDC = ::SaveDC(hDC); ::SetStretchBltMode(hDC, HALFTONE); //拉伸模式将内存图画到控件上 StretchBlt(hDC, m_rcItem.left, m_rcItem.top, m_rcItem.right - m_rcItem.left, m_nPalletHeight, m_MemDc, 0, 1, 360, 200, SRCCOPY); StretchBlt(hDC, m_rcItem.left, m_rcItem.bottom - m_nBarHeight, m_rcItem.right - m_rcItem.left, m_nBarHeight, m_MemDc, 0, 210, 200, m_nBarHeight, SRCCOPY); RECT rcCurSorPaint = { m_ptLastPalletMouse.x - 4, m_ptLastPalletMouse.y - 4, m_ptLastPalletMouse.x + 4, m_ptLastPalletMouse.y + 4 }; CRenderEngine::DrawImageString(hDC, m_pManager, rcCurSorPaint, m_rcPaint, m_strThumbImage); rcCurSorPaint.left = m_rcItem.left + m_nCurS * (m_rcItem.right - m_rcItem.left) / 200 - 4; rcCurSorPaint.right = m_rcItem.left + m_nCurS * (m_rcItem.right - m_rcItem.left) / 200 + 4; rcCurSorPaint.top = m_rcItem.bottom - m_nBarHeight / 2 - 4; rcCurSorPaint.bottom = m_rcItem.bottom - m_nBarHeight / 2 + 4; CRenderEngine::DrawImageString(hDC, m_pManager, rcCurSorPaint, m_rcPaint, m_strThumbImage); ::RestoreDC(hDC, nSaveDC); } void CColorPaletteUI::UpdatePalletData() { int x, y; BYTE *pPiexl; DWORD dwColor; for (y = 0; y < 200; ++y) { for (x = 0; x < 360; ++x) { pPiexl = LPBYTE(m_pBits) + ((200 - y)*m_bmInfo.bmWidthBytes) + ((x*m_bmInfo.bmBitsPixel) / 8); dwColor = _HSLToRGB(x, m_nCurS, y); if(dwColor == 0xFF000000) dwColor = 0xFF000001; pPiexl[0] = GetBValue(dwColor); pPiexl[1] = GetGValue(dwColor); pPiexl[2] = GetRValue(dwColor); } } SetBitmapBits(m_hMemBitmap, m_bmInfo.bmWidthBytes * m_bmInfo.bmHeight, m_pBits); } void CColorPaletteUI::UpdateBarData() { int x, y; BYTE *pPiexl; DWORD dwColor; //这里画出Bar for (y = 0; y < m_nBarHeight; ++y) { for (x = 0; x < 200; ++x) { pPiexl = LPBYTE(m_pBits) + ((210 + y)*m_bmInfo.bmWidthBytes) + ((x*m_bmInfo.bmBitsPixel) / 8); dwColor = _HSLToRGB(m_nCurH, x, m_nCurB); if(dwColor == 0xFF000000) dwColor = 0xFF000001; pPiexl[0] = GetBValue(dwColor); pPiexl[1] = GetGValue(dwColor); pPiexl[2] = GetRValue(dwColor); } } SetBitmapBits(m_hMemBitmap, m_bmInfo.bmWidthBytes * m_bmInfo.bmHeight, m_pBits); } }