|
|
/*++
Copyright (c) 1990-1998, Microsoft Corporation All rights reserved.
Module Name:
color2.c
Abstract:
This module implements the support for the Win32 color dialog.
Revision History:
--*/
// precompiled headers
#include "precomp.h"
#pragma hdrstop
#include "color.h"
// from pwin32.h
#define MMoveTo(hdc, x, y) MoveToEx(hdc, x, y, NULL)
////////////////////////////////////////////////////////////////////////////
//
// ChangeColorSettings
//
// Updates color shown.
//
////////////////////////////////////////////////////////////////////////////
VOID ChangeColorSettings( register PCOLORINFO pCI) { register HDC hDC; HWND hDlg = pCI->hDialog; DWORD dwRGBcolor = pCI->currentRGB;
RGBtoHLS(dwRGBcolor); if (gLum != pCI->currentLum) { hDC = GetDC(hDlg); EraseLumArrow(hDC, pCI); pCI->currentLum = gLum; HLStoHLSPos(COLOR_LUM, pCI); LumArrowPaint(hDC, pCI->nLumPos, pCI); ReleaseDC(hDlg, hDC); } if ((gHue != pCI->currentHue) || (gSat != pCI->currentSat)) { pCI->currentHue = gHue; pCI->currentSat = gSat; InvalidateRect(hDlg, (LPRECT)&pCI->rLumPaint, FALSE); hDC = GetDC(hDlg); EraseCrossHair(hDC, pCI); HLStoHLSPos(COLOR_HUE, pCI); HLStoHLSPos(COLOR_SAT, pCI); CrossHairPaint(hDC, pCI->nHuePos, pCI->nSatPos, pCI); ReleaseDC(hDlg, hDC); } }
////////////////////////////////////////////////////////////////////////////
//
// LumArrowPaint
//
////////////////////////////////////////////////////////////////////////////
VOID LumArrowPaint( HDC hDC, SHORT y, PCOLORINFO pCI) { HBRUSH hBrush; int x, h;
hBrush = SelectObject(hDC, GetSysColorBrush(COLOR_BTNTEXT));
for (x = pCI->rLumScroll.left + 2, h = 1; x < pCI->rLumScroll.right - 2; x++, h += 2) { PatBlt(hDC, x, y - h / 2, 1, h, PATCOPY); }
SelectObject(hDC, hBrush); }
////////////////////////////////////////////////////////////////////////////
//
// EraseLumArrow
//
////////////////////////////////////////////////////////////////////////////
VOID EraseLumArrow( HDC hDC, PCOLORINFO pCI) { HBRUSH hBrush; RECT Rect;
hBrush = (HBRUSH)SendMessage( pCI->hDialog, WM_CTLCOLORDLG, (WPARAM)hDC, (LPARAM)pCI->hDialog );
Rect.left = pCI->rLumScroll.left + 1; Rect.right = pCI->rLumScroll.right; Rect.top = pCI->nLumPos - (pCI->rLumScroll.right - pCI->rLumScroll.left); Rect.bottom = pCI->nLumPos + (pCI->rLumScroll.right - pCI->rLumScroll.left) + 1;
FillRect(hDC, &Rect, hBrush); }
////////////////////////////////////////////////////////////////////////////
//
// EraseCrossHair
//
////////////////////////////////////////////////////////////////////////////
VOID EraseCrossHair( HDC hDC, PCOLORINFO pCI) { HBITMAP hOldBitmap; WORD distancex, distancey; WORD topy, bottomy, leftx, rightx; RECT rRainbow;
CopyRect(&rRainbow, &pCI->rRainbow);
distancex = (WORD)(10 * cxBorder); distancey = (WORD)(10 * cyBorder); topy = ((WORD)rRainbow.top > pCI->nSatPos - distancey) ? (WORD)rRainbow.top : pCI->nSatPos - distancey; bottomy = ((WORD)rRainbow.bottom < pCI->nSatPos + distancey) ? (WORD)rRainbow.bottom : pCI->nSatPos + distancey; leftx = ((WORD)rRainbow.left > pCI->nHuePos - distancex) ? (WORD)rRainbow.left : pCI->nHuePos - distancex; rightx = ((WORD)rRainbow.right < pCI->nHuePos + distancex) ? (WORD)rRainbow.right : pCI->nHuePos + distancex;
hOldBitmap = SelectObject(hDCFastBlt, hRainbowBitmap); BitBlt( hDC, leftx, topy, rightx - leftx, bottomy - topy, hDCFastBlt, leftx - (WORD)rRainbow.left, topy - (WORD)rRainbow.top, SRCCOPY ); SelectObject(hDCFastBlt, hOldBitmap); }
////////////////////////////////////////////////////////////////////////////
//
// CrossHairPaint
//
////////////////////////////////////////////////////////////////////////////
VOID CrossHairPaint( register HDC hDC, SHORT x, SHORT y, PCOLORINFO pCI) { SHORT distancex, distancey; SHORT topy, bottomy, topy2, bottomy2; SHORT leftx, rightx, leftx2, rightx2; RECT rRainbow;
CopyRect(&rRainbow, &pCI->rRainbow); distancex = (SHORT)(5 * cxBorder); distancey = (SHORT)(5 * cyBorder); topy = (SHORT)((rRainbow.top > y - 2 * distancey) ? rRainbow.top : y - 2 * distancey); bottomy = (SHORT)((rRainbow.bottom < y + 2 * distancey) ? rRainbow.bottom : y + 2 * distancey); leftx = (SHORT)((rRainbow.left > x - 2 * distancex) ? rRainbow.left : x - 2 * distancex); rightx = (SHORT)((rRainbow.right < x + 2 * distancex) ? rRainbow.right : x + 2 * distancex); topy2 = (SHORT)((rRainbow.top > y - distancey) ? rRainbow.top : y - distancey); bottomy2 = (SHORT)((rRainbow.bottom < y + distancey) ? rRainbow.bottom : y + distancey); leftx2 = (SHORT)((rRainbow.left > x - distancex) ? rRainbow.left : x - distancex); rightx2 = (SHORT)((rRainbow.right < x + distancex) ? rRainbow.right : x + distancex); if (rRainbow.top < topy2) { if ((x - 1) >= rRainbow.left) { MMoveTo(hDC, x - 1, topy2); LineTo(hDC, x - 1, topy); } if ((int)x < rRainbow.right) { MMoveTo(hDC, x, topy2); LineTo(hDC, x, topy); } if ((x + 1) < rRainbow.right) { MMoveTo(hDC, x + 1, topy2); LineTo(hDC, x + 1, topy); } } if (rRainbow.bottom > bottomy2) { if ((x - 1) >= rRainbow.left) { MMoveTo(hDC, x - 1, bottomy2); LineTo(hDC, x - 1, bottomy); } if ((int)x < rRainbow.right) { MMoveTo(hDC, x, bottomy2); LineTo(hDC, x, bottomy); } if ((x + 1) < rRainbow.right) { MMoveTo(hDC, x + 1, bottomy2); LineTo(hDC, x + 1, bottomy); } } if (rRainbow.left < leftx2) { if ((y - 1) >= rRainbow.top) { MMoveTo(hDC, leftx2, y - 1); LineTo(hDC, leftx, y - 1); } if ((int)y < rRainbow.bottom) { MMoveTo(hDC, leftx2, y); LineTo(hDC, leftx, y); } if ((y + 1) < rRainbow.bottom) { MMoveTo(hDC, leftx2, y + 1); LineTo(hDC, leftx, y + 1); } } if (rRainbow.right > rightx2) { if ((y - 1) >= rRainbow.top) { MMoveTo(hDC, rightx2, y - 1); LineTo(hDC, rightx, y - 1); } if ((int)y < rRainbow.bottom) { MMoveTo(hDC, rightx2, y); LineTo(hDC, rightx, y); } if ((y + 1) < rRainbow.bottom) { MMoveTo(hDC, rightx2, y + 1); LineTo(hDC, rightx, y + 1); } } }
////////////////////////////////////////////////////////////////////////////
//
// NearestSolid
//
////////////////////////////////////////////////////////////////////////////
VOID NearestSolid( register PCOLORINFO pCI) { register HDC hDC; HWND hDlg = pCI->hDialog;
hDC = GetDC(hDlg); EraseCrossHair(hDC, pCI); EraseLumArrow(hDC, pCI); RGBtoHLS(pCI->currentRGB = GetNearestColor(hDC, pCI->currentRGB)); pCI->currentHue = gHue; pCI->currentLum = gLum; pCI->currentSat = gSat; HLStoHLSPos(0, pCI); CrossHairPaint(hDC, pCI->nHuePos, pCI->nSatPos, pCI); LumArrowPaint(hDC, pCI->nLumPos, pCI); ReleaseDC(hDlg, hDC); SetHLSEdit(0, pCI); SetRGBEdit(0, pCI); InvalidateRect(hDlg, (LPRECT)&pCI->rColorSamples, FALSE); InvalidateRect(hDlg, (LPRECT)&pCI->rLumPaint, FALSE); }
////////////////////////////////////////////////////////////////////////////
//
// HLSPostoHLS
//
////////////////////////////////////////////////////////////////////////////
VOID HLSPostoHLS( SHORT nHLSEdit, register PCOLORINFO pCI) { switch (nHLSEdit) { case COLOR_HUE: { pCI->currentHue = (WORD)((pCI->nHuePos - pCI->rRainbow.left) * (RANGE - 1) / (pCI->nHueWidth - 1)); break; } case COLOR_SAT: { pCI->currentSat = (WORD)(RANGE - (pCI->nSatPos - pCI->rRainbow.top) * RANGE / (pCI->nSatHeight - 1)); break; } case COLOR_LUM: { pCI->currentLum = (WORD)(RANGE - (pCI->nLumPos - pCI->rLumPaint.top) * RANGE / (pCI->nLumHeight - 1)); break; } default: { pCI->currentHue = (WORD)((pCI->nHuePos - pCI->rRainbow.left) * (RANGE - 1) / pCI->nHueWidth); pCI->currentSat = (WORD)(RANGE - (pCI->nSatPos - pCI->rRainbow.top) * RANGE / pCI->nSatHeight); pCI->currentLum = (WORD)(RANGE - (pCI->nLumPos - pCI->rLumPaint.top) * RANGE / pCI->nLumHeight); break; } } }
////////////////////////////////////////////////////////////////////////////
//
// HLStoHLSPos
//
////////////////////////////////////////////////////////////////////////////
VOID HLStoHLSPos( SHORT nHLSEdit, register PCOLORINFO pCI) { switch (nHLSEdit) { case ( COLOR_HUE ) : { pCI->nHuePos = (WORD)(pCI->rRainbow.left + pCI->currentHue * pCI->nHueWidth / (RANGE - 1)); break; } case COLOR_SAT: { pCI->nSatPos = (WORD)(pCI->rRainbow.top + (RANGE - pCI->currentSat) * (pCI->nSatHeight - 1) / RANGE); break; } case COLOR_LUM: { pCI->nLumPos = (WORD)(pCI->rLumPaint.top + (RANGE - pCI->currentLum) * (pCI->nLumHeight - 1) / RANGE); break; } default: { pCI->nHuePos = (WORD)(pCI->rRainbow.left + pCI->currentHue * pCI->nHueWidth / (RANGE - 1)); pCI->nSatPos = (WORD)(pCI->rRainbow.top + (RANGE - pCI->currentSat) * (pCI->nSatHeight - 1) / RANGE); pCI->nLumPos = (WORD)(pCI->rLumPaint.top + (RANGE - pCI->currentLum) * (pCI->nLumHeight - 1) / RANGE); break; } } }
////////////////////////////////////////////////////////////////////////////
//
// SetHLSEdit
//
////////////////////////////////////////////////////////////////////////////
VOID SetHLSEdit( SHORT nHLSEdit, register PCOLORINFO pCI) { register HWND hRainbowDlg = pCI->hDialog;
switch (nHLSEdit) { case ( COLOR_HUE ) : { SetDlgItemInt(hRainbowDlg, COLOR_HUE, pCI->currentHue, FALSE); break; } case ( COLOR_SAT ) : { SetDlgItemInt(hRainbowDlg, COLOR_SAT, pCI->currentSat, FALSE); break; } case ( COLOR_LUM ) : { SetDlgItemInt(hRainbowDlg, COLOR_LUM, pCI->currentLum, FALSE); break; } default : { SetDlgItemInt(hRainbowDlg, COLOR_HUE, pCI->currentHue, FALSE); SetDlgItemInt(hRainbowDlg, COLOR_SAT, pCI->currentSat, FALSE); SetDlgItemInt(hRainbowDlg, COLOR_LUM, pCI->currentLum, FALSE); break; } } }
////////////////////////////////////////////////////////////////////////////
//
// SetRGBEdit
//
////////////////////////////////////////////////////////////////////////////
VOID SetRGBEdit( SHORT nRGBEdit, PCOLORINFO pCI) { register HWND hRainbowDlg = pCI->hDialog; DWORD rainbowRGB = pCI->currentRGB;
switch (nRGBEdit) { case ( COLOR_RED ) : { SetDlgItemInt(hRainbowDlg, COLOR_RED, GetRValue(rainbowRGB), FALSE); break; } case ( COLOR_GREEN ) : { SetDlgItemInt(hRainbowDlg, COLOR_GREEN, GetGValue(rainbowRGB), FALSE); break; } case ( COLOR_BLUE ) : { SetDlgItemInt(hRainbowDlg, COLOR_BLUE, GetBValue(rainbowRGB), FALSE); break; } default : { SetDlgItemInt(hRainbowDlg, COLOR_RED, GetRValue(rainbowRGB), FALSE); SetDlgItemInt(hRainbowDlg, COLOR_GREEN, GetGValue(rainbowRGB), FALSE); SetDlgItemInt(hRainbowDlg, COLOR_BLUE, GetBValue(rainbowRGB), FALSE); break; } } }
////////////////////////////////////////////////////////////////////////////
//
// InitRainbow
//
// Returns TRUE iff we make it.
//
////////////////////////////////////////////////////////////////////////////
BOOL InitRainbow( register PCOLORINFO pCI) { HDC hDC; WORD Sat, Hue; HBITMAP hOldBitmap; RECT Rect; HBRUSH hbrSwipe; WORD nHueWidth, nSatHeight; register HWND hRainbowDlg = pCI->hDialog;
RGBtoHLS(pCI->currentRGB);
SetupRainbowCapture(pCI);
nHueWidth = pCI->nHueWidth = (WORD)(pCI->rRainbow.right - pCI->rRainbow.left); nSatHeight = pCI->nSatHeight = (WORD)(pCI->rRainbow.bottom - pCI->rRainbow.top);
pCI->currentHue = gHue; pCI->currentSat = gSat; pCI->currentLum = gLum;
HLStoHLSPos(0, pCI); SetRGBEdit(0, pCI); SetHLSEdit(0, pCI);
if (!hRainbowBitmap) { hDC = GetDC(hRainbowDlg); hRainbowBitmap = CreateCompatibleBitmap(hDC, nHueWidth, nSatHeight); if (!hRainbowBitmap) { return (FALSE); } }
hOldBitmap = SelectObject(hDCFastBlt, hRainbowBitmap);
//
// NOTE: The final pass through this loop paints on and past the end
// of the selected bitmap. Windows is a good product, and doesn't
// let such foolishness happen.
//
Rect.bottom = 0; for (Sat = RANGE; Sat > 0; Sat -= SATINC) { Rect.top = Rect.bottom; Rect.bottom = (nSatHeight * RANGE - (Sat - SATINC) * nSatHeight) / RANGE; Rect.right = 0;
for (Hue = 0; Hue < (RANGE - 1); Hue += HUEINC) { Rect.left = Rect.right; Rect.right = ((Hue + HUEINC) * nHueWidth) / RANGE; hbrSwipe = CreateSolidBrush(HLStoRGB(Hue, RANGE / 2, Sat)); FillRect(hDCFastBlt, &Rect, hbrSwipe); DeleteObject(hbrSwipe); } }
SelectObject(hDCFastBlt, hOldBitmap); ReleaseDC(hRainbowDlg, hDC);
UpdateWindow(hRainbowDlg);
return (TRUE); }
////////////////////////////////////////////////////////////////////////////
//
// PaintRainbow
//
////////////////////////////////////////////////////////////////////////////
VOID PaintRainbow( HDC hDC, LPRECT lpRect, register PCOLORINFO pCI) { HBITMAP hOldBitmap;
if (!hRainbowBitmap) { return; } hOldBitmap = SelectObject(hDCFastBlt, hRainbowBitmap); BitBlt( hDC, lpRect->left, lpRect->top, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top, hDCFastBlt, lpRect->left - pCI->rRainbow.left, lpRect->top - pCI->rRainbow.top, SRCCOPY ); SelectObject(hDCFastBlt, hOldBitmap); CrossHairPaint(hDC, pCI->nHuePos, pCI->nSatPos, pCI); UpdateWindow(pCI->hDialog); }
////////////////////////////////////////////////////////////////////////////
//
// RainbowPaint
//
////////////////////////////////////////////////////////////////////////////
void RainbowPaint( register PCOLORINFO pCI, HDC hDC, LPRECT lpPaintRect) { WORD Lum; RECT Rect; HBRUSH hbrSwipe;
//
// Paint the Current Color Sample.
//
if (IntersectRect((LPRECT)&Rect, lpPaintRect, (LPRECT)&(pCI->rCurrentColor))) { hbrSwipe = CreateSolidBrush(pCI->currentRGB); FillRect(hDC, (LPRECT)&Rect, hbrSwipe); DeleteObject(hbrSwipe); }
//
// Paint the Nearest Pure Color Sample.
//
if (IntersectRect((LPRECT)&Rect, lpPaintRect, (LPRECT)&(pCI->rNearestPure))) { hbrSwipe = CreateSolidBrush(GetNearestColor(hDC, pCI->currentRGB)); FillRect(hDC, (LPRECT)&Rect, hbrSwipe); DeleteObject(hbrSwipe); }
//
// Paint the Luminosity Range.
//
if (IntersectRect((LPRECT)&Rect, lpPaintRect, (LPRECT)&(pCI->rLumPaint))) { Rect.left = pCI->rLumPaint.left; Rect.right = pCI->rLumPaint.right; Rect.top = pCI->rLumPaint.bottom - LUMINC / 2; Rect.bottom = pCI->rLumPaint.bottom; hbrSwipe = CreateSolidBrush(HLStoRGB( pCI->currentHue, 0, pCI->currentSat )); FillRect(hDC, (LPRECT)&Rect, hbrSwipe); DeleteObject(hbrSwipe); for (Lum = LUMINC; Lum < RANGE; Lum += LUMINC) { Rect.bottom = Rect.top; Rect.top = (((pCI->rLumPaint.bottom + LUMINC / 2) * (DWORD)RANGE - (Lum + LUMINC) * pCI->nLumHeight) / RANGE); hbrSwipe = CreateSolidBrush(HLStoRGB( pCI->currentHue, Lum, pCI->currentSat )); FillRect(hDC, (LPRECT)&Rect, hbrSwipe); DeleteObject(hbrSwipe); } Rect.bottom = Rect.top; Rect.top = pCI->rLumPaint.top; hbrSwipe = CreateSolidBrush(HLStoRGB( pCI->currentHue, RANGE, pCI->currentSat )); FillRect(hDC, (LPRECT)&Rect, hbrSwipe); DeleteObject(hbrSwipe);
//
// Paint the bounding rectangle only when it might be necessary.
//
if (!EqualRect(lpPaintRect, (LPRECT)&pCI->rLumPaint)) { hbrSwipe = SelectObject(hDC, GetStockObject(NULL_BRUSH)); Rectangle( hDC, pCI->rLumPaint.left - 1, pCI->rLumPaint.top - 1, pCI->rLumPaint.right + 1, pCI->rLumPaint.bottom + 1 ); SelectObject(hDC, hbrSwipe); } }
//
// Paint the Luminosity Arrow.
//
if (IntersectRect((LPRECT)&Rect, lpPaintRect, (LPRECT)&pCI->rLumScroll)) { LumArrowPaint(hDC, pCI->nLumPos, pCI); }
if (IntersectRect((LPRECT)&Rect, lpPaintRect, (LPRECT)&pCI->rRainbow)) { PaintRainbow(hDC, (LPRECT)&Rect, pCI); } }
////////////////////////////////////////////////////////////////////////////
//
// Color conversion routines --
//
// RGBtoHLS() takes a DWORD RGB value, translates it to HLS, and stores the
// results in the global vars H, L, and S. HLStoRGB takes the current values
// of H, L, and S and returns the equivalent value in an RGB DWORD. The vars
// H, L and S are written to only by 1) RGBtoHLS (initialization) or 2) the
// scrollbar handlers.
//
// A point of reference for the algorithms is Foley and Van Dam, pp. 618-19.
// Their algorithm is in floating point.
//
// There are potential roundoff errors lurking throughout here.
// (0.5 + x/y) without floating point,
// (x / y) phrased ((x + (y / 2)) / y) yields very small roundoff error.
// This makes many of the following divisions look funny.
//
//
// H,L, and S vary over 0 - HLSMAX.
// R,G, and B vary over 0 - RGBMAX.
// HLSMAX BEST IF DIVISIBLE BY 6.
// RGBMAX, HLSMAX must each fit in a byte.
//
// Hue is undefined if Saturation is 0 (grey-scale).
// This value determines where the Hue scrollbar is initially set for
// achromatic colors.
//
////////////////////////////////////////////////////////////////////////////
#define UNDEFINED (HLSMAX * 2 / 3)
////////////////////////////////////////////////////////////////////////////
//
// RGBtoHLS
//
////////////////////////////////////////////////////////////////////////////
VOID RGBtoHLS( DWORD lRGBColor) { WORD R, G, B; // input RGB values
WORD cMax,cMin; // max and min RGB values
WORD cSum,cDif; SHORT Rdelta, Gdelta, Bdelta; // intermediate value: % of spread from max
//
// get R, G, and B out of DWORD.
//
R = GetRValue(lRGBColor); G = GetGValue(lRGBColor); B = GetBValue(lRGBColor);
//
// Calculate lightness.
//
cMax = max(max(R, G), B); cMin = min(min(R, G), B); cSum = cMax + cMin; gLum = (WORD)(((cSum * (DWORD)HLSMAX) + RGBMAX) / (2 * RGBMAX));
cDif = cMax - cMin; if (!cDif) { //
// r = g = b --> Achromatic case.
//
gSat = 0; // saturation
gHue = UNDEFINED; // hue
} else { //
// Chromatic case.
//
//
// Saturation.
//
// Note: Division by cSum is not a problem, as cSum can only
// be 0 if the RGB value is 0L, and that is achromatic.
//
if (gLum <= (HLSMAX / 2)) { gSat = (WORD)(((cDif * (DWORD) HLSMAX) + (cSum / 2) ) / cSum); } else { gSat = (WORD)((DWORD)((cDif * (DWORD)HLSMAX) + (DWORD)((2 * RGBMAX - cSum) / 2)) / (2 * RGBMAX - cSum)); }
//
// Hue.
//
Rdelta = (SHORT)((((cMax - R) * (DWORD)(HLSMAX / 6)) + (cDif / 2) ) / cDif); Gdelta = (SHORT)((((cMax - G) * (DWORD)(HLSMAX / 6)) + (cDif / 2) ) / cDif); Bdelta = (SHORT)((((cMax - B) * (DWORD)(HLSMAX / 6)) + (cDif / 2) ) / cDif);
if (R == cMax) { gHue = Bdelta - Gdelta; } else if (G == cMax) { gHue = (WORD)((HLSMAX / 3) + Rdelta - Bdelta); } else // (B == cMax)
{ gHue = (WORD)(((2 * HLSMAX) / 3) + Gdelta - Rdelta); }
if ((short)gHue < 0) { //
// This can occur when R == cMax and G is > B.
//
gHue += HLSMAX; } if (gHue >= HLSMAX) { gHue -= HLSMAX; } } }
////////////////////////////////////////////////////////////////////////////
//
// HueToRGB
//
// Utility routine for HLStoRGB.
//
////////////////////////////////////////////////////////////////////////////
WORD HueToRGB( WORD n1, WORD n2, WORD hue) { if (hue >= HLSMAX) { hue -= HLSMAX; }
//
// Return r, g, or b value from this tridrant.
//
if (hue < (HLSMAX / 6)) { return ((WORD)(n1 + (((n2 - n1) * hue + (HLSMAX / 12)) / (HLSMAX / 6)))); } if (hue < (HLSMAX/2)) { return (n2); } if (hue < ((HLSMAX*2)/3)) { return ((WORD)(n1 + (((n2 - n1) * (((HLSMAX * 2) / 3) - hue) + (HLSMAX / 12)) / (HLSMAX / 6)))); } else { return (n1); } }
////////////////////////////////////////////////////////////////////////////
//
// HLStoRGB
//
////////////////////////////////////////////////////////////////////////////
DWORD HLStoRGB( WORD hue, WORD lum, WORD sat) { WORD R, G, B; // RGB component values
WORD Magic1, Magic2; // calculated magic numbers
if (sat == 0) { //
// Achromatic case.
//
R = G = B = (WORD)((lum * RGBMAX) / HLSMAX); } else { //
// Chromatic case
//
//
// Set up magic numbers.
//
if (lum <= (HLSMAX / 2)) { Magic2 = (WORD)((lum * ((DWORD)HLSMAX + sat) + (HLSMAX / 2)) / HLSMAX); } else { Magic2 = lum + sat - (WORD)(((lum * sat) + (DWORD)(HLSMAX / 2)) / HLSMAX); } Magic1 = (WORD)(2 * lum - Magic2);
//
// Get RGB, change units from HLSMAX to RGBMAX.
//
R = (WORD)(((HueToRGB(Magic1, Magic2, (WORD)(hue + (HLSMAX / 3))) * (DWORD)RGBMAX + (HLSMAX / 2))) / HLSMAX); G = (WORD)(((HueToRGB(Magic1, Magic2, hue) * (DWORD)RGBMAX + (HLSMAX / 2))) / HLSMAX); B = (WORD)(((HueToRGB(Magic1, Magic2, (WORD)(hue - (HLSMAX / 3))) * (DWORD)RGBMAX + (HLSMAX / 2))) / HLSMAX); } return (RGB(R, G, B)); }
////////////////////////////////////////////////////////////////////////////
//
// RGBEditChange
//
// Checks the edit box for a valid entry and updates the Hue, Sat, and Lum
// edit controls if appropriate. Also updates Lum picture and current
// color sample.
//
// nDlgID - Dialog ID of Red, Green or Blue edit control.
//
////////////////////////////////////////////////////////////////////////////
SHORT RGBEditChange( SHORT nDlgID, PCOLORINFO pCI) { BOOL bOK; // check that value in edit control is uint
BYTE *currentValue; // pointer to byte in RGB to change (or reset)
SHORT nVal; TCHAR cEdit[3]; register HWND hDlg = pCI->hDialog;
currentValue = (BYTE *)&pCI->currentRGB; switch (nDlgID) { case ( COLOR_GREEN ) : { currentValue++; break; } case ( COLOR_BLUE ) : { currentValue += 2; break; } } nVal = (SHORT)GetDlgItemInt(hDlg, nDlgID, (BOOL FAR *)&bOK, FALSE); if (bOK) { if (nVal > RGBMAX) { nVal = RGBMAX; SetDlgItemInt(hDlg, nDlgID, nVal, FALSE); } if (nVal != (SHORT) *currentValue) { *currentValue = LOBYTE(nVal); ChangeColorSettings(pCI); SetHLSEdit(nDlgID, pCI); } } else if (GetDlgItemText(hDlg, nDlgID, (LPTSTR)cEdit, 2)) { SetRGBEdit(nDlgID, pCI); SendDlgItemMessage(hDlg, nDlgID, EM_SETSEL, (WPARAM)0, (LPARAM)-1); } return (SHORT)(bOK ? TRUE : FALSE); }
|