color2.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 28k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. /*++
  2. Copyright (c) 1990-1998,  Microsoft Corporation  All rights reserved.
  3. Module Name:
  4.     color2.c
  5. Abstract:
  6.     This module implements the support for the Win32 color dialog.
  7. Revision History:
  8. --*/
  9. //
  10. //  Include Files.
  11. //
  12. #include "comdlg32.h"
  13. #include "color.h"
  14. // from pwin32.h
  15. #define MMoveTo(hdc, x, y)        MoveToEx(hdc, x, y, NULL)
  16. ////////////////////////////////////////////////////////////////////////////
  17. //
  18. //  ChangeColorSettings
  19. //
  20. //  Updates color shown.
  21. //
  22. ////////////////////////////////////////////////////////////////////////////
  23. VOID ChangeColorSettings(
  24.     register PCOLORINFO pCI)
  25. {
  26.     register HDC hDC;
  27.     HWND hDlg = pCI->hDialog;
  28.     DWORD dwRGBcolor = pCI->currentRGB;
  29.     RGBtoHLS(dwRGBcolor);
  30.     if (gLum != pCI->currentLum)
  31.     {
  32.         hDC = GetDC(hDlg);
  33.         EraseLumArrow(hDC, pCI);
  34.         pCI->currentLum = gLum;
  35.         HLStoHLSPos(COLOR_LUM, pCI);
  36.         LumArrowPaint(hDC, pCI->nLumPos, pCI);
  37.         ReleaseDC(hDlg, hDC);
  38.     }
  39.     if ((gHue != pCI->currentHue) || (gSat != pCI->currentSat))
  40.     {
  41.         pCI->currentHue = gHue;
  42.         pCI->currentSat = gSat;
  43.         InvalidateRect(hDlg, (LPRECT)&pCI->rLumPaint, FALSE);
  44.         hDC = GetDC(hDlg);
  45.         EraseCrossHair(hDC, pCI);
  46.         HLStoHLSPos(COLOR_HUE, pCI);
  47.         HLStoHLSPos(COLOR_SAT, pCI);
  48.         CrossHairPaint(hDC, pCI->nHuePos, pCI->nSatPos, pCI);
  49.         ReleaseDC(hDlg, hDC);
  50.     }
  51. }
  52. ////////////////////////////////////////////////////////////////////////////
  53. //
  54. //  LumArrowPaint
  55. //
  56. ////////////////////////////////////////////////////////////////////////////
  57. VOID LumArrowPaint(
  58.     HDC hDC,
  59.     SHORT y,
  60.     PCOLORINFO pCI)
  61. {
  62.     HBRUSH hBrush;
  63.     int x, h;
  64.     hBrush = SelectObject(hDC, GetSysColorBrush(COLOR_BTNTEXT));
  65.     for (x = pCI->rLumScroll.left + 2, h = 1;
  66.          x < pCI->rLumScroll.right - 2;
  67.          x++, h += 2)
  68.     {
  69.         PatBlt(hDC, x, y - h / 2, 1, h, PATCOPY);
  70.     }
  71.     SelectObject(hDC, hBrush);
  72. }
  73. ////////////////////////////////////////////////////////////////////////////
  74. //
  75. //  EraseLumArrow
  76. //
  77. ////////////////////////////////////////////////////////////////////////////
  78. VOID EraseLumArrow(
  79.     HDC hDC,
  80.     PCOLORINFO pCI)
  81. {
  82.     HBRUSH hBrush;
  83.     RECT Rect;
  84.     hBrush = (HBRUSH)SendMessage( pCI->hDialog,
  85.                                   WM_CTLCOLORDLG,
  86.                                   (WPARAM)hDC,
  87.                                   (LPARAM)pCI->hDialog );
  88.     Rect.left   = pCI->rLumScroll.left + 1;
  89.     Rect.right  = pCI->rLumScroll.right;
  90.     Rect.top    = pCI->nLumPos - (pCI->rLumScroll.right - pCI->rLumScroll.left);
  91.     Rect.bottom = pCI->nLumPos + (pCI->rLumScroll.right - pCI->rLumScroll.left) + 1;
  92.     FillRect(hDC, &Rect, hBrush);
  93. }
  94. ////////////////////////////////////////////////////////////////////////////
  95. //
  96. //  EraseCrossHair
  97. //
  98. ////////////////////////////////////////////////////////////////////////////
  99. VOID EraseCrossHair(
  100.     HDC hDC,
  101.     PCOLORINFO pCI)
  102. {
  103.     HBITMAP hOldBitmap;
  104.     WORD distancex, distancey;
  105.     WORD topy, bottomy, leftx, rightx;
  106.     RECT rRainbow;
  107.     CopyRect(&rRainbow, &pCI->rRainbow);
  108.     distancex = (WORD)(10 * cxBorder);
  109.     distancey = (WORD)(10 * cyBorder);
  110.     topy    = ((WORD)rRainbow.top > pCI->nSatPos - distancey)
  111.                   ? (WORD)rRainbow.top
  112.                   : pCI->nSatPos - distancey;
  113.     bottomy = ((WORD)rRainbow.bottom < pCI->nSatPos + distancey)
  114.                   ? (WORD)rRainbow.bottom
  115.                   : pCI->nSatPos + distancey;
  116.     leftx   = ((WORD)rRainbow.left > pCI->nHuePos - distancex)
  117.                   ? (WORD)rRainbow.left
  118.                   : pCI->nHuePos - distancex;
  119.     rightx  = ((WORD)rRainbow.right < pCI->nHuePos + distancex)
  120.                   ? (WORD)rRainbow.right
  121.                   : pCI->nHuePos + distancex;
  122.     hOldBitmap = SelectObject(hDCFastBlt, hRainbowBitmap);
  123.     BitBlt( hDC,
  124.             leftx,
  125.             topy,
  126.             rightx - leftx,
  127.             bottomy - topy,
  128.             hDCFastBlt,
  129.             leftx - (WORD)rRainbow.left,
  130.             topy - (WORD)rRainbow.top,
  131.             SRCCOPY );
  132.     SelectObject(hDCFastBlt, hOldBitmap);
  133. }
  134. ////////////////////////////////////////////////////////////////////////////
  135. //
  136. //  CrossHairPaint
  137. //
  138. ////////////////////////////////////////////////////////////////////////////
  139. VOID CrossHairPaint(
  140.     register HDC hDC,
  141.     SHORT x,
  142.     SHORT y,
  143.     PCOLORINFO pCI)
  144. {
  145.     SHORT distancex, distancey;
  146.     SHORT topy, bottomy, topy2, bottomy2;
  147.     SHORT leftx, rightx, leftx2, rightx2;
  148.     RECT rRainbow;
  149.     CopyRect(&rRainbow, &pCI->rRainbow);
  150.     distancex = (SHORT)(5 * cxBorder);
  151.     distancey = (SHORT)(5 * cyBorder);
  152.     topy     = (SHORT)((rRainbow.top > y - 2 * distancey)
  153.                          ? rRainbow.top
  154.                          : y - 2 * distancey);
  155.     bottomy  = (SHORT)((rRainbow.bottom < y + 2 * distancey)
  156.                          ? rRainbow.bottom
  157.                          : y + 2 * distancey);
  158.     leftx    = (SHORT)((rRainbow.left > x - 2 * distancex)
  159.                          ? rRainbow.left
  160.                          : x - 2 * distancex);
  161.     rightx   = (SHORT)((rRainbow.right < x + 2 * distancex)
  162.                          ? rRainbow.right
  163.                          : x + 2 * distancex);
  164.     topy2    = (SHORT)((rRainbow.top > y - distancey)
  165.                          ? rRainbow.top
  166.                          : y - distancey);
  167.     bottomy2 = (SHORT)((rRainbow.bottom < y + distancey)
  168.                          ? rRainbow.bottom
  169.                          : y + distancey);
  170.     leftx2 = (SHORT)((rRainbow.left > x - distancex)
  171.                          ? rRainbow.left
  172.                          : x - distancex);
  173.     rightx2 = (SHORT)((rRainbow.right < x + distancex)
  174.                          ? rRainbow.right
  175.                          : x + distancex);
  176.     if (rRainbow.top < topy2)
  177.     {
  178.         if ((x - 1) >= rRainbow.left)
  179.         {
  180.             MMoveTo(hDC, x - 1, topy2);
  181.             LineTo(hDC, x - 1, topy);
  182.         }
  183.         if ((int)x < rRainbow.right)
  184.         {
  185.             MMoveTo(hDC, x, topy2);
  186.             LineTo(hDC, x, topy);
  187.         }
  188.         if ((x + 1) < rRainbow.right)
  189.         {
  190.             MMoveTo(hDC, x + 1, topy2);
  191.             LineTo(hDC, x + 1, topy);
  192.         }
  193.     }
  194.     if (rRainbow.bottom > bottomy2)
  195.     {
  196.         if ((x - 1) >= rRainbow.left)
  197.         {
  198.             MMoveTo(hDC, x - 1, bottomy2);
  199.             LineTo(hDC, x - 1, bottomy);
  200.         }
  201.         if ((int)x < rRainbow.right)
  202.         {
  203.             MMoveTo(hDC, x, bottomy2);
  204.             LineTo(hDC, x, bottomy);
  205.         }
  206.         if ((x + 1) < rRainbow.right)
  207.         {
  208.             MMoveTo(hDC, x + 1, bottomy2);
  209.             LineTo(hDC, x + 1, bottomy);
  210.         }
  211.     }
  212.     if (rRainbow.left < leftx2)
  213.     {
  214.         if ((y - 1) >= rRainbow.top)
  215.         {
  216.             MMoveTo(hDC, leftx2, y - 1);
  217.             LineTo(hDC, leftx, y - 1);
  218.         }
  219.         if ((int)y < rRainbow.bottom)
  220.         {
  221.             MMoveTo(hDC, leftx2, y);
  222.             LineTo(hDC, leftx, y);
  223.         }
  224.         if ((y + 1) < rRainbow.bottom)
  225.         {
  226.             MMoveTo(hDC, leftx2, y + 1);
  227.             LineTo(hDC, leftx, y + 1);
  228.         }
  229.     }
  230.     if (rRainbow.right > rightx2)
  231.     {
  232.         if ((y - 1) >= rRainbow.top)
  233.         {
  234.             MMoveTo(hDC, rightx2, y - 1);
  235.             LineTo(hDC, rightx, y - 1);
  236.         }
  237.         if ((int)y < rRainbow.bottom)
  238.         {
  239.             MMoveTo(hDC, rightx2, y);
  240.             LineTo(hDC, rightx, y);
  241.         }
  242.         if ((y + 1) < rRainbow.bottom)
  243.         {
  244.             MMoveTo(hDC, rightx2, y + 1);
  245.             LineTo(hDC, rightx, y + 1);
  246.         }
  247.     }
  248. }
  249. ////////////////////////////////////////////////////////////////////////////
  250. //
  251. //  NearestSolid
  252. //
  253. ////////////////////////////////////////////////////////////////////////////
  254. VOID NearestSolid(
  255.     register PCOLORINFO pCI)
  256. {
  257.     register HDC hDC;
  258.     HWND hDlg = pCI->hDialog;
  259.     hDC = GetDC(hDlg);
  260.     EraseCrossHair(hDC, pCI);
  261.     EraseLumArrow(hDC, pCI);
  262.     RGBtoHLS(pCI->currentRGB = GetNearestColor(hDC, pCI->currentRGB));
  263.     pCI->currentHue = gHue;
  264.     pCI->currentLum = gLum;
  265.     pCI->currentSat = gSat;
  266.     HLStoHLSPos(0, pCI);
  267.     CrossHairPaint(hDC, pCI->nHuePos, pCI->nSatPos, pCI);
  268.     LumArrowPaint(hDC, pCI->nLumPos, pCI);
  269.     ReleaseDC(hDlg, hDC);
  270.     SetHLSEdit(0, pCI);
  271.     SetRGBEdit(0, pCI);
  272.     InvalidateRect(hDlg, (LPRECT)&pCI->rColorSamples, FALSE);
  273.     InvalidateRect(hDlg, (LPRECT)&pCI->rLumPaint, FALSE);
  274. }
  275. ////////////////////////////////////////////////////////////////////////////
  276. //
  277. //  HLSPostoHLS
  278. //
  279. ////////////////////////////////////////////////////////////////////////////
  280. VOID HLSPostoHLS(
  281.     SHORT nHLSEdit,
  282.     register PCOLORINFO pCI)
  283. {
  284.     switch (nHLSEdit)
  285.     {
  286.         case COLOR_HUE:
  287.         {
  288.             pCI->currentHue = (WORD)((pCI->nHuePos - pCI->rRainbow.left) *
  289.                                      (RANGE - 1) / (pCI->nHueWidth - 1));
  290.             break;
  291.         }
  292.         case COLOR_SAT:
  293.         {
  294.             pCI->currentSat = (WORD)(RANGE -
  295.                                      (pCI->nSatPos - pCI->rRainbow.top) *
  296.                                      RANGE / (pCI->nSatHeight - 1));
  297.             break;
  298.         }
  299.         case COLOR_LUM:
  300.         {
  301.             pCI->currentLum = (WORD)(RANGE -
  302.                                      (pCI->nLumPos - pCI->rLumPaint.top) *
  303.                                      RANGE / (pCI->nLumHeight - 1));
  304.             break;
  305.         }
  306.         default:
  307.         {
  308.             pCI->currentHue = (WORD)((pCI->nHuePos - pCI->rRainbow.left) *
  309.                                      (RANGE - 1) / pCI->nHueWidth);
  310.             pCI->currentSat = (WORD)(RANGE -
  311.                                      (pCI->nSatPos - pCI->rRainbow.top) *
  312.                                      RANGE / pCI->nSatHeight);
  313.             pCI->currentLum = (WORD)(RANGE -
  314.                                      (pCI->nLumPos - pCI->rLumPaint.top) *
  315.                                      RANGE / pCI->nLumHeight);
  316.             break;
  317.         }
  318.     }
  319. }
  320. ////////////////////////////////////////////////////////////////////////////
  321. //
  322. //  HLStoHLSPos
  323. //
  324. ////////////////////////////////////////////////////////////////////////////
  325. VOID HLStoHLSPos(
  326.     SHORT nHLSEdit,
  327.     register PCOLORINFO pCI)
  328. {
  329.     switch (nHLSEdit)
  330.     {
  331.         case ( COLOR_HUE ) :
  332.         {
  333.             pCI->nHuePos = (WORD)(pCI->rRainbow.left + pCI->currentHue *
  334.                                   pCI->nHueWidth / (RANGE - 1));
  335.             break;
  336.         }
  337.         case COLOR_SAT:
  338.         {
  339.             pCI->nSatPos = (WORD)(pCI->rRainbow.top +
  340.                                   (RANGE - pCI->currentSat) *
  341.                                   (pCI->nSatHeight - 1) / RANGE);
  342.             break;
  343.         }
  344.         case COLOR_LUM:
  345.         {
  346.             pCI->nLumPos = (WORD)(pCI->rLumPaint.top +
  347.                                   (RANGE - pCI->currentLum) *
  348.                                   (pCI->nLumHeight - 1) / RANGE);
  349.             break;
  350.         }
  351.         default:
  352.         {
  353.             pCI->nHuePos = (WORD)(pCI->rRainbow.left + pCI->currentHue *
  354.                                   pCI->nHueWidth / (RANGE - 1));
  355.             pCI->nSatPos = (WORD)(pCI->rRainbow.top +
  356.                                   (RANGE - pCI->currentSat) *
  357.                                   (pCI->nSatHeight - 1) / RANGE);
  358.             pCI->nLumPos = (WORD)(pCI->rLumPaint.top +
  359.                                   (RANGE - pCI->currentLum) *
  360.                                   (pCI->nLumHeight - 1) / RANGE);
  361.             break;
  362.         }
  363.     }
  364. }
  365. ////////////////////////////////////////////////////////////////////////////
  366. //
  367. //  SetHLSEdit
  368. //
  369. ////////////////////////////////////////////////////////////////////////////
  370. VOID SetHLSEdit(
  371.     SHORT nHLSEdit,
  372.     register PCOLORINFO pCI)
  373. {
  374.     register HWND hRainbowDlg = pCI->hDialog;
  375.     switch (nHLSEdit)
  376.     {
  377.         case ( COLOR_HUE ) :
  378.         {
  379.             SetDlgItemInt(hRainbowDlg, COLOR_HUE, pCI->currentHue, FALSE);
  380.             break;
  381.         }
  382.         case ( COLOR_SAT ) :
  383.         {
  384.             SetDlgItemInt(hRainbowDlg, COLOR_SAT, pCI->currentSat, FALSE);
  385.             break;
  386.         }
  387.         case ( COLOR_LUM ) :
  388.         {
  389.             SetDlgItemInt(hRainbowDlg, COLOR_LUM, pCI->currentLum, FALSE);
  390.             break;
  391.         }
  392.         default :
  393.         {
  394.             SetDlgItemInt(hRainbowDlg, COLOR_HUE, pCI->currentHue, FALSE);
  395.             SetDlgItemInt(hRainbowDlg, COLOR_SAT, pCI->currentSat, FALSE);
  396.             SetDlgItemInt(hRainbowDlg, COLOR_LUM, pCI->currentLum, FALSE);
  397.             break;
  398.         }
  399.     }
  400. }
  401. ////////////////////////////////////////////////////////////////////////////
  402. //
  403. //  SetRGBEdit
  404. //
  405. ////////////////////////////////////////////////////////////////////////////
  406. VOID SetRGBEdit(
  407.     SHORT nRGBEdit,
  408.     PCOLORINFO pCI)
  409. {
  410.     register HWND hRainbowDlg = pCI->hDialog;
  411.     DWORD rainbowRGB = pCI->currentRGB;
  412.     switch (nRGBEdit)
  413.     {
  414.         case ( COLOR_RED ) :
  415.         {
  416.             SetDlgItemInt(hRainbowDlg, COLOR_RED, GetRValue(rainbowRGB), FALSE);
  417.             break;
  418.         }
  419.         case ( COLOR_GREEN ) :
  420.         {
  421.             SetDlgItemInt(hRainbowDlg, COLOR_GREEN, GetGValue(rainbowRGB), FALSE);
  422.             break;
  423.         }
  424.         case ( COLOR_BLUE ) :
  425.         {
  426.             SetDlgItemInt(hRainbowDlg, COLOR_BLUE, GetBValue(rainbowRGB), FALSE);
  427.             break;
  428.         }
  429.         default :
  430.         {
  431.             SetDlgItemInt(hRainbowDlg, COLOR_RED, GetRValue(rainbowRGB), FALSE);
  432.             SetDlgItemInt(hRainbowDlg, COLOR_GREEN, GetGValue(rainbowRGB), FALSE);
  433.             SetDlgItemInt(hRainbowDlg, COLOR_BLUE, GetBValue(rainbowRGB), FALSE);
  434.             break;
  435.         }
  436.     }
  437. }
  438. ////////////////////////////////////////////////////////////////////////////
  439. //
  440. //  InitRainbow
  441. //
  442. //  Returns TRUE iff we make it.
  443. //
  444. ////////////////////////////////////////////////////////////////////////////
  445. BOOL InitRainbow(
  446.     register PCOLORINFO pCI)
  447. {
  448.     HDC hDC;
  449.     WORD Sat, Hue;
  450.     HBITMAP hOldBitmap;
  451.     RECT Rect;
  452.     HBRUSH hbrSwipe;
  453.     WORD nHueWidth, nSatHeight;
  454.     register HWND hRainbowDlg = pCI->hDialog;
  455.     RGBtoHLS(pCI->currentRGB);
  456.     SetupRainbowCapture(pCI);
  457.     nHueWidth = pCI->nHueWidth = (WORD)(pCI->rRainbow.right -
  458.                                         pCI->rRainbow.left);
  459.     nSatHeight = pCI->nSatHeight = (WORD)(pCI->rRainbow.bottom -
  460.                                           pCI->rRainbow.top);
  461.     pCI->currentHue = gHue;
  462.     pCI->currentSat = gSat;
  463.     pCI->currentLum = gLum;
  464.     HLStoHLSPos(0, pCI);
  465.     SetRGBEdit(0, pCI);
  466.     SetHLSEdit(0, pCI);
  467.     if (!hRainbowBitmap)
  468.     {
  469.         hDC = GetDC(hRainbowDlg);
  470.         hRainbowBitmap = CreateCompatibleBitmap(hDC, nHueWidth, nSatHeight);
  471.         if (!hRainbowBitmap)
  472.         {
  473.             return (FALSE);
  474.         }
  475.     }
  476.     hOldBitmap = SelectObject(hDCFastBlt, hRainbowBitmap);
  477.     //
  478.     //  NOTE: The final pass through this loop paints on and past the end
  479.     //        of the selected bitmap.  Windows is a good product, and doesn't
  480.     //        let such foolishness happen.
  481.     //
  482.     Rect.bottom = 0;
  483.     for (Sat = RANGE; Sat > 0; Sat -= SATINC)
  484.     {
  485.         Rect.top = Rect.bottom;
  486.         Rect.bottom = (nSatHeight * RANGE - (Sat - SATINC) * nSatHeight) / RANGE;
  487.         Rect.right = 0;
  488.         for (Hue = 0; Hue < (RANGE - 1); Hue += HUEINC)
  489.         {
  490.             Rect.left = Rect.right;
  491.             Rect.right = ((Hue + HUEINC) * nHueWidth) / RANGE;
  492.             hbrSwipe = CreateSolidBrush(HLStoRGB(Hue, RANGE / 2, Sat));
  493.             FillRect(hDCFastBlt, &Rect, hbrSwipe);
  494.             DeleteObject(hbrSwipe);
  495.         }
  496.     }
  497.     SelectObject(hDCFastBlt, hOldBitmap);
  498.     ReleaseDC(hRainbowDlg, hDC);
  499.     UpdateWindow(hRainbowDlg);
  500.     return (TRUE);
  501. }
  502. ////////////////////////////////////////////////////////////////////////////
  503. //
  504. //  PaintRainbow
  505. //
  506. ////////////////////////////////////////////////////////////////////////////
  507. VOID PaintRainbow(
  508.     HDC hDC,
  509.     LPRECT lpRect,
  510.     register PCOLORINFO pCI)
  511. {
  512.     HBITMAP hOldBitmap;
  513.     if (!hRainbowBitmap)
  514.     {
  515.         return;
  516.     }
  517.     hOldBitmap = SelectObject(hDCFastBlt, hRainbowBitmap);
  518.     BitBlt( hDC,
  519.             lpRect->left,
  520.             lpRect->top,
  521.             lpRect->right - lpRect->left,
  522.             lpRect->bottom - lpRect->top,
  523.             hDCFastBlt,
  524.             lpRect->left - pCI->rRainbow.left,
  525.             lpRect->top - pCI->rRainbow.top,
  526.             SRCCOPY );
  527.     SelectObject(hDCFastBlt, hOldBitmap);
  528.     CrossHairPaint(hDC, pCI->nHuePos, pCI->nSatPos, pCI);
  529.     UpdateWindow(pCI->hDialog);
  530. }
  531. ////////////////////////////////////////////////////////////////////////////
  532. //
  533. //  RainbowPaint
  534. //
  535. ////////////////////////////////////////////////////////////////////////////
  536. void RainbowPaint(
  537.     register PCOLORINFO pCI,
  538.     HDC hDC,
  539.     LPRECT lpPaintRect)
  540. {
  541.     WORD Lum;
  542.     RECT Rect;
  543.     HBRUSH hbrSwipe;
  544.     //
  545.     //  Paint the Current Color Sample.
  546.     //
  547.     if (IntersectRect((LPRECT)&Rect, lpPaintRect, (LPRECT)&(pCI->rCurrentColor)))
  548.     {
  549.         hbrSwipe = CreateSolidBrush(pCI->currentRGB);
  550.         FillRect(hDC, (LPRECT)&Rect, hbrSwipe);
  551.         DeleteObject(hbrSwipe);
  552.     }
  553.     //
  554.     //  Paint the Nearest Pure Color Sample.
  555.     //
  556.     if (IntersectRect((LPRECT)&Rect, lpPaintRect, (LPRECT)&(pCI->rNearestPure)))
  557.     {
  558.         hbrSwipe = CreateSolidBrush(GetNearestColor(hDC, pCI->currentRGB));
  559.         FillRect(hDC, (LPRECT)&Rect, hbrSwipe);
  560.         DeleteObject(hbrSwipe);
  561.     }
  562.     //
  563.     //  Paint the Luminosity Range.
  564.     //
  565.     if (IntersectRect((LPRECT)&Rect, lpPaintRect, (LPRECT)&(pCI->rLumPaint)))
  566.     {
  567.         Rect.left = pCI->rLumPaint.left;
  568.         Rect.right = pCI->rLumPaint.right;
  569.         Rect.top = pCI->rLumPaint.bottom - LUMINC / 2;
  570.         Rect.bottom = pCI->rLumPaint.bottom;
  571.         hbrSwipe = CreateSolidBrush(HLStoRGB( pCI->currentHue,
  572.                                               0,
  573.                                               pCI->currentSat ));
  574.         FillRect(hDC, (LPRECT)&Rect, hbrSwipe);
  575.         DeleteObject(hbrSwipe);
  576.         for (Lum = LUMINC; Lum < RANGE; Lum += LUMINC)
  577.         {
  578.             Rect.bottom = Rect.top;
  579.             Rect.top = (((pCI->rLumPaint.bottom + LUMINC / 2) * (DWORD)RANGE -
  580.                          (Lum + LUMINC) * pCI->nLumHeight) / RANGE);
  581.             hbrSwipe = CreateSolidBrush(HLStoRGB( pCI->currentHue,
  582.                                                   Lum,
  583.                                                   pCI->currentSat ));
  584.             FillRect(hDC, (LPRECT)&Rect, hbrSwipe);
  585.             DeleteObject(hbrSwipe);
  586.         }
  587.         Rect.bottom = Rect.top;
  588.         Rect.top = pCI->rLumPaint.top;
  589.         hbrSwipe = CreateSolidBrush(HLStoRGB( pCI->currentHue,
  590.                                               RANGE,
  591.                                               pCI->currentSat ));
  592.         FillRect(hDC, (LPRECT)&Rect, hbrSwipe);
  593.         DeleteObject(hbrSwipe);
  594.         //
  595.         //  Paint the bounding rectangle only when it might be necessary.
  596.         //
  597.         if (!EqualRect(lpPaintRect, (LPRECT)&pCI->rLumPaint))
  598.         {
  599.             hbrSwipe = SelectObject(hDC, GetStockObject(NULL_BRUSH));
  600.             Rectangle( hDC,
  601.                        pCI->rLumPaint.left - 1,
  602.                        pCI->rLumPaint.top - 1,
  603.                        pCI->rLumPaint.right + 1,
  604.                        pCI->rLumPaint.bottom + 1 );
  605.             SelectObject(hDC, hbrSwipe);
  606.         }
  607.     }
  608.     //
  609.     //  Paint the Luminosity Arrow.
  610.     //
  611.     if (IntersectRect((LPRECT)&Rect, lpPaintRect, (LPRECT)&pCI->rLumScroll))
  612.     {
  613.         LumArrowPaint(hDC, pCI->nLumPos, pCI);
  614.     }
  615.     if (IntersectRect((LPRECT)&Rect, lpPaintRect, (LPRECT)&pCI->rRainbow))
  616.     {
  617.         PaintRainbow(hDC, (LPRECT)&Rect, pCI);
  618.     }
  619. }
  620. ////////////////////////////////////////////////////////////////////////////
  621. //
  622. //  Color conversion routines --
  623. //
  624. //  RGBtoHLS() takes a DWORD RGB value, translates it to HLS, and stores the
  625. //  results in the global vars H, L, and S.  HLStoRGB takes the current values
  626. //  of H, L, and S and returns the equivalent value in an RGB DWORD.  The vars
  627. //  H, L and S are written to only by 1) RGBtoHLS (initialization) or 2) the
  628. //  scrollbar handlers.
  629. //
  630. //  A point of reference for the algorithms is Foley and Van Dam, pp. 618-19.
  631. //  Their algorithm is in floating point.
  632. //
  633. //  There are potential roundoff errors lurking throughout here.
  634. //     (0.5 + x/y) without floating point,
  635. //     (x / y) phrased ((x + (y / 2)) / y) yields very small roundoff error.
  636. //  This makes many of the following divisions look funny.
  637. //
  638. //
  639. //  H,L, and S vary over 0 - HLSMAX.
  640. //  R,G, and B vary over 0 - RGBMAX.
  641. //  HLSMAX BEST IF DIVISIBLE BY 6.
  642. //  RGBMAX, HLSMAX must each fit in a byte.
  643. //
  644. //  Hue is undefined if Saturation is 0 (grey-scale).
  645. //  This value determines where the Hue scrollbar is initially set for
  646. //  achromatic colors.
  647. //
  648. ////////////////////////////////////////////////////////////////////////////
  649. #define UNDEFINED (HLSMAX * 2 / 3)
  650. ////////////////////////////////////////////////////////////////////////////
  651. //
  652. //  RGBtoHLS
  653. //
  654. ////////////////////////////////////////////////////////////////////////////
  655. VOID RGBtoHLS(
  656.     DWORD lRGBColor)
  657. {
  658.     WORD R, G, B;                 // input RGB values
  659.     WORD cMax,cMin;               // max and min RGB values
  660.     WORD cSum,cDif;
  661.     SHORT Rdelta, Gdelta, Bdelta; // intermediate value: % of spread from max
  662.     //
  663.     //  get R, G, and B out of DWORD.
  664.     //
  665.     R = GetRValue(lRGBColor);
  666.     G = GetGValue(lRGBColor);
  667.     B = GetBValue(lRGBColor);
  668.     //
  669.     //  Calculate lightness.
  670.     //
  671.     cMax = max(max(R, G), B);
  672.     cMin = min(min(R, G), B);
  673.     cSum = cMax + cMin;
  674.     gLum = (WORD)(((cSum * (DWORD)HLSMAX) + RGBMAX) / (2 * RGBMAX));
  675.     cDif = cMax - cMin;
  676.     if (!cDif)
  677.     {
  678.         //
  679.         //  r = g = b --> Achromatic case.
  680.         //
  681.         gSat = 0;                         // saturation
  682.         gHue = UNDEFINED;                 // hue
  683.     }
  684.     else
  685.     {
  686.         //
  687.         //  Chromatic case.
  688.         //
  689.         //
  690.         //  Saturation.
  691.         //
  692.         //  Note: Division by cSum is not a problem, as cSum can only
  693.         //        be 0 if the RGB value is 0L, and that is achromatic.
  694.         //
  695.         if (gLum <= (HLSMAX / 2))
  696.         {
  697.             gSat = (WORD)(((cDif * (DWORD) HLSMAX) + (cSum / 2) ) / cSum);
  698.         }
  699.         else
  700.         {
  701.             gSat = (WORD)((DWORD)((cDif * (DWORD)HLSMAX) +
  702.                                (DWORD)((2 * RGBMAX - cSum) / 2)) /
  703.                        (2 * RGBMAX - cSum));
  704.         }
  705.         //
  706.         //  Hue.
  707.         //
  708.         Rdelta = (SHORT)((((cMax - R) * (DWORD)(HLSMAX / 6)) + (cDif / 2) ) / cDif);
  709.         Gdelta = (SHORT)((((cMax - G) * (DWORD)(HLSMAX / 6)) + (cDif / 2) ) / cDif);
  710.         Bdelta = (SHORT)((((cMax - B) * (DWORD)(HLSMAX / 6)) + (cDif / 2) ) / cDif);
  711.         if (R == cMax)
  712.         {
  713.             gHue = Bdelta - Gdelta;
  714.         }
  715.         else if (G == cMax)
  716.         {
  717.             gHue = (WORD)((HLSMAX / 3) + Rdelta - Bdelta);
  718.         }
  719.         else  // (B == cMax)
  720.         {
  721.             gHue = (WORD)(((2 * HLSMAX) / 3) + Gdelta - Rdelta);
  722.         }
  723.         if ((short)gHue < 0)
  724.         {
  725.             //
  726.             //  This can occur when R == cMax and G is > B.
  727.             //
  728.             gHue += HLSMAX;
  729.         }
  730.         if (gHue >= HLSMAX)
  731.         {
  732.             gHue -= HLSMAX;
  733.         }
  734.     }
  735. }
  736. ////////////////////////////////////////////////////////////////////////////
  737. //
  738. //  HueToRGB
  739. //
  740. //  Utility routine for HLStoRGB.
  741. //
  742. ////////////////////////////////////////////////////////////////////////////
  743. WORD HueToRGB(
  744.     WORD n1,
  745.     WORD n2,
  746.     WORD hue)
  747. {
  748.     if (hue >= HLSMAX)
  749.     {
  750.         hue -= HLSMAX;
  751.     }
  752.     //
  753.     //  Return r, g, or b value from this tridrant.
  754.     //
  755.     if (hue < (HLSMAX / 6))
  756.     {
  757.         return ((WORD)(n1 + (((n2 - n1) * hue + (HLSMAX / 12)) / (HLSMAX / 6))));
  758.     }
  759.     if (hue < (HLSMAX/2))
  760.     {
  761.         return (n2);
  762.     }
  763.     if (hue < ((HLSMAX*2)/3))
  764.     {
  765.         return ((WORD)(n1 + (((n2 - n1) * (((HLSMAX * 2) / 3) - hue) +
  766.                        (HLSMAX / 12)) / (HLSMAX / 6))));
  767.     }
  768.     else
  769.     {
  770.         return (n1);
  771.     }
  772. }
  773. ////////////////////////////////////////////////////////////////////////////
  774. //
  775. //  HLStoRGB
  776. //
  777. ////////////////////////////////////////////////////////////////////////////
  778. DWORD HLStoRGB(
  779.     WORD hue,
  780.     WORD lum,
  781.     WORD sat)
  782. {
  783.     WORD R, G, B;                      // RGB component values
  784.     WORD Magic1, Magic2;               // calculated magic numbers
  785.     if (sat == 0)
  786.     {
  787.         //
  788.         //  Achromatic case.
  789.         //
  790.         R = G = B = (WORD)((lum * RGBMAX) / HLSMAX);
  791.     }
  792.     else
  793.     {
  794.         //
  795.         //  Chromatic case
  796.         //
  797.         //
  798.         //  Set up magic numbers.
  799.         //
  800.         if (lum <= (HLSMAX / 2))
  801.         {
  802.             Magic2 = (WORD)((lum * ((DWORD)HLSMAX + sat) + (HLSMAX / 2)) / HLSMAX);
  803.         }
  804.         else
  805.         {
  806.             Magic2 = lum + sat -
  807.                      (WORD)(((lum * sat) + (DWORD)(HLSMAX / 2)) / HLSMAX);
  808.         }
  809.         Magic1 = (WORD)(2 * lum - Magic2);
  810.         //
  811.         //  Get RGB, change units from HLSMAX to RGBMAX.
  812.         //
  813.         R = (WORD)(((HueToRGB(Magic1, Magic2, (WORD)(hue + (HLSMAX / 3))) *
  814.                      (DWORD)RGBMAX + (HLSMAX / 2))) / HLSMAX);
  815.         G = (WORD)(((HueToRGB(Magic1, Magic2, hue) *
  816.                      (DWORD)RGBMAX + (HLSMAX / 2))) / HLSMAX);
  817.         B = (WORD)(((HueToRGB(Magic1, Magic2, (WORD)(hue - (HLSMAX / 3))) *
  818.                      (DWORD)RGBMAX + (HLSMAX / 2))) / HLSMAX);
  819.     }
  820.     return (RGB(R, G, B));
  821. }
  822. ////////////////////////////////////////////////////////////////////////////
  823. //
  824. //  RGBEditChange
  825. //
  826. //  Checks the edit box for a valid entry and updates the Hue, Sat, and Lum
  827. //  edit controls if appropriate.  Also updates Lum picture and current
  828. //  color sample.
  829. //
  830. //  nDlgID - Dialog ID of Red, Green or Blue edit control.
  831. //
  832. ////////////////////////////////////////////////////////////////////////////
  833. SHORT RGBEditChange(
  834.     SHORT nDlgID,
  835.     PCOLORINFO pCI)
  836. {
  837.     BOOL bOK;               // check that value in edit control is uint
  838.     BYTE *currentValue;     // pointer to byte in RGB to change (or reset)
  839.     SHORT nVal;
  840.     TCHAR cEdit[3];
  841.     register HWND hDlg = pCI->hDialog;
  842.     currentValue = (BYTE *)&pCI->currentRGB;
  843.     switch (nDlgID)
  844.     {
  845.         case ( COLOR_GREEN ) :
  846.         {
  847.             currentValue++;
  848.             break;
  849.         }
  850.         case ( COLOR_BLUE ) :
  851.         {
  852.             currentValue += 2;
  853.             break;
  854.         }
  855.     }
  856.     nVal = (SHORT)GetDlgItemInt(hDlg, nDlgID, (BOOL FAR *)&bOK, FALSE);
  857.     if (bOK)
  858.     {
  859.         if (nVal > RGBMAX)
  860.         {
  861.             nVal = RGBMAX;
  862.             SetDlgItemInt(hDlg, nDlgID, nVal, FALSE);
  863.         }
  864.         if (nVal != (SHORT) *currentValue)
  865.         {
  866.             *currentValue = LOBYTE(nVal);
  867.             ChangeColorSettings(pCI);
  868.             SetHLSEdit(nDlgID, pCI);
  869.         }
  870.     }
  871.     else if (GetDlgItemText(hDlg, nDlgID, (LPTSTR)cEdit, 2))
  872.     {
  873.         SetRGBEdit(nDlgID, pCI);
  874.         SendDlgItemMessage(hDlg, nDlgID, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
  875.     }
  876.     return (SHORT)(bOK ? TRUE : FALSE);
  877. }