COLORWP.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:39k
源码类别:

Windows编程

开发平台:

Visual C++

  1.     /***************************************************************************
  2.      *                                                                         *
  3.      *  MODULE      : ColorWP.c                                                *
  4.      *                                                                         *
  5.      *  DESCRIPTION : Window function for the colors window and related fns.   *
  6.      *                                                                         *
  7.      *  FUNCTIONS   : ColorWP ()            - Window function for colors       *
  8.      *                                        window.                          *
  9.      *                                                                         *
  10.      *                ComputeInverseColor() - Gets the inverse RGB of a given  *
  11.      *                                        RGB value                        *
  12.      *                                                                         *
  13.      *  HISTORY     : 6/21/89 - adapted from pBrush - LR                       *
  14.      *                                                                         *
  15.      ***************************************************************************/
  16.     
  17.     #include "imagedit.h"
  18.     #include "dialogs.h"
  19.  #include <windowsx.h>
  20.     #include <commdlg.h>
  21.     
  22.     
  23.     STATICFN VOID NEAR ColorInit(HWND hwnd);
  24.     STATICFN VOID NEAR ColorProcessCommand(HWND hwnd, INT idCtrl, INT NotifyCode);
  25.     STATICFN VOID NEAR ColorBoxPaint(HDC hdc);
  26.     STATICFN VOID NEAR DrawColorRect(HDC hdc, DWORD rgb, INT x, INT y,
  27.         INT cx, INT cy, HDC hdcMem, BOOL fMonoOK);
  28.     STATICFN VOID NEAR MyRectangle(HDC hdc, INT left, INT top, INT right,
  29.         INT bottom, HDC hdcMem, BOOL fMonoOK);
  30.     STATICFN VOID NEAR ColorBoxClicked(UINT msg, PPOINT ppt);
  31.     STATICFN BOOL NEAR ColorBoxHitTest(PPOINT ppt, PINT piColor, PINT pfMode);
  32.     STATICFN VOID NEAR ColorLRPaint(HWND hwnd, HDC hdc);
  33.     STATICFN VOID NEAR ColorLRDrawSamples(HDC hdc, PRECT prc, BOOL fLeft);
  34.     STATICFN VOID NEAR ColorLRUpdate(BOOL fLeft);
  35.     STATICFN VOID NEAR ColorEdit(VOID);
  36.     STATICFN VOID NEAR SetLeftColor(INT iColor, INT iMode);
  37.     STATICFN VOID NEAR SetRightColor(INT iColor, INT iMode);
  38.     STATICFN HBRUSH NEAR MyCreateSolidBrush(DWORD rgb);
  39.     STATICFN DWORD NEAR MyGetNearestColor(DWORD rgb, BOOL fMonoOK);
  40.     STATICFN DWORD NEAR ComputeInverseColor(DWORD rgb);
  41.     
  42.     /*
  43.      * Width/height of a single color square.
  44.      */
  45.     static INT gcxColorBox;
  46.     
  47.     /*
  48.      * Vertical offset within the color box control to where to start the
  49.      * top row of color squares (the color squares are vertically centered
  50.      * within the color box control).
  51.      */
  52.     static INT gyColorBoxStart;
  53.     
  54.     /*
  55.      * Number of colors and image type.  These globals are used by the
  56.      * the color palette routines to know what mode the color palette
  57.      * is in.
  58.      */
  59.     static INT gnColorPalColors;
  60.     static INT giColorPalType;
  61.     
  62.     
  63.     
  64.     /****************************************************************************
  65.     * ColorShow
  66.     *
  67.     * This function shows or hides the color palette.
  68.     *
  69.     * History:
  70.     *
  71.     ****************************************************************************/
  72.     
  73.     VOID ColorShow(
  74.         BOOL fShow)
  75.     {
  76.         if (fShow)
  77.             ShowWindow(ghwndColor, SW_SHOWNA);
  78.         else
  79.             ShowWindow(ghwndColor, SW_HIDE);
  80.     }
  81.     
  82.     
  83.     
  84.     /************************************************************************
  85.     * ColorDlgProc
  86.     *
  87.     *
  88.     *
  89.     * Arguments:
  90.     *
  91.     * History:
  92.     *
  93.     ************************************************************************/
  94.     
  95.     DIALOGPROC ColorDlgProc(
  96.         HWND hwnd,
  97.         UINT msg,
  98.         WPARAM wParam,
  99.         LPARAM lParam)
  100.     {
  101.         switch (msg) {
  102.             case WM_INITDIALOG:
  103.                 ColorInit(hwnd);
  104.     
  105.                 /*
  106.                  * Return TRUE so that the dialog manager does NOT set the focus
  107.                  * for me.  This prevents the status window from initially having
  108.                  * the focus when the editor is started.
  109.                  */
  110.                 return TRUE;
  111.     
  112.             case WM_ACTIVATE:
  113.                 if (GET_WM_ACTIVATE_STATE(wParam, lParam))
  114.                     gidCurrentDlg = DID_COLOR;
  115.     
  116.                 break;
  117.     
  118.             case WM_CTLCOLORBTN:
  119.             case WM_CTLCOLORDLG:
  120.             case WM_CTLCOLORSTATIC:
  121.                 switch (GET_WM_CTLCOLOR_TYPE(wParam, lParam, msg)) {
  122.                     case CTLCOLOR_BTN:
  123.                     case CTLCOLOR_DLG:
  124.                         return (BOOL)GetStockObject(LTGRAY_BRUSH);
  125.     
  126.                     case CTLCOLOR_STATIC:
  127.                         SetBkColor(GET_WM_CTLCOLOR_HDC(wParam, lParam, msg),
  128.                                 RGB_LIGHTGRAY);
  129.                         return (BOOL)GetStockObject(LTGRAY_BRUSH);
  130.                 }
  131.     
  132.                 return (BOOL)NULL;
  133.     
  134.             case  WM_PAINT:
  135.                 {
  136.                     HDC hdc;
  137.                     PAINTSTRUCT ps;
  138.     
  139.                     hdc = BeginPaint(hwnd, &ps);
  140.                     DrawMarginBorder(hwnd, hdc);
  141.                     EndPaint(hwnd, &ps);
  142.                 }
  143.     
  144.                 break;
  145.     
  146.             case WM_COMMAND:
  147.                 ColorProcessCommand(hwnd,
  148.                         GET_WM_COMMAND_ID(wParam, lParam),
  149.                         GET_WM_COMMAND_CMD(wParam, lParam));
  150.                 break;
  151.     
  152.             case WM_CLOSE:
  153.                 /*
  154.                  * The user closed the color palette from the system menu.
  155.                  * Hide the window (we don't actually destroy it so
  156.                  * that it will appear in the same spot when they show
  157.                  * it again).
  158.                  */
  159.                 ColorShow(FALSE);
  160.                 gfShowColor = FALSE;
  161.                 break;
  162.     
  163.             case WM_DESTROY:
  164.                 {
  165.                     RECT rc;
  166.     
  167.                     /*
  168.                      * Save the position of the color palette.
  169.                      */
  170.                     GetWindowRect(hwnd, &rc);
  171.                     WriteWindowPos(&rc, FALSE, szColorPos);
  172.     
  173.                     /*
  174.                      * Null out the global window handle for the color palette
  175.                      * for safety's sake.
  176.                      */
  177.                     ghwndColor = NULL;
  178.                 }
  179.     
  180.                 break;
  181.     
  182.             default:
  183.                 return FALSE;
  184.         }
  185.     
  186.         return FALSE;
  187.     }
  188.     
  189.     
  190.     
  191.     /************************************************************************
  192.     * ColorInit
  193.     *
  194.     *
  195.     *
  196.     * Arguments:
  197.     *
  198.     * History:
  199.     *
  200.     ************************************************************************/
  201.     STATICFN VOID NEAR ColorInit(
  202.         HWND hwnd)
  203.     {
  204.         RECT rc;
  205.     
  206.         /*
  207.          * Get the dimension of a single color square, and the vertical
  208.          * offset to where the top of the squares are.
  209.          */
  210.         GetWindowRect(GetDlgItem(hwnd, DID_COLORBOX), &rc);
  211.         gcxColorBox = (rc.right - rc.left) / COLORCOLS;
  212.         gyColorBoxStart = ((rc.right - rc.left) - (gcxColorBox * COLORCOLS)) / 2;
  213.     }
  214.     
  215.     
  216.     
  217.     /************************************************************************
  218.     * ColorProcessCommand
  219.     *
  220.     *
  221.     * Arguments:
  222.     *   HWND hwnd        - The window handle.
  223.     *   INT idCtrl       - The id of the control the WM_COMMAND is for.
  224.     *   INT NotifyCode   - The control's notification code.
  225.     *
  226.     * History:
  227.     *
  228.     ************************************************************************/
  229.     
  230.     STATICFN VOID NEAR ColorProcessCommand(
  231.         HWND hwnd,
  232.         INT idCtrl,
  233.         INT NotifyCode)
  234.     {
  235.         switch (idCtrl) {
  236.             case DID_COLOREDIT:
  237.                 ColorEdit();
  238.                 break;
  239.     
  240.             case DID_COLORDEFAULT:
  241.                 if (gfModeLeft == MODE_COLOR) {
  242.                     gargbColor[giColorLeft] = gargbDefaultColor[giColorLeft];
  243.                     InvalidateRect(GetDlgItem(ghwndColor, DID_COLORBOX),
  244.                             NULL, TRUE);
  245.                     SetLeftColor(giColorLeft, gfModeLeft);
  246.                 }
  247.     
  248.                 break;
  249.         }
  250.     }
  251.     
  252.     
  253.     
  254.     /************************************************************************
  255.     * ColorBoxWndProc
  256.     *
  257.     *
  258.     *
  259.     * Arguments:
  260.     *
  261.     * History:
  262.     *
  263.     ************************************************************************/
  264.     
  265.     WINDOWPROC ColorBoxWndProc(
  266.         HWND hwnd,
  267.         UINT msg,
  268.         WPARAM wParam,
  269.         LPARAM lParam)
  270.     {
  271.         POINT pt;
  272.         HDC hdc;
  273.         PAINTSTRUCT ps;
  274.         INT iColor;
  275.         INT iMode;
  276.     
  277.         switch (msg) {
  278.             case WM_PAINT:
  279.                 hdc = BeginPaint(hwnd, &ps);
  280.                 ColorBoxPaint(hdc);
  281.                 EndPaint(hwnd, &ps);
  282.                 break;
  283.     
  284.             case WM_LBUTTONDOWN:
  285.             case WM_RBUTTONDOWN:
  286.                 ((pt).x = ((*((POINTS *)&(lParam)))).x, (pt).y = ((*((POINTS *)&(lParam)))).y);
  287.                 ColorBoxClicked(msg, &pt);
  288.                 break;
  289.     
  290.             case WM_LBUTTONDBLCLK:
  291.                 ((pt).x = ((*((POINTS *)&(lParam)))).x, (pt).y = ((*((POINTS *)&(lParam)))).y);
  292.                 if (ColorBoxHitTest(&pt, &iColor, &iMode))
  293.                     ColorEdit();
  294.     
  295.                 break;
  296.     
  297.             default:
  298.                 return DefWindowProc(hwnd, msg, wParam, lParam);
  299.         }
  300.     
  301.         return 0;
  302.     }
  303.     
  304.     
  305.     
  306.     /************************************************************************
  307.     * ColorBoxPaint
  308.     *
  309.     *
  310.     *
  311.     * Arguments:
  312.     *
  313.     * History:
  314.     *
  315.     ************************************************************************/
  316.     
  317.     STATICFN VOID NEAR ColorBoxPaint(
  318.         HDC hdc)
  319.     {
  320.         HDC hdcMem;
  321.         HBITMAP hbmMem;
  322.         INT i;
  323.         INT x;
  324.         INT y;
  325.         INT cx = gcxColorBox + 1;
  326.         INT cy = gcxColorBox + 1;
  327.     
  328.         if (giColorPalType != FT_BITMAP) {
  329.             x = 0;
  330.             y = gyColorBoxStart;
  331.             DrawColorRect(hdc, grgbScreen, x, y, cx, cy, NULL, FALSE);
  332.             y += gcxColorBox;
  333.             DrawColorRect(hdc, grgbInverse, x, y, cx, cy, NULL, FALSE);
  334.         }
  335.     
  336.         if (!(hdcMem = CreateCompatibleDC(hdc)))
  337.             return;
  338.     
  339.         /*
  340.          * Create a bitmap.  It will have the same number of colors as the
  341.          * current image.
  342.          */
  343.         if (!(hbmMem = MyCreateBitmap(hdc, cx, cy, gnColorPalColors))) {
  344.             DeleteDC(hdcMem);
  345.             return;
  346.         }
  347.     
  348.         SelectObject(hdcMem, hbmMem);
  349.     
  350.         x = gcxColorBox * 2;
  351.         y = gyColorBoxStart;
  352.     
  353.         for (i = 1; i <= COLORSMAX; i++) {
  354.             DrawColorRect(hdc, gargbCurrent[i - 1], x, y, cx, cy, hdcMem, TRUE);
  355.     
  356.             if (i % COLORROWS) {
  357.                 y += gcxColorBox;
  358.             }
  359.             else {
  360.                 x += gcxColorBox;
  361.                 y = gyColorBoxStart;
  362.             }
  363.         }
  364.     
  365.         DeleteDC(hdcMem);
  366.         DeleteObject(hbmMem);
  367.     }
  368.     
  369.     
  370.     
  371.     /************************************************************************
  372.     * DrawColorRect
  373.     *
  374.     *
  375.     *
  376.     * Arguments:
  377.     *
  378.     * History:
  379.     *
  380.     ************************************************************************/
  381.     
  382.     STATICFN VOID NEAR DrawColorRect(
  383.         HDC hdc,
  384.         DWORD rgb,
  385.         INT x,
  386.         INT y,
  387.         INT cx,
  388.         INT cy,
  389.         HDC hdcMem,
  390.         BOOL fMonoOK)
  391.     {
  392.         HBRUSH hbr;
  393.         HBRUSH hbrOld;
  394.     
  395.         hbr = CreateSolidBrush(rgb);
  396.         hbrOld = SelectObject(hdc, hbr);
  397.         MyRectangle(hdc, x, y, x + cx, y + cy, hdcMem, fMonoOK);
  398.         SelectObject(hdc, hbrOld);
  399.         DeleteObject(hbr);
  400.     }
  401.     
  402.     
  403.     
  404.     /************************************************************************
  405.     * MyRectangle
  406.     *
  407.     *
  408.     *
  409.     * Arguments:
  410.     *
  411.     * History:
  412.     *
  413.     ************************************************************************/
  414.     
  415.     STATICFN VOID NEAR MyRectangle(
  416.         HDC hdc,
  417.         INT left,
  418.         INT top,
  419.         INT right,
  420.         INT bottom,
  421.         HDC hdcMem,
  422.         BOOL fMonoOK)
  423.     {
  424.         HBITMAP hbmMem;
  425.         HBRUSH hbr;
  426.         HPEN hpen;
  427.         HBRUSH hbrOld;
  428.         HPEN hpenOld;
  429.         BOOL fDCCreated = FALSE;
  430.         INT cx = right - left;
  431.         INT cy = bottom - top;
  432.         INT nColors;
  433.     
  434.         /*
  435.          * Do they want us to create the memory DC and bitmap for them?
  436.          */
  437.         if (!hdcMem) {
  438.             if (!(hdcMem = CreateCompatibleDC(hdc)))
  439.                 return;
  440.     
  441.             /*
  442.              * Create a bitmap.  It will be monochrome if in 2 color mode
  443.              * and monochrome is ok, otherwise it will be 16 color.
  444.              */
  445.             nColors = gnColorPalColors;
  446.             if (!fMonoOK)
  447.                 nColors = 16;
  448.     
  449.             if (!(hbmMem = MyCreateBitmap(hdc, cx, cy, nColors))) {
  450.                 DeleteDC(hdcMem);
  451.                 return;
  452.             }
  453.     
  454.             SelectObject(hdcMem, hbmMem);
  455.             fDCCreated = TRUE;
  456.         }
  457.     
  458.         /*
  459.          * Extract the current pen and brush out of the passed in DC.
  460.          */
  461.         hbr = SelectObject(hdc, GetStockObject(NULL_BRUSH));
  462.         hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
  463.     
  464.         /*
  465.          * Select them into the memory DC.
  466.          */
  467.         hbrOld = SelectObject(hdcMem, hbr);
  468.         hpenOld = SelectObject(hdcMem, hpen);
  469.     
  470.         /*
  471.          * Draw the rectangle in the memory bitmap.
  472.          */
  473.         Rectangle(hdcMem, 0, 0, cx, cy);
  474.     
  475.         /*
  476.          * Unselect the pen and brush from the memory DC.
  477.          */
  478.         SelectObject(hdcMem, hbrOld);
  479.         SelectObject(hdcMem, hpenOld);
  480.     
  481.         /*
  482.          * Restore the pen and brush to the original DC.
  483.          */
  484.         SelectObject(hdc, hbr);
  485.         SelectObject(hdc, hpen);
  486.     
  487.         /*
  488.          * Blit the memory image to the passed in DC.
  489.          */
  490.         BitBlt(hdc, left, top, cx, cy, hdcMem, 0, 0, SRCCOPY);
  491.     
  492.         if (fDCCreated) {
  493.             DeleteDC(hdcMem);
  494.             DeleteObject(hbmMem);
  495.         }
  496.     }
  497.     
  498.     
  499.     
  500.     /************************************************************************
  501.     * ColorBoxClicked
  502.     *
  503.     *
  504.     *
  505.     * Arguments:
  506.     *
  507.     * History:
  508.     *
  509.     ************************************************************************/
  510.     
  511.     STATICFN VOID NEAR ColorBoxClicked(
  512.         UINT msg,
  513.         PPOINT ppt)
  514.     {
  515.         INT iColor;
  516.         INT iMode;
  517.     
  518.         if (ColorBoxHitTest(ppt, &iColor, &iMode)) {
  519.             switch (msg) {
  520.                 case WM_LBUTTONDOWN:
  521.                     SetLeftColor(iColor, iMode);
  522.                     break;
  523.     
  524.                 case WM_RBUTTONDOWN:
  525.                     SetRightColor(iColor, iMode);
  526.                     break;
  527.             }
  528.         }
  529.     }
  530.     
  531.     
  532.     
  533.     /************************************************************************
  534.     * ColorBoxHitTest
  535.     *
  536.     *
  537.     *
  538.     * Arguments:
  539.     *
  540.     * History:
  541.     *
  542.     ************************************************************************/
  543.     
  544.     STATICFN BOOL NEAR ColorBoxHitTest(
  545.         PPOINT ppt,
  546.         PINT piColor,
  547.         PINT pfMode)
  548.     {
  549.         INT iCol;
  550.         INT iRow;
  551.         INT iBox;
  552.     
  553.         if (ppt->y < gyColorBoxStart)
  554.             return FALSE;
  555.     
  556.         iCol = ppt->x / gcxColorBox;
  557.         iRow = (ppt->y - gyColorBoxStart) / gcxColorBox;
  558.     
  559.         if (iCol >= (COLORSMAX / COLORROWS) + 2 || iRow >= COLORROWS)
  560.             return FALSE;
  561.     
  562.         iBox = iRow + (iCol * COLORROWS);
  563.     
  564.         switch (iBox) {
  565.             case 0:
  566.                 if (giColorPalType == FT_BITMAP)
  567.                     return FALSE;
  568.     
  569.                 *piColor = 0;
  570.                 *pfMode = MODE_SCREEN;
  571.                 return TRUE;
  572.     
  573.             case 1:
  574.                 if (giColorPalType == FT_BITMAP)
  575.                     return FALSE;
  576.     
  577.                 *piColor = 0;
  578.                 *pfMode = MODE_INVERSE;
  579.                 return TRUE;
  580.     
  581.             case 2:
  582.             case 3:
  583.                 return FALSE;
  584.     
  585.             default:
  586.                 *piColor = iBox - (COLORROWS * 2);
  587.                 *pfMode = MODE_COLOR;
  588.                 return TRUE;
  589.         }
  590.     }
  591.     
  592.     
  593.     
  594.     /************************************************************************
  595.     * ColorLRWndProc
  596.     *
  597.     *
  598.     *
  599.     * Arguments:
  600.     *
  601.     * History:
  602.     *
  603.     ************************************************************************/
  604.     
  605.     WINDOWPROC ColorLRWndProc(
  606.         HWND hwnd,
  607.         UINT msg,
  608.         WPARAM wParam,
  609.         LPARAM lParam)
  610.     {
  611.         HDC hdc;
  612.         PAINTSTRUCT ps;
  613.     
  614.         switch (msg) {
  615.             case WM_PAINT:
  616.                 hdc = BeginPaint(hwnd, &ps);
  617.                 ColorLRPaint(hwnd, hdc);
  618.                 EndPaint(hwnd, &ps);
  619.                 break;
  620.     
  621.             default:
  622.                 return DefWindowProc(hwnd, msg, wParam, lParam);
  623.         }
  624.     
  625.         return 0;
  626.     }
  627.     
  628.     
  629.     
  630.     /************************************************************************
  631.     * ColorLRPaint
  632.     *
  633.     *
  634.     *
  635.     * Arguments:
  636.     *
  637.     * History:
  638.     *
  639.     ************************************************************************/
  640.     
  641.     STATICFN VOID NEAR ColorLRPaint(
  642.         HWND hwnd,
  643.         HDC hdc)
  644.     {
  645.         RECT rc;
  646.     
  647.         GetClientRect(hwnd, &rc);
  648.         DrawSunkenRect(&rc, hdc);
  649.         ColorLRDrawSamples(hdc, &rc, TRUE);
  650.         ColorLRDrawSamples(hdc, &rc, FALSE);
  651.     }
  652.     
  653.     
  654.     
  655.     /************************************************************************
  656.     * ColorLRDrawSamples
  657.     *
  658.     * Draws the sample colors in the Color Left-Right control.
  659.     *
  660.     * Arguments:
  661.     *   HDC hdc    - DC to draw into.
  662.     *   PRECT prc  - Rectangle of color sample control.  The samples will
  663.     *                be centered within this with an appropriate margin.
  664.     *   BOOL fLeft - TRUE if the left sample is to be drawn, FALSE for the right.
  665.     *
  666.     * History:
  667.     *
  668.     ************************************************************************/
  669.     
  670.     STATICFN VOID NEAR ColorLRDrawSamples(
  671.         HDC hdc,
  672.         PRECT prc,
  673.         BOOL fLeft)
  674.     {
  675.         INT xLeftStart;
  676.         INT xRightStart;
  677.         INT ySolidStart;
  678.         INT yDitherStart;
  679.         INT cx;
  680.         INT cy;
  681.         HBRUSH hbrOld;
  682.         HPEN hpenOld;
  683.         BOOL fMonoOK;
  684.     
  685.         /*
  686.          * The width and height of each square includes the border.
  687.          */
  688.         cx = ((prc->right - prc->left) - (6 * PALETTEMARGIN)) / 2;
  689.         cy = ((prc->bottom - prc->top) - (4 * PALETTEMARGIN)) / 2;
  690.     
  691.         xLeftStart = prc->left + (PALETTEMARGIN * 2) + 1;
  692.         xRightStart = xLeftStart + cx + (PALETTEMARGIN * 2);
  693.     
  694.         ySolidStart = prc->top + (PALETTEMARGIN * 2) + 1;
  695.         yDitherStart = ySolidStart - 1 + cy;
  696.     
  697.         /*
  698.          * Draw either the left or the right color sample.
  699.          */
  700.         if (fLeft) {
  701.             fMonoOK = (gfModeLeft == MODE_COLOR) ? TRUE : FALSE;
  702.     
  703.             /*
  704.              * Draw the solid color.
  705.              */
  706.             hbrOld = SelectObject(hdc, ghbrLeftSolid);
  707.             hpenOld = SelectObject(hdc, GetStockObject(NULL_PEN));
  708.             MyRectangle(hdc, xLeftStart, ySolidStart,
  709.                     xLeftStart + cx, yDitherStart + 1, NULL, fMonoOK);
  710.     
  711.             /*
  712.              * Draw the true color (may be dithered).
  713.              */
  714.             SelectObject(hdc, ghbrLeft);
  715.             MyRectangle(hdc, xLeftStart, yDitherStart,
  716.                     xLeftStart + cx, yDitherStart + cy, NULL, fMonoOK);
  717.         }
  718.         else {
  719.             fMonoOK = (gfModeRight == MODE_COLOR) ? TRUE : FALSE;
  720.     
  721.             hbrOld = SelectObject(hdc, ghbrRightSolid);
  722.             hpenOld = SelectObject(hdc, GetStockObject(NULL_PEN));
  723.             MyRectangle(hdc, xRightStart, ySolidStart,
  724.                     xRightStart + cx, yDitherStart + 1, NULL, fMonoOK);
  725.     
  726.             SelectObject(hdc, ghbrRight);
  727.             MyRectangle(hdc, xRightStart, yDitherStart,
  728.                     xRightStart + cx, yDitherStart + cy, NULL, fMonoOK);
  729.         }
  730.     
  731.         /*
  732.          * Now draw the outline rectangle.
  733.          */
  734.         SelectObject(hdc, GetStockObject(BLACK_PEN));
  735.         SelectObject(hdc, GetStockObject(NULL_BRUSH));
  736.     
  737.         if (fLeft) {
  738.             Rectangle(hdc, xLeftStart - 1, ySolidStart - 1,
  739.                     xLeftStart + cx, yDitherStart + cy);
  740.         }
  741.         else {
  742.             Rectangle(hdc, xRightStart - 1, ySolidStart - 1,
  743.                     xRightStart + cx, yDitherStart + cy);
  744.         }
  745.     
  746.         /*
  747.          * Clean up.
  748.          */
  749.         SelectObject(hdc, hpenOld);
  750.         SelectObject(hdc, hbrOld);
  751.     }
  752.     
  753.     
  754.     
  755.     /************************************************************************
  756.     * ColorLRUpdate
  757.     *
  758.     * Called when the left or right color has been changed.  This function
  759.     * will cause the specified color sample to be updated in the color palette.
  760.     *
  761.     * History:
  762.     *
  763.     ************************************************************************/
  764.     
  765.     STATICFN VOID NEAR ColorLRUpdate(
  766.         BOOL fLeft)
  767.     {
  768.         RECT rc;
  769.         HWND hwndLR;
  770.         HDC hdc;
  771.     
  772.         hwndLR = GetDlgItem(ghwndColor, DID_COLORLR);
  773.         GetClientRect(hwndLR, &rc);
  774.         hdc = GetDC(hwndLR);
  775.         ColorLRDrawSamples(hdc, &rc, fLeft);
  776.         ReleaseDC(hwndLR, hdc);
  777.     }
  778.     
  779.     
  780.     
  781.     /************************************************************************
  782.     * ColorEdit
  783.     *
  784.     * This function calls the standard color chooser dialog to get a
  785.     * new color for the selected palette entry.
  786.     *
  787.     * History:
  788.     *
  789.     ************************************************************************/
  790.     
  791.     STATICFN VOID NEAR ColorEdit(VOID)
  792.     {
  793.         /*
  794.          * This array of custom colors is initialized to all white colors.
  795.          * The custom colors will be remembered between calls, but not
  796.          * between sessions.
  797.          */
  798.         static DWORD argbCust[16] = {
  799.             RGB(255, 255, 255), RGB(255, 255, 255),
  800.             RGB(255, 255, 255), RGB(255, 255, 255),
  801.             RGB(255, 255, 255), RGB(255, 255, 255),
  802.             RGB(255, 255, 255), RGB(255, 255, 255),
  803.             RGB(255, 255, 255), RGB(255, 255, 255),
  804.             RGB(255, 255, 255), RGB(255, 255, 255),
  805.             RGB(255, 255, 255), RGB(255, 255, 255),
  806.             RGB(255, 255, 255), RGB(255, 255, 255)
  807.         };
  808.         CHOOSECOLOR cc;
  809.         DWORD rgbOld;
  810.         BOOL fResult;
  811.         INT idPrevDlg;
  812.     
  813.         switch (gfModeLeft) {
  814.             case MODE_COLOR:
  815.                 /*
  816.                  * The monochrome palette cannot be edited.
  817.                  */
  818.                 if (gnColorPalColors == 2)
  819.                     return;
  820.     
  821.                 rgbOld = gargbCurrent[giColorLeft];
  822.                 break;
  823.     
  824.             case MODE_SCREEN:
  825.                 rgbOld = grgbScreen;
  826.                 break;
  827.     
  828.             case MODE_INVERSE:
  829.                 rgbOld = grgbInverse;
  830.                 break;
  831.         }
  832.     
  833.         cc.lStructSize = sizeof(CHOOSECOLOR);
  834.         cc.hwndOwner = ghwndMain;
  835.         cc.hInstance = ghInst;
  836.         cc.rgbResult = rgbOld;
  837.         cc.lpCustColors = argbCust;
  838.         cc.Flags = CC_RGBINIT | CC_SHOWHELP;
  839.         cc.lCustData = 0;
  840.         cc.lpfnHook = NULL;
  841.         cc.lpTemplateName = NULL;
  842.     
  843.         EnteringDialog(DID_COMMONFILECHOOSECOLOR, &idPrevDlg, TRUE);
  844.         fResult = ChooseColor(&cc);
  845.         EnteringDialog(idPrevDlg, NULL, FALSE);
  846.     
  847.         if (fResult && rgbOld != cc.rgbResult) {
  848.             switch (gfModeLeft) {
  849.                 case MODE_COLOR:
  850.                     gargbCurrent[giColorLeft] = cc.rgbResult;
  851.                     break;
  852.     
  853.                 case MODE_SCREEN:
  854.                     SetScreenColor(cc.rgbResult);
  855.                     break;
  856.     
  857.                 case MODE_INVERSE:
  858.                     SetScreenColor(ComputeInverseColor(cc.rgbResult));
  859.                     break;
  860.             }
  861.     
  862.             SetLeftColor(giColorLeft, gfModeLeft);
  863.             InvalidateRect(GetDlgItem(ghwndColor, DID_COLORBOX), NULL, TRUE);
  864.         }
  865.     }
  866.     
  867.     
  868.     
  869.     /************************************************************************
  870.     * SetLeftColor
  871.     *
  872.     *
  873.     * History:
  874.     *
  875.     ************************************************************************/
  876.     
  877.     STATICFN VOID NEAR SetLeftColor(
  878.         INT iColor,
  879.         INT iMode)
  880.     {
  881.         DWORD rgbSolid;
  882.         BOOL fEnableDefault = FALSE;
  883.         BOOL fEnableEdit = FALSE;
  884.     
  885.         if (ghbrLeft)
  886.             DeleteObject(ghbrLeft);
  887.     
  888.         if (ghbrLeftSolid)
  889.             DeleteObject(ghbrLeftSolid);
  890.     
  891.         if (ghpenLeft)
  892.             DeleteObject(ghpenLeft);
  893.     
  894.         switch (iMode) {
  895.             case MODE_COLOR:
  896.                 ghbrLeft = MyCreateSolidBrush(gargbCurrent[iColor]);
  897.                 rgbSolid = MyGetNearestColor(gargbCurrent[iColor], TRUE);
  898.                 ghbrLeftSolid = CreateSolidBrush(rgbSolid);
  899.                 ghpenLeft = CreatePen(PS_INSIDEFRAME, 1, rgbSolid);
  900.                 giColorLeft = iColor;
  901.     
  902.                 /*
  903.                  * We will enable the "Default" button if the current color
  904.                  * on the left button is not the default color, and we are
  905.                  * not in monochrome mode.
  906.                  */
  907.                 if (gargbColor[giColorLeft] != gargbDefaultColor[giColorLeft] &&
  908.                         gnColorPalColors > 2)
  909.                     fEnableDefault = TRUE;
  910.     
  911.                 /*
  912.                  * For non-screen colors, the Edit button will be enabled
  913.                  * if we are not in monochrome mode.
  914.                  */
  915.                 if (gnColorPalColors > 2)
  916.                     fEnableEdit = TRUE;
  917.     
  918.                 break;
  919.     
  920.             case MODE_SCREEN:
  921.                 ghbrLeft = CreateSolidBrush(grgbScreen);
  922.                 ghbrLeftSolid = CreateSolidBrush(grgbScreen);
  923.                 ghpenLeft = CreatePen(PS_INSIDEFRAME, 1, grgbScreen);
  924.                 giColorLeft = 0;
  925.                 fEnableEdit = TRUE;
  926.                 break;
  927.     
  928.             case MODE_INVERSE:
  929.                 ghbrLeft = CreateSolidBrush(grgbInverse);
  930.                 ghbrLeftSolid = CreateSolidBrush(grgbInverse);
  931.                 ghpenLeft = CreatePen(PS_INSIDEFRAME, 1, grgbInverse);
  932.                 giColorLeft = 0;
  933.                 fEnableEdit = TRUE;
  934.                 break;
  935.         }
  936.     
  937.         EnableWindow(GetDlgItem(ghwndColor, DID_COLORDEFAULT), fEnableDefault);
  938.         EnableWindow(GetDlgItem(ghwndColor, DID_COLOREDIT), fEnableEdit);
  939.     
  940.         gfModeLeft = iMode;
  941.         ColorLRUpdate(TRUE);
  942.     }
  943.     
  944.     
  945.     
  946.     /************************************************************************
  947.     * SetRightColor
  948.     *
  949.     *
  950.     * History:
  951.     *
  952.     ************************************************************************/
  953.     
  954.     STATICFN VOID NEAR SetRightColor(
  955.         INT iColor,
  956.         INT iMode)
  957.     {
  958.         DWORD rgbSolid;
  959.     
  960.         if (ghbrRight)
  961.             DeleteObject(ghbrRight);
  962.     
  963.         if (ghbrRightSolid)
  964.             DeleteObject(ghbrRightSolid);
  965.     
  966.         if (ghpenRight)
  967.             DeleteObject(ghpenRight);
  968.     
  969.         switch (iMode) {
  970.             case MODE_COLOR:
  971.                 ghbrRight = MyCreateSolidBrush(gargbCurrent[iColor]);
  972.                 rgbSolid = MyGetNearestColor(gargbCurrent[iColor], TRUE);
  973.                 ghbrRightSolid = CreateSolidBrush(rgbSolid);
  974.                 ghpenRight = CreatePen(PS_INSIDEFRAME, 1, rgbSolid);
  975.                 giColorRight = iColor;
  976.                 break;
  977.     
  978.             case MODE_SCREEN:
  979.                 ghbrRight = CreateSolidBrush(grgbScreen);
  980.                 ghbrRightSolid = CreateSolidBrush(grgbScreen);
  981.                 ghpenRight = CreatePen(PS_INSIDEFRAME, 1, grgbScreen);
  982.                 giColorRight = 0;
  983.                 break;
  984.     
  985.             case MODE_INVERSE:
  986.                 ghbrRight = CreateSolidBrush(grgbInverse);
  987.                 ghbrRightSolid = CreateSolidBrush(grgbInverse);
  988.                 ghpenRight = CreatePen(PS_INSIDEFRAME, 1, grgbInverse);
  989.                 giColorRight = 0;
  990.                 break;
  991.         }
  992.     
  993.         gfModeRight = iMode;
  994.         ColorLRUpdate(FALSE);
  995.     }
  996.     
  997.     
  998.     
  999.     /************************************************************************
  1000.     * SetScreenColor
  1001.     *
  1002.     *
  1003.     * History:
  1004.     *
  1005.     ************************************************************************/
  1006.     
  1007.     VOID SetScreenColor(
  1008.         DWORD rgb)
  1009.     {
  1010.         DWORD rgbInverse;
  1011.         HDC hdcTemp;
  1012.         HBITMAP hbmOld;
  1013.         HDC hdcANDTemp;
  1014.         HBITMAP hbmANDOld;
  1015.     
  1016.         rgb = MyGetNearestColor(rgb, FALSE);
  1017.     
  1018.         /*
  1019.          * Because we are about to change the screen color, separate
  1020.          * out the XOR mask (but only for icons/cursors).
  1021.          */
  1022.         if (giColorPalType != FT_BITMAP) {
  1023.             if (gpImageCur) {
  1024.                 ImageDCSeparate(ghdcImage, gcxImage, gcyImage, ghdcANDMask,
  1025.                         grgbScreen);
  1026.     
  1027.                 /*
  1028.                  * Is there a pending undo buffer?  If so, it must be
  1029.                  * changed as well or an undo that is done after a screen
  1030.                  * color change will restore the wrong colors!
  1031.                  */
  1032.                 if (ghbmUndo) {
  1033.                     /*
  1034.                      * Create some temporary DC's to use when separating
  1035.                      * out the undo buffer's masks.  These will be deleted
  1036.                      * a little later.
  1037.                      */
  1038.                     hdcTemp = CreateCompatibleDC(ghdcImage);
  1039.                     hbmOld = SelectObject(hdcTemp, ghbmUndo);
  1040.                     hdcANDTemp = CreateCompatibleDC(ghdcANDMask);
  1041.                     hbmANDOld = SelectObject(hdcANDTemp, ghbmUndoMask);
  1042.     
  1043.                     /*
  1044.                      * Separate out the undo buffer's colors, before
  1045.                      * changing the screen color.  It will be combined
  1046.                      * later.
  1047.                      */
  1048.                     ImageDCSeparate(hdcTemp, gcxImage, gcyImage, hdcANDTemp,
  1049.                             grgbScreen);
  1050.                 }
  1051.             }
  1052.         }
  1053.     
  1054.         if (ghbrScreen)
  1055.             DeleteObject(ghbrScreen);
  1056.     
  1057.         ghbrScreen = CreateSolidBrush(rgb);
  1058.         grgbScreen = rgb;
  1059.     
  1060.         if (ghbrInverse)
  1061.             DeleteObject(ghbrInverse);
  1062.     
  1063.         rgbInverse = ComputeInverseColor(rgb);
  1064.         ghbrInverse = CreateSolidBrush(rgbInverse);
  1065.         grgbInverse = rgbInverse;
  1066.     
  1067.         /*
  1068.          * For icons and cursors, we might need to update a few more things.
  1069.          */
  1070.         if (giColorPalType != FT_BITMAP) {
  1071.             /*
  1072.              * Recombine the XOR and AND images now that there is a new screen
  1073.              * color.  This updates the image DC with the new color properly.
  1074.              */
  1075.             if (gpImageCur) {
  1076.                 ImageDCCombine(ghdcImage, gcxImage, gcyImage, ghdcANDMask);
  1077.     
  1078.                 /*
  1079.                  * Is there a pending undo buffer?  If so, it has to be
  1080.                  * recombined with the new screen color.
  1081.                  */
  1082.                 if (ghbmUndo) {
  1083.                     ImageDCCombine(hdcTemp, gcxImage, gcyImage, hdcANDTemp);
  1084.     
  1085.                     /*
  1086.                      * Clean up the DC's that were allocated a little earlier.
  1087.                      */
  1088.                     SelectObject(hdcANDTemp, hbmANDOld);
  1089.                     DeleteDC(hdcANDTemp);
  1090.                     SelectObject(hdcTemp, hbmOld);
  1091.                     DeleteDC(hdcTemp);
  1092.                 }
  1093.             }
  1094.     
  1095.             /*
  1096.              * Reset the colors on the mouse buttons, just in case a screen
  1097.              * or inverse screen color was assigned to either of them.
  1098.              */
  1099.             SetLeftColor(giColorLeft, gfModeLeft);
  1100.             SetRightColor(giColorRight, gfModeRight);
  1101.     
  1102.             InvalidateRect(GetDlgItem(ghwndColor, DID_COLORBOX), NULL, TRUE);
  1103.         }
  1104.     
  1105.         ViewUpdate();
  1106.     }
  1107.     
  1108.     
  1109.     
  1110.     /************************************************************************
  1111.     * MyCreateSolidBrush
  1112.     *
  1113.     *
  1114.     * History:
  1115.     *
  1116.     ************************************************************************/
  1117.     
  1118.     STATICFN HBRUSH NEAR MyCreateSolidBrush(
  1119.         DWORD rgb)
  1120.     {
  1121.         HDC hdc;
  1122.         HDC hdcMem;
  1123.         HBRUSH hbr;
  1124.         HBRUSH hbrOld;
  1125.         HBITMAP hbmPat;
  1126.         HBITMAP hbmOld;
  1127.     
  1128.         /*
  1129.          * First, create a brush for the given RGB value.
  1130.          */
  1131.         hbr = CreateSolidBrush(rgb);
  1132.     
  1133.         /*
  1134.          * Create a temporary memory DC.
  1135.          */
  1136.         hdc = GetDC(ghwndMain);
  1137.         hdcMem = CreateCompatibleDC(hdc);
  1138.     
  1139.         /*
  1140.          * Create a temporary bitmap.
  1141.          */
  1142.         hbmPat = MyCreateBitmap(hdc, 8, 8, gnColorPalColors);
  1143.         ReleaseDC(ghwndMain, hdc);
  1144.     
  1145.         /*
  1146.          * Draw the (possibly) dithered pattern on the temporary bitmap.
  1147.          */
  1148.         hbmOld = SelectObject(hdcMem, hbmPat);
  1149.         hbrOld = SelectObject(hdcMem, hbr);
  1150.         PatBlt(hdcMem, 0, 0, 8, 8, PATCOPY);
  1151.         SelectObject(hdcMem, hbrOld);
  1152.         SelectObject(hdcMem, hbmOld);
  1153.         DeleteDC(hdcMem);
  1154.     
  1155.         /*
  1156.          * Delete the first brush.
  1157.          */
  1158.         DeleteObject(hbr);
  1159.     
  1160.         /*
  1161.          * Now create a pattern brush out of the (dithered) bitmap.
  1162.          */
  1163.         hbr = CreatePatternBrush(hbmPat);
  1164.     
  1165.         DeleteObject(hbmPat);
  1166.     
  1167.         /*
  1168.          * Return the pattern brush.
  1169.          */
  1170.         return hbr;
  1171.     }
  1172.     
  1173.     
  1174.     
  1175.     /************************************************************************
  1176.     * MyGetNearestColor
  1177.     *
  1178.     * This function returns the RGB value of the nearest color to the
  1179.     * specified RGB value.  If fMonoOK is TRUE, it takes into account
  1180.     * the number of colors of the current image being edited.  In other
  1181.     * words, it will return the nearest solid color for a device that
  1182.     * has the number of colors of the current image.
  1183.     *
  1184.     * Arguments:
  1185.     *   DWORD rgb    - RGB value of the color.
  1186.     *   BOOL fMonoOK - TRUE if the returned color should be mapped to a
  1187.     *                  color in a monochrome palette, if the current image
  1188.     *                  is monochrome.  A value of FALSE will return a
  1189.     *                  color mapped to the closest color in a 16 color
  1190.     *                  palette.
  1191.     *
  1192.     * History:
  1193.     *
  1194.     ************************************************************************/
  1195.     
  1196.     STATICFN DWORD NEAR MyGetNearestColor(
  1197.         DWORD rgb,
  1198.         BOOL fMonoOK)
  1199.     {
  1200.         HDC hdc;
  1201.         HDC hdcMem;
  1202.         DWORD rgbNearest;
  1203.         HBITMAP hbmMem;
  1204.         HBITMAP hbmOld;
  1205.     
  1206.         hdc = GetDC(ghwndMain);
  1207.         hdcMem = CreateCompatibleDC(hdc);
  1208.         hbmMem = MyCreateBitmap(hdc, 1, 1, (fMonoOK) ? gnColorPalColors : 16);
  1209.         hbmOld = SelectObject(hdcMem, hbmMem);
  1210.         rgbNearest = GetNearestColor(hdcMem, rgb);
  1211.         SelectObject(hdcMem, hbmOld);
  1212.         DeleteObject(hbmMem);
  1213.         DeleteDC(hdcMem);
  1214.         ReleaseDC(ghwndMain, hdc);
  1215.     
  1216.         return rgbNearest;
  1217.     }
  1218.     
  1219.     
  1220.     
  1221.     /************************************************************************
  1222.     * ComputeInverseColor
  1223.     *
  1224.     * Computes the inverse value of a given rgb color.
  1225.     *
  1226.     * Arguments:
  1227.     *
  1228.     * History:
  1229.     *
  1230.     ************************************************************************/
  1231.     
  1232.     STATICFN DWORD NEAR ComputeInverseColor(
  1233.         DWORD rgb)
  1234.     {
  1235.         HBITMAP hTempBit1;
  1236.         HBITMAP hTempBit2;
  1237.         HDC hTempDC1;
  1238.         HDC hTempDC2;
  1239.         HDC hdc;
  1240.         HANDLE hOldObj1;
  1241.         HANDLE hOldObj2;
  1242.         DWORD rgbInv;
  1243.     
  1244.         hdc = GetDC(ghwndMain);
  1245.         hTempDC1 = CreateCompatibleDC(hdc);
  1246.         hTempDC2 = CreateCompatibleDC(hdc);
  1247.     
  1248.         /* create two temporary 1x1, 16 color bitmaps */
  1249.         hTempBit1 = MyCreateBitmap(hdc, 1, 1, 16);
  1250.         hTempBit2 = MyCreateBitmap(hdc, 1, 1, 16);
  1251.     
  1252.         ReleaseDC(ghwndMain, hdc);
  1253.     
  1254.         hOldObj1 = SelectObject(hTempDC1, hTempBit1);
  1255.         hOldObj2 = SelectObject(hTempDC2, hTempBit2);
  1256.     
  1257.         /* method for getting inverse color : set the given pixel (rgb) on
  1258.          * one DC. Now blt it to the other DC using a SRCINVERT rop.
  1259.          * This yields a pixel of the inverse color on the destination DC
  1260.          */
  1261.         SetPixel(hTempDC1, 0, 0, rgb);
  1262.         PatBlt(hTempDC2, 0, 0, 1, 1, WHITENESS);
  1263.         BitBlt(hTempDC2, 0, 0, 1, 1, hTempDC1, 0, 0, SRCINVERT);
  1264.         rgbInv = GetPixel(hTempDC2, 0, 0);
  1265.     
  1266.         /* clean up ... */
  1267.         SelectObject(hTempDC1, hOldObj1);
  1268.         SelectObject(hTempDC2, hOldObj2);
  1269.         DeleteObject(hTempBit1);
  1270.         DeleteObject(hTempBit2);
  1271.         DeleteDC(hTempDC1);
  1272.         DeleteDC(hTempDC2);
  1273.     
  1274.         /* ...and return the inverted RGB value */
  1275.         return rgbInv;
  1276.     }
  1277.     
  1278.     
  1279.     
  1280.     /************************************************************************
  1281.     * SetColorPalette
  1282.     *
  1283.     *
  1284.     * History:
  1285.     *
  1286.     ************************************************************************/
  1287.     
  1288.     VOID SetColorPalette(
  1289.         INT nColors,
  1290.         INT iType,
  1291.         BOOL fForce)
  1292.     {
  1293.         /*
  1294.          * Quit if nothing changed (unless they are forcing it to be updated).
  1295.          */
  1296.         if (!fForce && nColors == gnColorPalColors && iType == giColorPalType)
  1297.             return;
  1298.     
  1299.         /*
  1300.          * Set the globals that all the color palette routines use.
  1301.          */
  1302.         gnColorPalColors = nColors;
  1303.         giColorPalType = iType;
  1304.     
  1305.         if (gnColorPalColors == 2)
  1306.             gargbCurrent = gargbMono;
  1307.         else
  1308.             gargbCurrent = gargbColor;
  1309.     
  1310.         ShowWindow(GetDlgItem(ghwndColor, DID_COLORSCREENLABEL),
  1311.                 (giColorPalType == FT_BITMAP) ? SW_HIDE : SW_SHOW);
  1312.         ShowWindow(GetDlgItem(ghwndColor, DID_COLORINVERSELABEL),
  1313.                 (giColorPalType == FT_BITMAP) ? SW_HIDE : SW_SHOW);
  1314.     
  1315.         SetLeftColor(1, MODE_COLOR);
  1316.         SetRightColor(0, MODE_COLOR);
  1317.     
  1318.         InvalidateRect(GetDlgItem(ghwndColor, DID_COLORBOX), NULL, TRUE);
  1319.     }
  1320.     
  1321.     
  1322.     
  1323.     /************************************************************************
  1324.     * RestoreDefaultColors
  1325.     *
  1326.     *
  1327.     * History:
  1328.     *
  1329.     ************************************************************************/
  1330.     
  1331.     VOID RestoreDefaultColors(VOID)
  1332.     {
  1333.         INT i;
  1334.     
  1335.         for (i = 0; i < COLORSMAX; i++)
  1336.             gargbColor[i] = gargbDefaultColor[i];
  1337.     
  1338.         SetColorPalette(16, giColorPalType, TRUE);
  1339.     }