home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 17.ddi / SAMPLES / DIBVIEW / PALETTE.C_ / PALETTE.C
Encoding:
C/C++ Source or Header  |  1993-02-08  |  34.8 KB  |  1,204 lines

  1. /*************************************************************************
  2.  
  3.       File:  PALETTE.C
  4.  
  5.    Purpose:  Contains routines to display a palette in a popup window.
  6.              Allows the user to scroll around the palette and dump info
  7.              on particular colors in the palette.  Has much the same
  8.              look as the Clipboard's palette dump.
  9.  
  10.  Functions:  PaletteWndProc
  11.              HighlightSquare
  12.              UnHighlightSquare
  13.              PalRowsAndColumns
  14.              SetPaletteWindowsPal
  15.              PalEntriesOnDevice
  16.              GetSystemPalette
  17.              ColorsInPalette
  18.              MyAnimatePalette
  19.              CopyPaletteChangingFlags
  20.  
  21.   Comments:  The routines in this module are provided mostly for
  22.              debugging purposes.  There are definite improvements
  23.              that can be made.  For example, the scroll bars now
  24.              let you scroll way beyond the existing colors in a
  25.              palette.  They should probably be limited to the number
  26.              of rows to be displayed in the palette window.
  27.  
  28.    History:   Date      Reason
  29.              6/ 1/91     Created
  30.             11/15/91     Use LoadString instead of a hardcoded
  31.                          array of strings.  This frees up some
  32.                          DS, and is better for localizing for
  33.                          international markets.
  34.              1/28/92     Added WM_QUERYNEWPALETTE message,
  35.                          and always select palette as
  36.                          a background palette in WM_PAINT.
  37.  
  38. *************************************************************************/
  39.  
  40.  
  41. #include "master.h"
  42.  
  43.  
  44.    // Useful magic numbers.
  45.  
  46. #define PAL_SIZE_DEF       PALSIZE_MEDIUM    // Default palette square size.
  47. #define ID_INFO_CHILD      1                 // Palette information window ID
  48.  
  49.  
  50. int nEntriesPerInch [4] = {15,               // Tiny mode  squares/inch
  51.                            10,               // Small mode squares/inch
  52.                             6,               // Medium mode squares/inch
  53.                             4};              // Large mode squares/inch
  54.  
  55.  
  56.  
  57.  
  58.    // Local function prototypes.
  59.  
  60. int  PalEntriesOnDevice  (HDC hDC);
  61.  
  62. void PalRowsAndColumns  (HWND hWnd,
  63.                           int nSquareSize,
  64.                         LPINT lpnCols,
  65.                         LPINT lpnRows,
  66.                         LPINT lpcxSquare,
  67.                         LPINT lpcySquare);
  68.  
  69. void HighlightSquare     (HDC hDC,
  70.                      HPALETTE hPal,
  71.                          HWND hInfoBar,
  72.                          WORD wEntry,
  73.                           int cxSquare,
  74.                           int cySquare,
  75.                           int nCols,
  76.                           int nColors,
  77.                           int nScroll);
  78.  
  79. void UnHighlightSquare   (HDC hDC,
  80.                          WORD wEntry,
  81.                           int cxSquare,
  82.                           int cySquare,
  83.                           int nCols,
  84.                           int nScroll);
  85.  
  86.  
  87.  
  88.  
  89.  
  90.  
  91. //---------------------------------------------------------------------
  92. //
  93. // Function:   PaletteWndProc
  94. //
  95. // Purpose:    Window procedure for palette child windows.  These
  96. //             windows are responsible for displaying a color palette
  97. //             a-la the Clipboard Viewer.  It also dumps info on each
  98. //             palette color.
  99. //
  100. // Parms:      hWnd    == Handle to this child window.
  101. //             message == Message for window.
  102. //             wParam  == Depends on message.
  103. //             lParam  == Depends on message.
  104. //
  105. // History:   Date      Reason
  106. //             6/01/91  Created
  107. //             1/28/92  Added WM_QUERYNEWPALETTE message,
  108. //                        and always select palette as
  109. //                        a background palette in WM_PAINT.
  110. //
  111. //---------------------------------------------------------------------
  112.  
  113. long FAR PASCAL __export PaletteWndProc (HWND hWnd,
  114.                 UINT message,
  115.                 WPARAM wParam,
  116.                 LPARAM lParam)
  117. {
  118.    switch (message)
  119.       {
  120.       case WM_CREATE:
  121.          {
  122.          HWND      hInfoBar;
  123.          HANDLE    hPalInfo;
  124.  
  125.          hInfoBar = CreateWindow ("static",       // Class
  126.                                   NULL,           // Name
  127.                                        WS_CHILD |      // Styles
  128.                                    WS_VISIBLE |
  129.                                    SS_CENTER,
  130.                                        0,              // x (set in WM_SIZE)
  131.                                        0,              // y (set in WM_SIZE)
  132.                                        100,            // Width (set in WM_SIZE)
  133.                                        30,             // Height (set in WM_SIZE)
  134.                                        hWnd,           // hParent
  135.                                        ID_INFO_CHILD,  // Child Window ID
  136.                                        hInst,          // Instance
  137.                                        NULL);          // Extra information
  138.  
  139.          hPalInfo = GlobalAlloc (GHND, sizeof (PALINFO));
  140.  
  141.          if (hPalInfo)
  142.             {
  143.             LPPALINFO lpPalInfo;
  144.  
  145.             lpPalInfo              = (LPPALINFO) GlobalLock (hPalInfo);
  146.             lpPalInfo->hPal        = NULL;
  147.             lpPalInfo->wEntries    = 0;
  148.             lpPalInfo->nSquareSize = PAL_SIZE_DEF;
  149.             lpPalInfo->hInfoWnd    = hInfoBar;
  150.             lpPalInfo->nRows       = 0;
  151.             lpPalInfo->nCols       = 0;
  152.             lpPalInfo->cxSquare    = 0;
  153.             lpPalInfo->cySquare    = 0;
  154.             lpPalInfo->wEntry      = 0;
  155.             GlobalUnlock (hPalInfo);
  156.             }
  157.  
  158.          SetWindowWord (hWnd, WW_PAL_HPALINFO, hPalInfo);
  159.  
  160.             // Set the palette square size to the default value.
  161.             //  This must be done AFTER the PALINFO structure's
  162.             //  handle is put into the window words.
  163.  
  164.          SendMessage (hWnd, WM_COMMAND, PAL_SIZE_DEF, 0L);
  165.          break;
  166.          }
  167.  
  168.  
  169.  
  170.          // If the window is re-sized, move the information bar (a static
  171.          //  text control) accordingly.
  172.  
  173.       case WM_SIZE:
  174.          {
  175.          HANDLE      hPalInfo;
  176.          LPPALINFO   lpPalInfo;
  177.          HWND        hInfoBar;
  178.          HDC         hDC;
  179.          TEXTMETRIC  tm;
  180.          RECT        rect;
  181.          static BOOL bInSize = FALSE;
  182.  
  183.             // We implement a semaphore here to avoid an
  184.             //  infinte loop.  Scroll bars are set up in
  185.             //  PalRowsAndColumns().  This, in turn, can
  186.             //  effect the size of the window's client area.
  187.             //  Thus, sending the window another WM_SIZE
  188.             //  message.  We ignore this 2nd WM_SIZE message
  189.             //  if we're already processing one.
  190.  
  191.          if (bInSize)
  192.             break;
  193.  
  194.          bInSize = TRUE;
  195.  
  196.  
  197.             // Get a handle to the info bar window.
  198.  
  199.          hPalInfo = GetWindowWord (hWnd, WW_PAL_HPALINFO);
  200.          if (!hPalInfo)
  201.             {
  202.             bInSize = FALSE;
  203.             break;
  204.             }
  205.  
  206.          lpPalInfo = (LPPALINFO) GlobalLock (hPalInfo);
  207.          hInfoBar  = lpPalInfo->hInfoWnd;
  208.  
  209.          PalRowsAndColumns (hWnd, lpPalInfo->nSquareSize,
  210.                             &lpPalInfo->nCols, &lpPalInfo->nRows,
  211.                             &lpPalInfo->cxSquare, &lpPalInfo->cySquare);
  212.  
  213.          GlobalUnlock (hPalInfo);
  214.  
  215.          if (!hInfoBar)
  216.             {
  217.             bInSize = FALSE;
  218.             break;
  219.             }
  220.  
  221.  
  222.             // The size of the info bar is dependent on the size of the
  223.             //  system font.
  224.  
  225.          hDC = GetDC (NULL);
  226.          GetTextMetrics (hDC, &tm);
  227.          ReleaseDC (NULL, hDC);
  228.  
  229.          GetClientRect (hWnd, &rect);
  230.  
  231.             // Now actually move the icon bar.  It should be flush
  232.             //  left with the palette window's client area, and should
  233.             //  be the height of some text.
  234.  
  235.          SetWindowPos (hInfoBar,
  236.                        NULL,
  237.                        0,
  238.                        rect.bottom - tm.tmHeight,
  239.                        rect.right - rect.left,
  240.                        tm.tmHeight,
  241.                        SWP_NOZORDER | SWP_NOACTIVATE);
  242.  
  243.  
  244.             // Clear our semaphore.
  245.  
  246.          bInSize = FALSE;
  247.          break;
  248.          }
  249.  
  250.  
  251.  
  252.       case WM_PAINT:
  253.          {
  254.          RECT        rect;
  255.          HDC         hDC;
  256.          PAINTSTRUCT ps;
  257.          int         nCols;
  258.          int         nColors, i, nPerInch;
  259.          int         cxSquare,  cySquare;
  260.          int         nScroll;
  261.          HPALETTE    hPal, hOldPal = NULL;
  262.          HANDLE      hPalInfo;
  263.          LPPALINFO   lpPalInfo;
  264.          HWND        hInfoBar;
  265.          WORD        wCurrent;
  266.  
  267.  
  268.             // First do some setup.
  269.  
  270.          GetClientRect (hWnd, &rect);
  271.  
  272.          hDC       = BeginPaint (hWnd, &ps);
  273.          nScroll   = GetScrollPos (hWnd, SB_VERT);
  274.          hPalInfo  = GetWindowWord (hWnd, WW_PAL_HPALINFO);
  275.  
  276.          if (!hPalInfo)
  277.             goto ENDPAINT;
  278.  
  279.          lpPalInfo = (LPPALINFO) GlobalLock (hPalInfo);
  280.          nPerInch  = nEntriesPerInch [lpPalInfo->nSquareSize];
  281.          hPal      = lpPalInfo->hPal;
  282.          nColors   = lpPalInfo->wEntries;
  283.          cxSquare  = lpPalInfo->cxSquare;
  284.          cySquare  = lpPalInfo->cySquare;
  285.          wCurrent  = lpPalInfo->wEntry;
  286.          nCols     = lpPalInfo->nCols;
  287.          hInfoBar  = lpPalInfo->hInfoWnd;
  288.          GlobalUnlock (hPalInfo);
  289.  
  290.          assert (nPerInch);
  291.          assert (cxSquare);
  292.          assert (cySquare);
  293.          assert (nCols);
  294.  
  295.  
  296.             // Change our window origin to reflect the current
  297.             //  scroll bar state.
  298.  
  299.          SetWindowOrg (hDC, 0, GetScrollPos (hWnd, SB_VERT) * cySquare);
  300.  
  301.  
  302.             // Let's paint -- first realize the palette.  Note that
  303.             //  we ALWAYS realize the palette as if it were a background
  304.             //  palette (i.e. the last parm is TRUE).  We do this, since
  305.             //  we will already be the foreground palette if we are
  306.             //  supposed to be (because we handle the WM_QUERYNEWPALETTE
  307.             //  message).
  308.  
  309.          if (hPal)
  310.             hOldPal = SelectPalette (hDC, hPal, TRUE);
  311.  
  312.          else
  313.             {
  314.             char szErr[20];
  315.  
  316.             szErr[0] = '\0';
  317.             LoadString (hInst, IDS_PAL_NOPAL, szErr, sizeof (szErr)-1);
  318.  
  319.             TextOut (hDC, 0, 0, szErr, lstrlen (szErr));
  320.             goto ENDPAINT;
  321.             }
  322.  
  323.          RealizePalette (hDC);
  324.  
  325.  
  326.             // Go through the palette displaying each color
  327.             //  as a rectangle.
  328.  
  329.          for (i = 0;  i < nColors;  i++)
  330.             {
  331.             HBRUSH hBrush, hOldBrush;
  332.  
  333.             hBrush = CreateSolidBrush (PALETTEINDEX (i));
  334.  
  335.             if (hBrush)
  336.                {
  337.                POINT pt;
  338.  
  339.                hOldBrush = SelectObject (hDC, hBrush);
  340.  
  341.                pt.x = (i % nCols) * cxSquare;
  342.                pt.y = (i / nCols) * cySquare;
  343.  
  344.                Rectangle (hDC,
  345.                           pt.x,
  346.                           pt.y,
  347.                           pt.x + cxSquare,
  348.                           pt.y + cySquare);
  349.  
  350.                SelectObject (hDC, hOldBrush);
  351.                DeleteObject (hBrush);
  352.                }
  353.             }
  354.  
  355.  
  356.             // Highlight the currently selected palette square,
  357.             //  and change the info window to reflect this
  358.             //  square.
  359.  
  360.          HighlightSquare (hDC,
  361.                           hPal,
  362.                           hInfoBar,
  363.                           wCurrent,
  364.                           cxSquare,
  365.                           cySquare,
  366.                           nCols,
  367.                           nColors,
  368.                           nScroll);
  369.  
  370.  
  371.             // Clean up.
  372.  
  373.          if (hOldPal)
  374.             SelectPalette (hDC, hOldPal, FALSE);
  375.  
  376.  
  377. ENDPAINT:
  378.  
  379.          EndPaint (hWnd, &ps);
  380.          break;
  381.          }
  382.  
  383.  
  384.  
  385.          // If the user hits the left mouse button, change the
  386.          //  selected palette entry.
  387.  
  388.       case WM_LBUTTONDOWN:
  389.          {
  390.          HDC       hDC;
  391.          HANDLE    hPalInfo;
  392.          LPPALINFO lpPalInfo;
  393.          int       nRow, nCol;
  394.          int       nScroll;
  395.  
  396.          hPalInfo = GetWindowWord (hWnd, WW_PAL_HPALINFO);
  397.          if (!hPalInfo)
  398.             break;
  399.  
  400.          nScroll   = GetScrollPos (hWnd, SB_VERT);
  401.          lpPalInfo = (LPPALINFO) GlobalLock (hPalInfo);
  402.          nRow      = (HIWORD (lParam) ) / lpPalInfo->cySquare;
  403.          nCol      = LOWORD (lParam) / lpPalInfo->cxSquare;
  404.          hDC       = GetDC (hWnd);
  405.  
  406.          UnHighlightSquare (hDC,
  407.                             lpPalInfo->wEntry,
  408.                             lpPalInfo->cxSquare,
  409.                             lpPalInfo->cySquare,
  410.                             lpPalInfo->nCols,
  411.                             nScroll);
  412.  
  413.  
  414.             // Determine which entry is the new highlighted entry.
  415.             //  Take into account the scroll bar position.
  416.  
  417.          lpPalInfo->wEntry = nRow * lpPalInfo->nCols + nCol +
  418.                               lpPalInfo->nCols * nScroll;
  419.  
  420.  
  421.             // Don't let the selected palette entry be greater
  422.             //  than the # of palette entries available.
  423.  
  424.          if (lpPalInfo->wEntry >= lpPalInfo->wEntries)
  425.             lpPalInfo->wEntry = lpPalInfo->wEntries - 1;
  426.  
  427.          HighlightSquare (hDC,
  428.                           lpPalInfo->hPal,
  429.                           lpPalInfo->hInfoWnd,
  430.                           lpPalInfo->wEntry,
  431.                           lpPalInfo->cxSquare,
  432.                           lpPalInfo->cySquare,
  433.                           lpPalInfo->nCols,
  434.                           lpPalInfo->wEntries,
  435.                           nScroll);
  436.  
  437.          ReleaseDC (hWnd, hDC);
  438.          GlobalUnlock (hPalInfo);
  439.          break;
  440.          }
  441.  
  442.  
  443.          // Do that horizontal scroll bar thing.
  444.  
  445.       case WM_VSCROLL:
  446.          {
  447.          HWND      hBar = HIWORD (lParam);      // HWND of scrollbar
  448.          int       yBar;                        // Where scrollbar is now.
  449.          int       nMin;                        // Minumum scroll bar value.
  450.          int       nMax;                        // Maximum scroll bar value.
  451.          int       dy;                          // How much to move.
  452.          int       cyClient;                    // Width of client area.
  453.          int       cySquare;                    // Height of a palette square.
  454.          RECT      rect;                        // Client area.
  455.          HANDLE    hPalInfo;                    // Handle to PALINFO struct.
  456.          LPPALINFO lpPalInfo;                   // Pointer to PALINFO struct.
  457.  
  458.  
  459.          hPalInfo = GetWindowWord (hWnd, WW_PAL_HPALINFO);
  460.          if (!hPalInfo)
  461.             break;
  462.  
  463.          lpPalInfo = (LPPALINFO) GlobalLock (hPalInfo);
  464.          cySquare  = lpPalInfo->cySquare;
  465.          GlobalUnlock (hPalInfo);
  466.  
  467.          if (!hBar)
  468.             hBar = hWnd;
  469.  
  470.          GetClientRect (hWnd, &rect);
  471.          GetScrollRange (hBar, SB_VERT, &nMin, &nMax);
  472.  
  473.          cyClient = rect.bottom - rect.top;
  474.          yBar     = GetScrollPos (hBar, SB_VERT);
  475.  
  476.          switch (wParam)
  477.             {
  478.             case SB_LINEDOWN:             // One line right.
  479.                dy = 1;
  480.                break;
  481.  
  482.             case SB_LINEUP:               // One line left.
  483.                dy = -1;
  484.                break;
  485.  
  486.             case SB_PAGEDOWN:             // One page right.
  487.                dy = cyClient / cySquare;
  488.                break;
  489.  
  490.             case SB_PAGEUP:               // One page left.
  491.                dy = -cyClient / cySquare;
  492.                break;
  493.  
  494.             case SB_THUMBPOSITION:        // Absolute position.
  495.                dy = LOWORD (lParam) - yBar;
  496.                break;
  497.  
  498.             default:                      // No change.
  499.                dy = 0;
  500.                break;
  501.             }
  502.  
  503.          if (dy)
  504.             {
  505.             yBar += dy;
  506.  
  507.             if (yBar < nMin)
  508.                {
  509.                dy  -= yBar - nMin;
  510.                yBar = nMin;
  511.                }
  512.  
  513.             if (yBar > nMax)
  514.                {
  515.                dy  -= yBar - nMax;
  516.                yBar = nMax;
  517.                }
  518.  
  519.             if (dy)
  520.                {
  521.                SetScrollPos (hBar, SB_VERT, yBar, TRUE);
  522.                InvalidateRect (hWnd, NULL, TRUE);
  523.                UpdateWindow (hWnd);
  524.                }
  525.             }
  526.          break;
  527.          }
  528.  
  529.  
  530.  
  531.          // If the system palette changes, we need to re-draw, re-mapping
  532.          //  our palette colors.  Otherwise they will be completely
  533.          //  wrong (and if any palette animation is going on, they
  534.          //  will start animating)!!
  535.  
  536.       case WM_PALETTECHANGED:
  537.          if (hWnd != (HWND) wParam)
  538.             InvalidateRect (hWnd, NULL, FALSE);
  539.          break;
  540.  
  541.  
  542.  
  543.          // If we get the focus on this window, we want to insure
  544.          //  that we have the foreground palette.
  545.  
  546.       case WM_QUERYNEWPALETTE:
  547.          {
  548.          HANDLE    hPalInfo;
  549.          LPPALINFO lpPalInfo;
  550.          HPALETTE  hPal, hOldPal;
  551.          HDC       hDC;
  552.  
  553.          hPalInfo  = GetWindowWord (hWnd, WW_PAL_HPALINFO);
  554.          if (!hPalInfo)
  555.             break;
  556.          lpPalInfo = (LPPALINFO) GlobalLock (hPalInfo);
  557.          hPal      = lpPalInfo->hPal;
  558.          GlobalUnlock (hPalInfo);
  559.  
  560.          if (hPal)
  561.             {
  562.             hDC       = GetDC (hWnd);
  563.             hOldPal   = SelectPalette (hDC, hPal, FALSE);
  564.  
  565.             RealizePalette (hDC);
  566.             SelectPalette (hDC, hOldPal, FALSE);
  567.             ReleaseDC (hWnd, hDC);
  568.  
  569.             InvalidateRect (hWnd, NULL, FALSE);
  570.             return TRUE;
  571.             }
  572.          break;
  573.          }
  574.  
  575.  
  576.          // Window's going away, destroy the palette, and the PALINFO
  577.          //  structure.
  578.  
  579.       case WM_DESTROY:
  580.          {
  581.          HANDLE    hPalInfo;
  582.          LPPALINFO lpPalInfo;
  583.  
  584.          hPalInfo = GetWindowWord (hWnd, WW_PAL_HPALINFO);
  585.  
  586.          if (!hPalInfo)
  587.             break;
  588.  
  589.          lpPalInfo = (LPPALINFO) GlobalLock (hPalInfo);
  590.  
  591.          if (lpPalInfo->hPal)
  592.             DeleteObject (lpPalInfo->hPal);
  593.  
  594.          GlobalUnlock (hPalInfo);
  595.          GlobalFree (hPalInfo);
  596.          SetWindowWord (hWnd, WW_PAL_HPALINFO, NULL);
  597.          break;
  598.          }
  599.  
  600.  
  601.  
  602.          // If we're getting the focus, our palette may not be the
  603.          //  currently selected palette.  Therefore, force a repaint.
  604.  
  605.       case WM_SETFOCUS:
  606.      InvalidateRect (hWnd, NULL, TRUE);
  607.          break;
  608.  
  609.  
  610.  
  611.          // Something was picked off a menu.  If the user is asking
  612.          //  to change the way we represent the palette, uncheck the
  613.          //  old way, check the new way, and force a repaint.  If not,
  614.          //  pass the value on to DefWindowProc().
  615.  
  616.       case WM_COMMAND:
  617.          {
  618.          if ((wParam >= IDM_PAL_TINY) && (wParam <= IDM_PAL_LARGE))
  619.             {
  620.             HANDLE    hPalInfo;
  621.             LPPALINFO lpPalInfo;
  622.             HMENU     hMenu;
  623.             WORD      wOldItem;
  624.  
  625.             hPalInfo = GetWindowWord (hWnd, WW_PAL_HPALINFO);
  626.             hMenu    = GetMenu (hWnd);
  627.  
  628.             if (!hPalInfo)
  629.                break;
  630.  
  631.             lpPalInfo = (LPPALINFO) GlobalLock (hPalInfo);
  632.             wOldItem  = lpPalInfo->nSquareSize;
  633.  
  634.             CheckMenuItem (hMenu,
  635.                            wOldItem + IDM_PAL_TINY,
  636.                            MF_BYCOMMAND | MF_UNCHECKED);
  637.  
  638.             CheckMenuItem (hMenu,
  639.                            wParam,
  640.                            MF_BYCOMMAND | MF_CHECKED);
  641.  
  642.  
  643.             lpPalInfo->nSquareSize = wParam - IDM_PAL_TINY;
  644.             PalRowsAndColumns (hWnd, lpPalInfo->nSquareSize,
  645.                                &lpPalInfo->nCols, &lpPalInfo->nRows,
  646.                                &lpPalInfo->cxSquare, &lpPalInfo->cySquare);
  647.  
  648.             GlobalUnlock (hPalInfo);
  649.  
  650.             InvalidateRect (hWnd, NULL, TRUE);
  651.             }
  652.          else
  653.             return DefWindowProc (hWnd, message, wParam, lParam);
  654.  
  655.          break;
  656.          }
  657.  
  658.  
  659.  
  660.       default:
  661.          return DefWindowProc (hWnd, message, wParam, lParam);
  662.       }
  663.  
  664.     return (NULL);
  665. }
  666.  
  667.  
  668.  
  669.  
  670. //---------------------------------------------------------------------
  671. //
  672. // Function:   HighlightSquare
  673. //
  674. // Purpose:    Highlight the currently selected palette entry, and
  675. //             change the info bar to reflect it.
  676. //
  677. // Parms:      hDC      == DC where we want to highlight a pal. square.
  678. //             hPal     == Handle to the palette we're displaying info on.
  679. //             hInfoBar == Handle to the information bar window.
  680. //             wEntry   == Entry to highlight.
  681. //             cxSquare == Width a a palette square.
  682. //             cySquare == Height of a palette square.
  683. //             nCols    == # of columns currently displayed in window.
  684. //             nColors  == # of colors in the palette.
  685. //             nScroll  == # of rows the window has scrolled.
  686. //
  687. // History:   Date      Reason
  688. //             6/01/91  Created
  689. //            11/18/91  Added call to LoadString instead of
  690. //                      using a hardcoded array of strings.
  691. //
  692. //---------------------------------------------------------------------
  693.  
  694. void HighlightSquare (HDC hDC,
  695.                  HPALETTE hPal,
  696.                      HWND hInfoBar,
  697.                      WORD wEntry,
  698.                       int cxSquare,
  699.                       int cySquare,
  700.                       int nCols,
  701.                       int nColors,
  702.                       int nScroll)
  703. {
  704.    RECT         rect;
  705.    HBRUSH       hBrush;
  706.    PALETTEENTRY pe;
  707.    char         szStr [70], szFlag [20], szFormat [70];
  708.    DWORD        dwOrg;
  709.  
  710.    rect.left   = (wEntry % nCols) * cxSquare;
  711.    rect.top    = (wEntry / nCols) * cySquare;
  712.    rect.right  = rect.left + cxSquare;
  713.    rect.bottom = rect.top  + cySquare;
  714.    hBrush      = CreateHatchBrush (HS_BDIAGONAL,
  715.                                     GetSysColor (COLOR_HIGHLIGHT));
  716.  
  717.    dwOrg = SetWindowOrg (hDC, 0, nScroll * cySquare);
  718.    FrameRect (hDC, &rect, hBrush);
  719.    dwOrg = SetWindowOrg (hDC, LOWORD (dwOrg), HIWORD (dwOrg));
  720.  
  721.    GetPaletteEntries (hPal, wEntry, 1, &pe);
  722.  
  723.       // If the palette entry we just got is just an index into the
  724.       //  system palette, get it's RGB value.
  725.  
  726.    if (pe.peFlags == PC_EXPLICIT)
  727.       {
  728.       COLORREF cref;
  729.       HPALETTE hOldPal;
  730.  
  731.       cref       = PALETTEINDEX ((WORD) pe.peRed + (pe.peGreen << 4));
  732.       hOldPal    = SelectPalette (hDC, hPal, FALSE);
  733.       cref       = GetNearestColor (hDC, cref);
  734.       pe.peRed   = (BYTE)  (cref & 0x0000FF);
  735.       pe.peGreen = (BYTE) ((cref & 0x00FF00) >> 8);
  736.       pe.peBlue  = (BYTE) ((cref & 0xFF0000) >> 16);
  737.  
  738.       SelectPalette (hDC, hOldPal, FALSE);
  739.       }
  740.  
  741.  
  742.       // Decode the palette flag by loading the appropriate description
  743.       //  string from the string table.  Note that we also keep the
  744.       //  format string for wsprintf() in the string table.  Don't
  745.       //  change wsprintf() below without also examining IDS_PAL_DISPRGB
  746.       //  in DIBVIEW.RC's string table!
  747.  
  748.    szFlag[0] = '\0';
  749.    LoadString (hInst, IDS_PAL_RGB + pe.peFlags, szFlag, sizeof (szFlag)-1);
  750.  
  751.    if (LoadString (hInst, IDS_PAL_DISPRGB, szFormat, sizeof (szFormat-1)))
  752.       wsprintf (szStr, szFormat,
  753.                   pe.peRed, pe.peGreen, pe.peBlue,
  754.                   wEntry + 1, nColors,
  755.                   (LPSTR) szFlag);
  756.  
  757.  
  758.    SetWindowText (hInfoBar, szStr);
  759.  
  760.    DeleteObject (hBrush);
  761. }
  762.  
  763.  
  764.  
  765.  
  766.  
  767. //---------------------------------------------------------------------
  768. //
  769. // Function:   UnHighlightSquare
  770. //
  771. // Purpose:    Un-Highlight a palette entry.
  772. //
  773. // Parms:      hDC      == DC where we want to unhighlight a pal. square.
  774. //             wEntry   == Entry to highlight.
  775. //             cxSquare == Width a a palette square.
  776. //             cySquare == Height of a palette square.
  777. //             nCols    == # of columns currently displayed in window.
  778. //             nScroll  == # of rows the window has scrolled.
  779. //
  780. // History:   Date      Reason
  781. //             6/01/91  Created
  782. //
  783. //---------------------------------------------------------------------
  784.  
  785. void UnHighlightSquare (HDC hDC,
  786.                        WORD wEntry,
  787.                         int cxSquare,
  788.                         int cySquare,
  789.                         int nCols,
  790.                         int nScroll)
  791. {
  792.    RECT  rect;
  793.    DWORD dwOrg;
  794.  
  795.    rect.left   = (wEntry % nCols) * cxSquare;
  796.    rect.top    = (wEntry / nCols) * cySquare;
  797.    rect.right  = rect.left + cxSquare;
  798.    rect.bottom = rect.top  + cySquare;
  799.  
  800.    dwOrg = SetWindowOrg (hDC, 0, nScroll * cySquare);
  801.    FrameRect (hDC, &rect, GetStockObject (BLACK_BRUSH));
  802.    SetWindowOrg (hDC, LOWORD (dwOrg), HIWORD (dwOrg));
  803. }
  804.  
  805.  
  806.  
  807.  
  808.  
  809. //---------------------------------------------------------------------
  810. //
  811. // Function:   PalRowsAndColumns
  812. //
  813. // Purpose:    Given a square size, determine the # of Rows/Columns
  814. //             that will fit in the client area of a palette window.
  815. //             Also, set the # of pixels per square for height/width.
  816. //             Finally, set up the scroll bar.
  817. //
  818. // Parms:      hWnd       == Window we're doing this for.
  819. //             nSquareSize== Size to make squares (offset into
  820. //                            nEntriesPerInch array).
  821. //             lpnCols    == far ptr to # Cols to display, set dependent
  822. //                            on nSquareSize and dimeinsions of window.
  823. //             lpnRows    == Ditto -- for # of rows to display.
  824. //             lpcxSquare == Ditto -- width of a palette square.
  825. //             lpcySquare == Ditto -- height of a palette square.
  826. //
  827. // History:   Date      Reason
  828. //             6/01/91  Created
  829. //
  830. //---------------------------------------------------------------------
  831.  
  832. void PalRowsAndColumns  (HWND hWnd,
  833.                           int nSquareSize,
  834.                         LPINT lpnCols,
  835.                         LPINT lpnRows,
  836.                         LPINT lpcxSquare,
  837.                         LPINT lpcySquare)
  838. {
  839.    HDC  hDC;
  840.    int  cxInch, cyInch;
  841.    int  nPerInch;
  842.    RECT rect;
  843.  
  844.    hDC    = GetDC (NULL);
  845.    cxInch = GetDeviceCaps (hDC, LOGPIXELSX);
  846.    cyInch = GetDeviceCaps (hDC, LOGPIXELSY);
  847.    ReleaseDC (NULL, hDC);
  848.  
  849.    GetClientRect (hWnd, &rect);
  850.  
  851.    nPerInch    = nEntriesPerInch [nSquareSize];
  852.    *lpcxSquare = cxInch / nPerInch;
  853.    *lpcySquare = cyInch / nPerInch;
  854.  
  855.    if (*lpcxSquare == 0)
  856.       *lpcxSquare = 1;
  857.  
  858.    if (*lpcySquare == 0)
  859.       *lpcySquare = 1;
  860.  
  861.  
  862.       // Translate palette squares per inch into # of columns,
  863.       //  and pixels per square.  Insure that we have at least
  864.       //  one column, and 1 pix per side on our squares.
  865.  
  866.    *lpnCols = (int) ((((long) rect.right - rect.left) * nPerInch) / cxInch);
  867.    *lpnRows = (int) ((((long) rect.bottom - rect.top) * nPerInch) / cyInch);
  868.  
  869.    if (!*lpnCols)
  870.       *lpnCols = 1;
  871.  
  872.    if (!*lpnRows)
  873.       *lpnRows = 1;
  874. }
  875.  
  876.  
  877.  
  878.  
  879.  
  880. //---------------------------------------------------------------------
  881. //
  882. // Function:   SetPaletteWindowsPal
  883. //
  884. // Purpose:    Set a palette Window's hPal in its PALINFO structure.
  885. //             This sets the palette that will be displayed in the
  886. //             given window.  Also sets up the other structure members
  887. //             of the PALINFO structure.
  888. //
  889. // Parms:      hWnd == Window we're going to display palette in.
  890. //             hPal == Palette to display in the window.
  891. //
  892. // History:   Date      Reason
  893. //             6/01/91  Created
  894. //
  895. //---------------------------------------------------------------------
  896.  
  897. void SetPaletteWindowsPal (HWND hWnd, HPALETTE hPal)
  898. {
  899.    HANDLE    hPalInfo;
  900.    LPPALINFO lpPalInfo;
  901.  
  902.    if (!hPal)
  903.       return;
  904.  
  905.    hPalInfo = GetWindowWord (hWnd, WW_PAL_HPALINFO);
  906.  
  907.    if (hPalInfo)
  908.       {
  909.       lpPalInfo           = (LPPALINFO) GlobalLock (hPalInfo);
  910.       lpPalInfo->hPal     = hPal;
  911.       lpPalInfo->wEntries = ColorsInPalette (hPal);
  912.  
  913.       GlobalUnlock (hPalInfo);
  914.       }
  915. }
  916.  
  917.  
  918.  
  919. //---------------------------------------------------------------------
  920. //
  921. // Function:   PalEntriesOnDevice
  922. //
  923. // Purpose:    Returns the number of colors a device supports.
  924. //
  925. // Parms:      hDC == DC for the device we want # of colors for.
  926. //
  927. // Returns:    # of colors that the given device can represent.
  928. //
  929. // History:   Date      Reason
  930. //             6/01/91  Created
  931. //
  932. //---------------------------------------------------------------------
  933.  
  934. int PalEntriesOnDevice (HDC hDC)
  935. {
  936.    int nColors;
  937.  
  938.       // Find out the number of palette entries on this
  939.       //  defice.
  940.  
  941.    nColors = GetDeviceCaps (hDC, SIZEPALETTE);
  942.  
  943.  
  944.       // For non-palette devices, we'll use the # of system
  945.       //  colors for our palette size.
  946.  
  947.    if (!nColors)
  948.       nColors = GetDeviceCaps (hDC, NUMCOLORS);
  949.  
  950.    assert (nColors);
  951.  
  952.    return nColors;
  953. }
  954.  
  955.  
  956.  
  957.  
  958.  
  959. //---------------------------------------------------------------------
  960. //
  961. // Function:   GetSystemPalette
  962. //
  963. // Purpose:    This routine returns a handle to a palette which represents
  964. //             the system palette (each entry is an offset into the system
  965. //             palette instead of an RGB with a flag of PC_EXPLICIT).
  966. //             Useful for dumping the system palette.
  967. //
  968. // Parms:      None
  969. //
  970. // Returns:    Handle to a palette consisting of the system palette
  971. //             colors.
  972. //
  973. // History:   Date      Reason
  974. //             6/01/91  Created
  975. //
  976. //---------------------------------------------------------------------
  977.  
  978. HPALETTE GetSystemPalette (void)
  979. {
  980.    HDC           hDC;
  981.    HPALETTE      hPal = NULL;
  982.    HANDLE        hLogPal;
  983.    LPLOGPALETTE  lpLogPal;
  984.    int           i, nColors;
  985.  
  986.  
  987.       // Find out how many palette entries we want.
  988.  
  989.    hDC = GetDC (NULL);
  990.    if (!hDC)
  991.       {
  992.       DIBError (ERR_GETDC);
  993.       return NULL;
  994.       }
  995.  
  996.    nColors = PalEntriesOnDevice (hDC);
  997.    ReleaseDC (NULL, hDC);
  998.  
  999.  
  1000.       // Allocate room for the palette and lock it.
  1001.  
  1002.    hLogPal = GlobalAlloc (GHND, sizeof (LOGPALETTE) +
  1003.                            nColors * sizeof (PALETTEENTRY));
  1004.  
  1005.    if (!hLogPal)
  1006.       {
  1007.       DIBError (ERR_CREATEPAL);
  1008.       return NULL;
  1009.       }
  1010.  
  1011.    lpLogPal = (LPLOGPALETTE) GlobalLock (hLogPal);
  1012.  
  1013.    lpLogPal->palVersion    = PALVERSION;
  1014.    lpLogPal->palNumEntries = nColors;
  1015.  
  1016.    for (i = 0;  i < nColors;  i++)
  1017.       {
  1018.       lpLogPal->palPalEntry[i].peBlue  = 0;
  1019.       *((LPWORD) (&lpLogPal->palPalEntry[i].peRed)) = i;
  1020.       lpLogPal->palPalEntry[i].peFlags = PC_EXPLICIT;
  1021.       }
  1022.  
  1023.  
  1024.  
  1025.       // Go ahead and create the palette.  Once it's created,
  1026.       //  we no longer need the LOGPALETTE, so free it.
  1027.  
  1028.    hPal = CreatePalette (lpLogPal);
  1029.  
  1030.    GlobalUnlock (hLogPal);
  1031.    GlobalFree (hLogPal);
  1032.  
  1033.    return hPal;
  1034. }
  1035.  
  1036.  
  1037.  
  1038.  
  1039.  
  1040. //---------------------------------------------------------------------
  1041. //
  1042. // Function:   ColorsInPalette
  1043. //
  1044. // Purpose:    Given a handle to a palette, returns the # of colors
  1045. //             in that palette.
  1046. //
  1047. // Parms:      hPal == Handle to palette we want info on.
  1048. //
  1049. // Returns:    # of colors in the palette.
  1050. //
  1051. // History:   Date      Reason
  1052. //             6/01/91  Created
  1053. //
  1054. //---------------------------------------------------------------------
  1055.  
  1056. int ColorsInPalette (HPALETTE hPal)
  1057. {
  1058.    int nColors;
  1059.  
  1060.    if (!hPal)
  1061.       return 0;
  1062.  
  1063.    GetObject (hPal, sizeof (nColors), (LPSTR) &nColors);
  1064.  
  1065.    return nColors;
  1066. }
  1067.  
  1068.  
  1069.  
  1070.  
  1071. //---------------------------------------------------------------------
  1072. //
  1073. // Function:   MyAnimatePalette
  1074. //
  1075. // Purpose:    This routine animates the given palette.  It does this
  1076. //             by moving all the palette entries down one in the palette,
  1077. //             and putting the first entry at the end of the palette (we
  1078. //             could do something different here, like run various shades
  1079. //             of a certain color through the palette, or run random colors
  1080. //             through the palette).
  1081. //
  1082. //             Not really that useful -- it just creates a pretty funky
  1083. //             "psychadelic" effect.  It does show how to do palette
  1084. //             animation, though.
  1085. //
  1086. //             This routine is called by CHILD.C.
  1087. //
  1088. // Parms:      hWnd == Window we're animating.
  1089. //             hPal == Palette we're animating.
  1090. //
  1091. // History:   Date      Reason
  1092. //             6/01/91  Created
  1093. //
  1094. //---------------------------------------------------------------------
  1095.  
  1096. void MyAnimatePalette (HWND hWnd, HPALETTE hPal)
  1097. {
  1098.    HDC            hDC;
  1099.    HANDLE         hPalEntries;
  1100.    LPPALETTEENTRY lpPalEntries;
  1101.    WORD           wEntries, i;
  1102.    HPALETTE       hOldPal;
  1103.    PALETTEENTRY   pe;
  1104.  
  1105.    if (!hPal)
  1106.       return;
  1107.  
  1108.    wEntries = ColorsInPalette (hPal);
  1109.  
  1110.    if (!wEntries)
  1111.       return;
  1112.  
  1113.    hPalEntries = GlobalAlloc (GHND, sizeof (PALETTEENTRY) * wEntries);
  1114.  
  1115.    if (!hPalEntries)
  1116.       return;
  1117.  
  1118.    lpPalEntries = (LPPALETTEENTRY) GlobalLock (hPalEntries);
  1119.  
  1120.    GetPaletteEntries (hPal, 0, wEntries, lpPalEntries);
  1121.  
  1122.    pe = lpPalEntries[0];
  1123.  
  1124.    for (i = 0;  i < wEntries - 1;  i++)
  1125.       lpPalEntries[i] = lpPalEntries[i+1];
  1126.  
  1127.    lpPalEntries[wEntries - 1] = pe;
  1128.  
  1129.    hDC     = GetDC (hWnd);
  1130.    hOldPal = SelectPalette (hDC, hPal, FALSE);
  1131.  
  1132.    AnimatePalette (hPal, 0, wEntries, lpPalEntries);
  1133.  
  1134.    if (hOldPal)
  1135.       SelectPalette (hDC, hOldPal, FALSE);
  1136.  
  1137.    ReleaseDC (hWnd, hDC);
  1138.  
  1139.    GlobalUnlock (hPalEntries);
  1140.    GlobalFree (hPalEntries);
  1141. }
  1142.  
  1143.  
  1144.  
  1145.  
  1146. //---------------------------------------------------------------------
  1147. //
  1148. // Function:   CopyPaletteChangingFlags
  1149. //
  1150. // Purpose:    Duplicate a given palette, changing all the flags in
  1151. //             it to a certain flag value (i.e. peFlags member of
  1152. //             the PALETTEENTRY structure).
  1153. //
  1154. // Parms:      hPal     == Handle to palette to duplicate.
  1155. //             bNewFlag == New peFlags PALETTEENTRY flag.  Set
  1156. //                         to DONT_CHANGE_FLAGS if don't want
  1157. //                         to touch the flags.
  1158. //
  1159. // Returns:    Handle to the new palette.  NULL on error.
  1160. //
  1161. // History:   Date      Reason
  1162. //             6/01/91  Created
  1163. //
  1164. //---------------------------------------------------------------------
  1165.  
  1166. HPALETTE CopyPaletteChangingFlags (HPALETTE hPal, BYTE bNewFlag)
  1167. {
  1168.    WORD         wEntries, i;
  1169.    HANDLE       hLogPal;
  1170.    LPLOGPALETTE lpLogPal;
  1171.  
  1172.    if (!hPal)
  1173.       return NULL;
  1174.  
  1175.    wEntries = ColorsInPalette (hPal);
  1176.  
  1177.    if (!wEntries)
  1178.       return NULL;
  1179.  
  1180.    hLogPal = GlobalAlloc (GHND,
  1181.                sizeof (LOGPALETTE) + sizeof (PALETTEENTRY) * wEntries);
  1182.  
  1183.    if (!hLogPal)
  1184.       return NULL;
  1185.  
  1186.    lpLogPal = (LPLOGPALETTE) GlobalLock (hLogPal);
  1187.  
  1188.    lpLogPal->palVersion    = PALVERSION;
  1189.    lpLogPal->palNumEntries = wEntries;
  1190.  
  1191.    GetPaletteEntries (hPal, 0, wEntries, lpLogPal->palPalEntry);
  1192.  
  1193.    if (bNewFlag != DONT_CHANGE_FLAGS)
  1194.       for (i = 0;  i < wEntries;  i++)
  1195.          lpLogPal->palPalEntry[i].peFlags = bNewFlag;
  1196.  
  1197.    hPal = CreatePalette (lpLogPal);
  1198.  
  1199.    GlobalUnlock (hLogPal);
  1200.    GlobalFree (hLogPal);
  1201.  
  1202.    return hPal;
  1203. }
  1204.