home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / gdi / palette / mypal.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  23KB  |  530 lines

  1.  
  2. /******************************************************************************\
  3. *       This is a part of the Microsoft Source Code Samples. 
  4. *       Copyright (C) 1993-1997 Microsoft Corporation.
  5. *       All rights reserved. 
  6. *       This source code is only intended as a supplement to 
  7. *       Microsoft Development Tools and/or WinHelp documentation.
  8. *       See these sources for detailed information regarding the 
  9. *       Microsoft samples programs.
  10. \******************************************************************************/
  11.  
  12. /***************************************************************************
  13.  *                                                                         *
  14.  *  PROGRAM     : MyPal.c                                                  *
  15.  *                                                                         *
  16.  *  PURPOSE     : Sets up a bar representation of the current physical     *
  17.  *                palette and displays useful information regarding        *
  18.  *                pixel colors and palette indices.                        *
  19.  *                                                                         *
  20.  *  FUNCTIONS   : WinMain() - calls initialization function,               *
  21.  *                            processes message loop                       *
  22.  *                                                                         *
  23.  *                WndProc() - Window function for app. Processes           *
  24.  *                            window messages.                             *
  25.  *                                                                         *
  26.  *              ShowColor() - Displays a little box on each side of the    *
  27.  *                            caption bar displaying the pixel color at the*
  28.  *                            mouse position.                              *
  29.  ***************************************************************************/
  30.  
  31. #include <windows.h>
  32. #include "mypal.h"
  33.  
  34. HANDLE          hPal;          /* Handle to the application's logical palette */
  35. static INT      nSizeX;        /* Width of the application window             */
  36. static INT      nSizeY;        /* Height of the application window            */
  37. NPLOGPALETTE    pLogPal;       /* Pointer to program's logical palette        */
  38. INT             nXBorder;      /* Width of window border                      */
  39. INT             nXTitle;       /* Width of title bar                          */
  40. INT             nYTitle;       /* Height of title bar                         */
  41. BOOL            bCaptureOn;    /* Indicates if mouse capture is on            */
  42. INT             iIndex;        /* Last index selected in palette              */
  43. CHAR            szTitlebuf[90];/* Buffer for pixel and palette info. text     */
  44. HDC             hDCGlobal;     /* The Screen DC                               */
  45. INT             iNumColors;    /* Number of colors supported by device        */
  46. INT             iRasterCaps;   /* Raster capabilities                         */
  47. RECT            rClientRect;   /* Client rectangle coordinates                */
  48. DWORD    dwPal[PALETTESIZE];   /* Stores palette entries for later lookup     */
  49. INT             iGlobalXOffset;
  50. INT             iGlobalYOffset;
  51. INT             iYMiddle;
  52.  
  53. LONG APIENTRY WndProc(HWND hWnd, UINT iMessage, UINT wParam, LONG lParam);
  54.  
  55. /****************************************************************************
  56.  *                                                                          *
  57.  *  FUNCTION   : void ShowColor(HWND hWnd, HDC hDC)                         *
  58.  *                                                                          *
  59.  *  PURPOSE    : Displays a little box on each side of the caption bar      *
  60.  *               displaying the pixel color at the mouse position.          *
  61.  *                                                                          *
  62.  ****************************************************************************/
  63. VOID ShowColor (
  64.         HWND  hWnd,
  65.         HDC   hDC)
  66. {
  67.      HBRUSH  hBrush, hOldBrush;
  68.  
  69.      hBrush    = CreateSolidBrush ( PALETTEINDEX(iIndex) );
  70.      hOldBrush = SelectObject (hDC,hBrush) ;
  71.  
  72.      GetWindowRect (hWnd, (LPRECT)&rClientRect);
  73.  
  74.      PatBlt ( hDC,
  75.               rClientRect.left + nXTitle + nXBorder + 1,
  76.               rClientRect.top + nXBorder,
  77.               nXTitle,
  78.               nYTitle,
  79.               PATCOPY);
  80.  
  81.      PatBlt(hDC,
  82.             rClientRect.right - ( 3 * nXTitle + nXBorder + 2),
  83.             rClientRect.top + nXBorder,
  84.             nXTitle,
  85.             nYTitle,
  86.             PATCOPY);
  87.      SelectObject (hDC, hOldBrush);
  88.      DeleteObject (hBrush) ;
  89. }
  90.  
  91. /****************************************************************************
  92.  *                                                                          *
  93.  *  FUNCTION   : WinMain(HANDLE, HANDLE, LPSTR, int)                        *
  94.  *                                                                          *
  95.  *  PURPOSE    : Creates the app. window and processes the message loop.    *
  96.  *                                                                          *
  97.  ****************************************************************************/
  98. int APIENTRY WinMain(
  99.     HINSTANCE hInstance,
  100.     HINSTANCE hPrevInstance,
  101.     LPSTR lpCmdLine,
  102.     int nCmdShow
  103.     )
  104. {
  105.      static CHAR szAppName [] = "MyPal";
  106.      HWND        hWnd;
  107.      WNDCLASS    wndclass;
  108.      MSG         msg ;
  109.      INT         xScreen;
  110.      INT         yScreen;
  111.  
  112.      UNREFERENCED_PARAMETER( lpCmdLine );
  113.  
  114.      if (!hPrevInstance){
  115.          wndclass.style         = CS_HREDRAW | CS_VREDRAW;
  116.          wndclass.lpfnWndProc   = (WNDPROC) WndProc;
  117.          wndclass.cbClsExtra    = 0;
  118.          wndclass.cbWndExtra    = 0;
  119.          wndclass.hInstance     = hInstance;
  120.          wndclass.hIcon         = LoadIcon(hInstance, szAppName);
  121.          wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW);
  122.          wndclass.hbrBackground = GetStockObject (BLACK_BRUSH);
  123.          wndclass.lpszMenuName  = szAppName;
  124.          wndclass.lpszClassName = szAppName;
  125.  
  126.          if (!RegisterClass (&wndclass))
  127.              return FALSE ;
  128.      }
  129.  
  130.      /* Do some global initializations */
  131.      xScreen     = GetSystemMetrics (SM_CXSCREEN);
  132.      yScreen     = GetSystemMetrics (SM_CYSCREEN);
  133.      nXBorder    = (INT)GetSystemMetrics (SM_CXFRAME);
  134.      nXTitle     = (INT)GetSystemMetrics (SM_CXSIZE);
  135.      nYTitle     = (INT)GetSystemMetrics (SM_CYSIZE);
  136.      iIndex      = 0;
  137.      bCaptureOn  = FALSE;
  138.  
  139.      hDCGlobal   = GetDC (NULL);
  140.      iRasterCaps = GetDeviceCaps(hDCGlobal, RASTERCAPS);
  141.      iRasterCaps = (iRasterCaps & RC_PALETTE) ? TRUE : FALSE;
  142.  
  143.      if (iRasterCaps)
  144.          iNumColors = GetDeviceCaps(hDCGlobal, SIZEPALETTE);
  145.      else
  146.          iNumColors = GetDeviceCaps( hDCGlobal, NUMCOLORS);
  147.      ReleaseDC (NULL,hDCGlobal);
  148.  
  149.      nSizeX = ((xScreen - 2*nXBorder) / PALETTESIZE) * PALETTESIZE;
  150.  
  151.      /* create the app. window */
  152.      hWnd = CreateWindow (szAppName,
  153.                           "My Physical Palette ",
  154.                           WS_OVERLAPPEDWINDOW,
  155.                           (xScreen-nSizeX) / 2 - nXBorder,
  156.                           yScreen - ( 4 * GetSystemMetrics (SM_CYCAPTION)),
  157.                           nSizeX + 2 * nXBorder,
  158.                           4 * GetSystemMetrics (SM_CYCAPTION),
  159.                           NULL,
  160.                           NULL,
  161.                           hInstance,
  162.                           NULL);
  163.      ShowWindow (hWnd, nCmdShow);
  164.      UpdateWindow (hWnd);
  165.  
  166.      while (GetMessage (&msg, NULL, 0, 0)){
  167.            TranslateMessage (&msg) ;
  168.            DispatchMessage (&msg) ;
  169.      }
  170.  
  171.      return msg.wParam ;
  172. }
  173.  
  174. /******************************************************************************
  175.  *                                                                            *
  176.  *  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)                             *
  177.  *                                                                            *
  178.  *  PURPOSE:  Processes window messages and sets up a 256 bar representation  *
  179.  *            of the current physical palette. Specifically, in response to:  *
  180.  *                                                                            *
  181.  *               WM_CREATE  -Allocates for and sets up a LOGPALETTE           *
  182.  *                           structure, creates a logical palette the same    *
  183.  *                           size as the physical palette and obtains a       *
  184.  *                           handle to the logical palette.                   *
  185.  *                                                                            *
  186.  *               WM_DESTROY -Destroys the logical palette and shuts down app. *
  187.  *                                                                            *
  188.  *               WM_PAINT   -Resizes client area to hold as many vertical     *
  189.  *                           color bars as there are physical palette entries.*
  190.  *                           Also realises the current logical palette and    *
  191.  *                           draws one color bar corresponding to each        *
  192.  *                           palette entry                                    *
  193.  *                                                                            *
  194.  *           WM_RBUTTONDOWN -Captures the mouse and initiates the below       *
  195.  *                           process:                                         *
  196.  *                                                                            *
  197.  *           WM_MOUSEMOVE   -Following a WM_RBUTTONDOWN, if the right mouse   *
  198.  *                           key is depressed, displays info about the        *
  199.  *                           pixel RGB value and palette index of the mouse   *
  200.  *                           coordinates.                                     *
  201.  *                                                                            *
  202.  *           WM_RBUTTONUP   -Release mouse capture and terminates the above   *
  203.  *                           process                                          *
  204.  *                                                                            *
  205.  *           WM_LBUTTONDOWN -Determines and displays the palette index and    *
  206.  *                           RGB value of the bar under the mouse.            *
  207.  *                                                                            *
  208.  *           WM_KEYDOWN     -Allows use of the arrow keys in stepping thro'   *
  209.  *                           palette entries.                                 *
  210.  *                                                                            *
  211.  *****************************************************************************/
  212. LONG APIENTRY WndProc (
  213.     HWND         hWnd,
  214.     UINT     iMessage,
  215.     UINT         wParam,
  216.     LONG         lParam)
  217. {
  218.     HDC           hDC;
  219.     PAINTSTRUCT   ps;
  220.     INT           iLoop;
  221.     INT           nStart;
  222.     HBRUSH        hBrush;
  223.     HBRUSH        hOldBrush;
  224.  
  225.     MPOINT        pt;
  226.     static INT    nIncr;
  227.     static DWORD  dwColor;
  228.     static DWORD  dwLastColor;
  229.     static INT    i, x;
  230.  
  231.     switch (iMessage) {
  232.          case WM_DESTROY:
  233.               /* delete the handle to the logical palette if it has any
  234.                * color entries and quit.
  235.                */
  236.               if (pLogPal->palNumEntries)
  237.                   DeleteObject (hPal);
  238.               PostQuitMessage (0) ;
  239.               break ;
  240.  
  241.          case WM_CREATE:
  242.               /* Allocate enough memory for a logical palette with
  243.                * PALETTESIZE entries and set the size and version fields
  244.                * of the logical palette structure.
  245.                */
  246.               pLogPal = (NPLOGPALETTE) LocalAlloc (LMEM_FIXED,
  247.                                                   (sizeof (LOGPALETTE) +
  248.                                                   (sizeof (PALETTEENTRY) * (PALETTESIZE))));
  249.  
  250.           if(!pLogPal){
  251.             MessageBox(hWnd, "<WM_CREATE> Not enough memory for palette.", NULL, MB_OK | MB_ICONHAND);
  252.                 PostQuitMessage (0) ;
  253.             break;
  254.           }
  255.  
  256.               pLogPal->palVersion    = 0x300;
  257.               pLogPal->palNumEntries = PALETTESIZE;
  258.  
  259.               /* fill in intensities for all palette entry colors */
  260.               for (iLoop = 0; iLoop < PALETTESIZE; iLoop++) {
  261.                   *((WORD *) (&pLogPal->palPalEntry[iLoop].peRed)) = (WORD)iLoop;
  262.                   pLogPal->palPalEntry[iLoop].peBlue  = 0;
  263.                   pLogPal->palPalEntry[iLoop].peFlags = PC_EXPLICIT;
  264.               }
  265.  
  266.               /*  create a logical color palette according the information
  267.                *  in the LOGPALETTE structure.
  268.                */
  269.               hPal = CreatePalette ((LPLOGPALETTE) pLogPal) ;
  270.               break;
  271.  
  272.          case WM_GETMINMAXINFO:
  273.  
  274.               ((LPRGPT)lParam)->iInfo[6] = nXBorder * 2 + PALETTESIZE;
  275.               ((LPRGPT)lParam)->iInfo[7] = nXBorder * 2 + nYTitle*3;
  276.  
  277.               return DefWindowProc (hWnd, iMessage, wParam, lParam) ;
  278.               break;
  279.  
  280.          case WM_PAINT:
  281.  
  282.               /* Divide client width into equal-sized parts, one per palette
  283.                * entry, and re-calculate client width so that it will display
  284.                * exactly as many vertical bars as there are palette entries.
  285.                */
  286.                GetClientRect(hWnd,(LPRECT) &rClientRect);
  287.                nSizeX = (rClientRect.right - rClientRect.left);
  288.                nSizeX = (nSizeX/iNumColors) * iNumColors;
  289.  
  290.                nSizeY = rClientRect.bottom - rClientRect.top;
  291.                GetWindowRect(hWnd,(LPRECT) &rClientRect);
  292.  
  293.               /* Adjust window width so that it can display exactly
  294.                * as many vertical bars( of equal width) as there are palette
  295.                * colors.
  296.                */
  297.  
  298.               SetWindowPos( hWnd,
  299.                             (HWND)NULL,
  300.                             0,
  301.                             0,
  302.                             nSizeX + 2*nXBorder,
  303.                             rClientRect.bottom - rClientRect.top,
  304.                             SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  305.  
  306.               hDC = BeginPaint(hWnd, &ps);
  307.  
  308.               /* Select the palette into the window device context and
  309.                * make the Palette Manager map the logical palette to the
  310.                * system palette (realize it).
  311.                */
  312.               SelectPalette (hDC, hPal, 1);
  313.               RealizePalette (hDC);
  314.  
  315.               /* Calculate width of each color bar to be displayed */
  316.               nIncr = nSizeX / iNumColors;
  317.  
  318.               /* Paint the individual bars separately on the app. window */
  319.               for (nStart = iLoop = 0; iLoop < iNumColors; iLoop++){
  320.  
  321.                   /* Since this app. uses a logical palette, use the
  322.                    * PALETTEINDEX macro to specify the palette entry
  323.                    * index instead of using an explicit RGB value.
  324.                    */
  325.                   hBrush       = CreateSolidBrush (PALETTEINDEX (iLoop));
  326.                   dwPal[iLoop] = GetNearestColor (hDC, PALETTEINDEX (iLoop) );
  327.                   hOldBrush    = SelectObject (hDC,hBrush) ;
  328.                   PatBlt (hDC, nStart, 0, nIncr, nSizeY, PATCOPY);
  329.                   nStart       += nIncr;
  330.                   SelectObject (hDC, hOldBrush);
  331.                   DeleteObject (hBrush) ;
  332.               }
  333.               wsprintf (szTitlebuf, "MyPal Colors= %d", iNumColors);
  334.               SetWindowText (hWnd, (LPSTR)szTitlebuf);
  335.  
  336.               EndPaint(hWnd,&ps);
  337.  
  338.               break ;
  339.  
  340.          case WM_MOUSEMOVE:
  341.  
  342.               if (wParam & MK_RBUTTON) {
  343.  
  344.           POINT pt;
  345.                   
  346. #ifdef WIN16
  347.                   /* Convert mouse position to screen coordinates */
  348.                   pt.x = LOWORD(lParam);
  349.                   pt.y = HIWORD(lParam);
  350. #else
  351.                   LONG2POINT(lParam, pt);       
  352. #endif
  353.                   ClientToScreen(hWnd, &pt);
  354.  
  355.                   /* Get RGB value (color) of pixel under mouse coordinate */
  356.                   dwColor = GetPixel(hDCGlobal, pt.x, pt.y);
  357.  
  358.                   /* If color value already exists in palette lookup table,
  359.                    * obtain it's index.
  360.                    */
  361.                   for (i=0 ; i < iNumColors ; i++)
  362.                       if ( dwColor == dwPal[i] )
  363.                           break;
  364.                   iIndex = i;
  365.  
  366.                   /* If previous color value was not identical to current one,
  367.                    * display color boxes on either side of title bar,
  368.                    * the R, G, B values and palette index of current color.
  369.                    */
  370.                   if (dwColor != dwLastColor) {
  371.                       wsprintf ( szTitlebuf,
  372.                                  "MyPal Colors=%d  Index=%d  R=%3u G=%3u B=%3u",
  373.                                  iNumColors,
  374.                                  iIndex,
  375.                                  (WORD)(BYTE) GetRValue (dwColor),
  376.                                  (WORD)(BYTE) GetGValue (dwColor),
  377.                                  (WORD)(BYTE) GetBValue (dwColor));
  378.                       SetWindowText (hWnd, (LPSTR)szTitlebuf);
  379.                       ShowColor (hWnd, hDCGlobal);
  380.                       dwLastColor = dwColor;
  381.                   }
  382.               }
  383.               break;
  384.  
  385.          case WM_RBUTTONDOWN:
  386.  
  387.               /* Determine number of color bar under mouse, thus the index
  388.                * of color in palette.
  389.                */
  390.               x = LOWORD(lParam);
  391.               iIndex = (x / nIncr );
  392.  
  393.               wsprintf ( szTitlebuf,
  394.                          "MyPal Colors=%d  Index=%d  PalSize=%d RasterCaps:%d",
  395.                          iNumColors,
  396.                          iIndex,
  397.                          iNumColors,
  398.                          iRasterCaps );
  399.  
  400.               SetWindowText (hWnd, (LPSTR)szTitlebuf);
  401.  
  402.               /* Set mouse capture so that subsequent WM_MOUSEMOVEs
  403.                * (with right mouse button depressed) will allow MyPal
  404.                * to display RGB info anywhere on the screen without losing
  405.                * the focus.
  406.                */
  407.               SetCapture (hWnd);
  408.               bCaptureOn = TRUE;
  409.               hDCGlobal = GetDC(NULL);
  410.               if (hPal) {
  411.                   SelectPalette (hDCGlobal, hPal, FALSE);
  412.                   RealizePalette (hDCGlobal);
  413.               }
  414.               break;
  415.  
  416.          case WM_RBUTTONUP:
  417.               /* Stops displaying RGB and palette info and releases mouse
  418.                * capture
  419.                */
  420.               ReleaseDC (NULL, hDCGlobal);
  421.               bCaptureOn = FALSE;
  422.               ReleaseCapture ();
  423.               break;
  424.  
  425.          case WM_MOVE:
  426.               /* If you have a wide column, this adds 1/2 so X is centered */
  427.               iGlobalXOffset  = LOWORD (lParam);
  428.               iGlobalYOffset  = HIWORD (lParam) + nXBorder;
  429.               break;
  430.  
  431.          case WM_SIZE:
  432.               iYMiddle = (HIWORD (lParam)/2);
  433.               break;
  434.  
  435.          case WM_LBUTTONDOWN:
  436.          case WM_KEYDOWN:
  437.  
  438.              if (iMessage == WM_LBUTTONDOWN){
  439.                  /* determine which column was hit by the mouse */
  440.                  x = LOWORD(lParam);
  441.                  iIndex = (x / nIncr );
  442.              }
  443.              else{
  444.                  /* Use arrow keys to step thro' the palette entries */
  445.                  switch (wParam) {
  446.                      case VK_RIGHT:
  447.                      case VK_UP:
  448.                                   /* go to next (higher) palette entry */
  449.                                   iIndex++;
  450.                                   break;
  451.                      case VK_LEFT:
  452.                      case VK_DOWN:
  453.                                   /* go to previous (lower) palette entry */
  454.                                   iIndex--;
  455.                                   break;
  456.                      case VK_NEXT:
  457.                                   iIndex += 10;
  458.                                   break;
  459.                      case VK_PRIOR:
  460.                                   iIndex -= 10;
  461.                                   break;
  462.                      case VK_HOME:
  463.                                   /* go to first palette entry */
  464.                                   iIndex = 0;
  465.                                   break;
  466.                      case VK_END:
  467.                                   /* go to last palette entry */
  468.                                   iIndex = iNumColors-1;
  469.                                   break;
  470.                      default:
  471.                                   return 0L;
  472.                                   break;
  473.                  }
  474.                  /* Make sure the palette index is within range else
  475.                   * set it to the limiting values and give a warning beep.
  476.                   */
  477.                  if (iIndex < 0) {
  478.                      iIndex = 0;
  479.                      MessageBeep(1);
  480.                  }
  481.                  else{
  482.                      if (iIndex > iNumColors-1) {
  483.                          iIndex = iNumColors-1;
  484.                          MessageBeep(1);
  485.                       }
  486.                  }
  487.  
  488.                  pt.x = (SHORT)((iIndex * nIncr) +
  489.                         iGlobalXOffset   +
  490.                         ((nIncr > 1) ? (nIncr / 2) : 1));
  491.                  pt.y = (SHORT)(iYMiddle + iGlobalYOffset);
  492.  
  493.                  SetCursorPos (pt.x, pt.y);
  494.              }
  495.  
  496.              if (TRUE == bCaptureOn) {
  497.                  MessageBeep(1);
  498.                  break;
  499.              }
  500.  
  501.              /* Select & realize the palette or the colors > 0x7
  502.               * will not match up.
  503.               */
  504.              hDC = GetDC(NULL);
  505.              SelectPalette  (hDC, hPal, 1);
  506.              RealizePalette (hDC) ;
  507.  
  508.              dwColor = GetNearestColor (hDC, PALETTEINDEX (iIndex));
  509.  
  510.              wsprintf ( szTitlebuf,
  511.                         "MyPal Colors=%d  Index=%d  R=%3u G=%3u B=%3u",
  512.                         iNumColors,
  513.                         iIndex,
  514.                         (WORD)(BYTE)GetRValue (dwColor),
  515.                         (WORD)(BYTE)GetGValue (dwColor),
  516.                         (WORD)(BYTE)GetBValue (dwColor)
  517.                      );
  518.  
  519.              SetWindowText (hWnd, (LPSTR)szTitlebuf);
  520.              ShowColor (hWnd,hDC);
  521.              ReleaseDC(NULL, hDC);
  522.              break;
  523.  
  524.          default:
  525.               return DefWindowProc (hWnd, iMessage, wParam, lParam) ;
  526.  
  527.     }
  528.     return 0L ;
  529. }
  530.