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 / showdib / showdib.c < prev    next >
C/C++ Source or Header  |  1997-10-10  |  43KB  |  1,126 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     : ShowDIB.c                                                    *
  15.  *                                                                             *
  16.  *  PURPOSE     : Application to illustrate the use of the GDI                 *
  17.  *                DIB (Device Independent Bitmap) and Palette manager          *
  18.  *                functions.                                                   *
  19.  *                                                                             *
  20.  *  FUNCTIONS   : WinMain ()             -  Creates the app. window and enters *
  21.  *                                          the message loop.                  *
  22.  *                                                                             *
  23.  *                WndProc()              -  Processes app. window messages.    *
  24.  *                                                                             *
  25.  *                MenuCommand()          -  Processes menu commands.           *
  26.  *                                                                             *
  27.  *                FreeDIB()              -  Frees currently active objects.    *
  28.  *                                                                             *
  29.  *                InitDIB()              -  Reads DIB from a file and loads it.*
  30.  *                                                                             *
  31.  *******************************************************************************/
  32.  
  33. #include <windows.h>
  34. #include <io.h>
  35. #include <stdio.h>
  36. #include "showdib.h"
  37. #include <commdlg.h>
  38.  
  39. DIBPARAMS      DIBParams;                  /* params for the SETSCALING escape */
  40. CHAR           achFileName[128];
  41. DWORD          dwOffset;
  42. NPLOGPALETTE   pLogPal;
  43. HPALETTE       hpalSave = NULL;
  44. HINSTANCE      hInst ;
  45. RECT           rcClip;
  46. static         HCURSOR hcurSave;
  47.  
  48. BOOL    fPalColors  = FALSE;          /* TRUE if the current DIB's color table   */
  49.                                       /* contains palette indexes not rgb values */
  50. UINT    nAnimating  = 0;              /* Palette animation count                 */
  51. WORD    UpdateCount = 0;
  52.  
  53. BOOL    bUpdateColors = TRUE;  /* Directly update screen colors                */
  54. BOOL    bDIBToDevice  = FALSE; /* Use SetDIBitsToDevice() to BLT data.         */
  55. BOOL    bNoUgly       = FALSE; /* Make window black on a WM_PALETTEISCHANGING  */
  56. BOOL    bLegitDraw    = FALSE; /* We have a valid bitmap to draw               */
  57.  
  58. CHAR    szBitmapExt[] = "*.BMP; *.DIB; *.RLE";     /* possible file extensions */
  59. WORD    wTransparent  = TRANSPARENT;               /* Mode of DC               */
  60. CHAR    szAppName[]   = "ShowDIB" ;                /* App. name                */
  61.  
  62. HPALETTE hpalCurrent   = NULL;         /* Handle to current palette            */
  63. HANDLE   hdibCurrent   = NULL;         /* Handle to current memory DIB         */
  64. HBITMAP  hbmCurrent    = NULL;         /* Handle to current memory BITMAP      */
  65. HANDLE   hbiCurrent    = NULL;         /* Handle to current bitmap info struct */
  66. HWND     hWndApp;                      /* Handle to app. window                */
  67.  
  68. /* Styles of app. window */
  69. DWORD          dwStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |
  70.                          WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_THICKFRAME;
  71.  
  72. VOID PrintDIB (HWND hWnd, HDC hDC, INT x, INT y, INT dx, INT dy);
  73. /****************************************************************************
  74.  *                                                                          *
  75.  *  FUNCTION   : WinMain(HANDLE, HANDLE, LPSTR, int)                        *
  76.  *                                                                          *
  77.  *  PURPOSE    : Creates the app. window and enters the message loop.       *
  78.  *                                                                          *
  79.  ****************************************************************************/
  80. int APIENTRY WinMain(
  81.     HINSTANCE hInstance,
  82.     HINSTANCE hPrevInstance,
  83.     LPSTR lpCmdLine,
  84.     int nCmdShow
  85.     )
  86. {
  87.      HWND        hWnd ;
  88.      WNDCLASS    wndclass ;
  89.      MSG         msg ;
  90.      int         xScreen, yScreen ;
  91.      CHAR        ach[40];
  92.  
  93.      hInst = hInstance ;
  94.  
  95.      /* Initialize clip rectangle */
  96.      SetRectEmpty(&rcClip);
  97.  
  98.      if (!hPrevInstance) {
  99.          wndclass.style         = CS_DBLCLKS;
  100.          wndclass.lpfnWndProc   = (WNDPROC) WndProc ;
  101.          wndclass.cbClsExtra    = 0 ;
  102.          wndclass.cbWndExtra    = 0 ;
  103.          wndclass.hInstance     = hInstance ;
  104.          wndclass.hIcon         = LoadIcon(hInst, "SHOWICON");
  105.          wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
  106.          wndclass.hbrBackground = GetStockObject (BLACK_BRUSH) ;
  107.          wndclass.lpszMenuName  = szAppName ;
  108.          wndclass.lpszClassName = szAppName ;
  109.  
  110.          if (!RegisterClass (&wndclass))
  111.                  return FALSE ;
  112.      }
  113.  
  114.      if (!GetProfileString("extensions", "bmp", "", ach, sizeof(ach)))
  115.              WriteProfileString("extensions", "bmp", "showdib.exe ^.bmp");
  116.      if (!GetProfileString("extensions", "dib", "", ach, sizeof(ach)))
  117.              WriteProfileString("extensions", "dib", "showdib.exe ^.dib");
  118.  
  119.      /* Save the pointer to the command line */
  120.      lstrcpy(achFileName, lpCmdLine);
  121.  
  122.      xScreen = GetSystemMetrics (SM_CXSCREEN) ;
  123.      yScreen = GetSystemMetrics (SM_CYSCREEN) ;
  124.  
  125.      /* Create the app. window */
  126.      hWnd = CreateWindow( szAppName,
  127.                           szAppName,
  128.                           dwStyle,
  129.                           CW_USEDEFAULT,
  130.                           0,
  131.                           xScreen / 2,
  132.                           yScreen / 2,
  133.                           NULL,
  134.                           NULL,
  135.                           hInstance,
  136.                           NULL) ;
  137.  
  138.      ShowWindow (hWndApp = hWnd, nCmdShow) ;
  139.  
  140.      /* Enter message loop */
  141.      while (GetMessage (&msg, NULL, 0, 0)) {
  142.          TranslateMessage (&msg) ;
  143.          DispatchMessage (&msg) ;
  144.      }
  145.  
  146.      return msg.wParam ;
  147. }
  148.  
  149. /****************************************************************************
  150.  *                                                                          *
  151.  *  FUNCTION   : WndProc (hWnd, iMessage, wParam, lParam)                   *
  152.  *                                                                          *
  153.  *  PURPOSE    : Processes window messages.                                 *
  154.  *                                                                          *
  155.  ****************************************************************************/
  156. LONG    APIENTRY WndProc (
  157.     HWND     hWnd ,
  158.     UINT     iMessage ,
  159.     UINT     wParam ,
  160.     LONG     lParam )
  161.  
  162. {
  163.     PAINTSTRUCT      ps;
  164.     HDC              hDC;
  165.     HANDLE           h;
  166.     INT              i;
  167.     INT              iMax;
  168.     INT              iMin;
  169.     INT              iPos;
  170.     INT              dn;
  171.     RECT             rc,Rect;
  172.     HPALETTE         hOldPal;
  173.     HMENU            hMenu;
  174.     CHAR             lpBuffer[128];
  175.  
  176.     switch (iMessage) {
  177.         case WM_DESTROY:
  178.                 /* Clean up and quit */
  179.                 FreeDib();
  180.                 PostQuitMessage(0);
  181.                 break ;
  182.  
  183.         case WM_CREATE:
  184.                 /* Allocate space for our logical palette */
  185.                 pLogPal = (NPLOGPALETTE) LocalAlloc( LMEM_FIXED,
  186.                                                      (sizeof(LOGPALETTE) +
  187.                                                      (sizeof(PALETTEENTRY)*(MAXPALETTE))));
  188.         if(!pLogPal){
  189.             LoadString(hInst, IDS_MEMLOW, lpBuffer, sizeof(lpBuffer));
  190.             MessageBox(hWnd, lpBuffer, NULL, MB_OK | MB_ICONHAND);
  191.             PostQuitMessage(0);
  192.             break;
  193.         }
  194.  
  195. // Temporary workaround.  lpCmdLine points to exe name, not first parameter
  196.                 /* If DIB initialization fails, quit */
  197. //              if (achFileName[0] && !InitDIB(hWnd))
  198. //                      PostQuitMessage (3) ;
  199.  
  200.                 /* fall through */
  201.  
  202.         case WM_WININICHANGE:
  203.  
  204.               hMenu = GetMenu(hWnd);
  205.               if ( hDC = GetPrinterDC1() ) {
  206.                     EnableMenuItem( hMenu,
  207.                                     IDM_PRINT,
  208.                                     (RC_DIBTODEV &
  209.                                      GetDeviceCaps(hDC, RASTERCAPS)) ?
  210.                                      MF_ENABLED :
  211.                                      MF_GRAYED | MF_DISABLED);
  212.                   DeleteDC(hDC);
  213.               }
  214.                 break;
  215.  
  216.         case WM_PALETTEISCHANGING:
  217.                 /* if SHOWDIB was not responsible for palette change and if
  218.                  * ok to hide changes, paint app. window black.
  219.                  */
  220.                 if (wParam != (UINT)(hWnd && bNoUgly)) {
  221.                     GetClientRect(hWnd, &Rect);
  222.  
  223.                     hDC = GetDC(hWnd);
  224.                     FillRect( hDC, (LPRECT) &Rect, GetStockObject(BLACK_BRUSH));
  225.                     ReleaseDC(hWnd, hDC);
  226.                 }
  227.                 break;
  228.  
  229.         case WM_ACTIVATE:
  230.                 if (!GET_WM_ACTIVATE_STATE(wParam, lParam))  /* app. is being de-activated */
  231.                    break;
  232.                 /* If the app. is moving to the foreground, fall through and
  233.                  * redraw full client area with the newly realized palette,
  234.                  * if the palette has changed.
  235.                  */
  236.  
  237.         case WM_QUERYNEWPALETTE:
  238.                 /* If palette realization causes a palette change,
  239.                  * we need to do a full redraw.
  240.                  */
  241.                 if (bLegitDraw) {
  242.                     hDC = GetDC (hWnd);
  243.                     hOldPal = SelectPalette (hDC, hpalCurrent, 0);
  244.  
  245.                     i = RealizePalette(hDC);
  246.  
  247.                     SelectPalette (hDC, hOldPal, 0);
  248.                     ReleaseDC (hWnd, hDC);
  249.  
  250.                     if (i) {
  251.                         InvalidateRect (hWnd, (LPRECT) (NULL), 1);
  252.                         UpdateCount = 0;
  253.                         return 1;
  254.                     } else
  255.                         return FALSE;
  256.                 }
  257.                 else
  258.                     return FALSE;
  259.                 break;
  260.  
  261.         case WM_PALETTECHANGED:
  262.                 /* if SHOWDIB was not responsible for palette change and if
  263.                  * palette realization causes a palette change, do a redraw.
  264.                  */
  265.                  if ((HWND)wParam != hWnd){
  266.                     if (bLegitDraw){
  267.                         hDC = GetDC (hWnd);
  268.                         hOldPal = SelectPalette (hDC, hpalCurrent, 0);
  269.  
  270.                         i = RealizePalette (hDC);
  271.  
  272.                         if (i){
  273.                             if (bUpdateColors){
  274.                                 UpdateColors (hDC);
  275.                                 UpdateCount++;
  276.                             }
  277.                             else
  278.                                 InvalidateRect (hWnd, (LPRECT) (NULL), 1);
  279.                         }
  280.  
  281.                         SelectPalette (hDC, hOldPal, 0);
  282.                         ReleaseDC (hWnd, hDC);
  283.                     }
  284.                 }
  285.                 break;
  286.  
  287.         case WM_RENDERALLFORMATS:
  288.                 /* Ensure that clipboard data can be rendered even tho'
  289.                  * app. is being destroyed.
  290.                  */
  291.                 SendMessage(hWnd,WM_RENDERFORMAT,CF_DIB,0L);
  292.                 SendMessage(hWnd,WM_RENDERFORMAT,CF_BITMAP,0L);
  293.                 SendMessage(hWnd,WM_RENDERFORMAT,CF_PALETTE,0L);
  294.                 break;
  295.  
  296.         case WM_RENDERFORMAT:
  297.                 /* Format data in manner specified and pass the data
  298.                  * handle to clipboard.
  299.                  */
  300.                 if (h = RenderFormat(wParam))
  301.                     SetClipboardData((WORD)wParam,h);
  302.                 break;
  303.  
  304.         case WM_COMMAND:
  305.                 /* Process menu commands */
  306.                 return MenuCommand(hWnd, LOWORD(wParam));
  307.                 break;
  308.  
  309.         case WM_TIMER:
  310.                 /* Signal for palette animation */
  311.                 hDC = GetDC(hWnd);
  312.                 hOldPal = SelectPalette(hDC, hpalCurrent, 0);
  313.                 {
  314.                     PALETTEENTRY peTemp;
  315.  
  316.                     /* Shift all palette entries left by one position and wrap
  317.                      * around the first entry
  318.                      */
  319.                     peTemp = pLogPal->palPalEntry[0];
  320.                     for (i = 0; i < (pLogPal->palNumEntries - 1); i++)
  321.                          pLogPal->palPalEntry[i] = pLogPal->palPalEntry[i+1];
  322.                     pLogPal->palPalEntry[i] = peTemp;
  323.                 }
  324.                 /* Replace entries in logical palette with new entries*/
  325.                 AnimatePalette(hpalCurrent, 0, pLogPal->palNumEntries, pLogPal->palPalEntry);
  326.  
  327.                 SelectPalette(hDC, hOldPal, 0);
  328.                 ReleaseDC(hWnd, hDC);
  329.  
  330.                 /* Decrement animation count and terminate animation
  331.                  * if it reaches zero
  332.                  */
  333.                 if (!(--nAnimating))
  334.                     PostMessage(hWnd,WM_COMMAND,IDM_ANIMATE0,0L);
  335.                 break;
  336.  
  337.         case WM_PAINT:
  338.                 /* If we have updated more than once, the rest of our
  339.                  * window is not in some level of degradation worse than
  340.                  * our redraw...  we need to redraw the whole area
  341.                  */
  342.                 if (UpdateCount > 1) {
  343.                     BeginPaint(hWnd, &ps);
  344.                     EndPaint(hWnd, &ps);
  345.                     UpdateCount = 0;
  346.                     InvalidateRect(hWnd, (LPRECT) (NULL), 1);
  347.                     break;
  348.                 }
  349.  
  350.                 hDC = BeginPaint(hWnd, &ps);
  351.                 AppPaint(hWnd,
  352.                          hDC,
  353.                          GetScrollPos(hWnd,SB_HORZ),
  354.                          GetScrollPos(hWnd,SB_VERT) );
  355.                 EndPaint(hWnd, &ps);
  356.                 break ;
  357.  
  358.         case WM_SIZE:
  359.             SetScrollRanges(hWnd);
  360.             break;
  361.  
  362.         case WM_KEYDOWN:
  363.             /* Translate keyboard messages to scroll commands */
  364.             switch (wParam) {
  365.                 case VK_UP:
  366.                     PostMessage (hWnd, WM_VSCROLL, SB_LINEUP,   0L);
  367.                     break;
  368.  
  369.                 case VK_DOWN:
  370.                     PostMessage (hWnd, WM_VSCROLL, SB_LINEDOWN, 0L);
  371.                     break;
  372.  
  373.                 case VK_PRIOR:
  374.                     PostMessage (hWnd, WM_VSCROLL, SB_PAGEUP,   0L);
  375.                     break;
  376.  
  377.                 case VK_NEXT:
  378.                     PostMessage (hWnd, WM_VSCROLL, SB_PAGEDOWN, 0L);
  379.                     break;
  380.  
  381.                 case VK_HOME:
  382.                     PostMessage (hWnd, WM_HSCROLL, SB_PAGEUP,   0L);
  383.                     break;
  384.  
  385.                 case VK_END:
  386.                     PostMessage (hWnd, WM_HSCROLL, SB_PAGEDOWN, 0L);
  387.                     break;
  388.  
  389.                 case VK_LEFT:
  390.                     PostMessage (hWnd, WM_HSCROLL, SB_LINEUP,   0L);
  391.                     break;
  392.  
  393.                 case VK_RIGHT:
  394.                     PostMessage (hWnd, WM_HSCROLL, SB_LINEDOWN, 0L);
  395.                     break;
  396.             }
  397.             break;
  398.  
  399.         case WM_KEYUP:
  400.             switch (wParam) {
  401.                case VK_UP:
  402.                case VK_DOWN:
  403.                case VK_PRIOR:
  404.                case VK_NEXT:
  405.                   PostMessage (hWnd, WM_VSCROLL, SB_ENDSCROLL, 0L);
  406.                   break;
  407.  
  408.                case VK_HOME:
  409.                case VK_END:
  410.                case VK_LEFT:
  411.                case VK_RIGHT:
  412.                   PostMessage (hWnd, WM_HSCROLL, SB_ENDSCROLL, 0L);
  413.                   break;
  414.             }
  415.             break;
  416.  
  417.         case WM_VSCROLL:
  418.             /* Calculate new vertical scroll position */
  419.             GetScrollRange (hWnd, SB_VERT, &iMin, &iMax);
  420.             iPos = GetScrollPos (hWnd, SB_VERT);
  421.             GetClientRect (hWnd, &rc);
  422.  
  423.             switch (GET_WM_VSCROLL_CODE(wParam, lParam)) {
  424.                 case SB_LINEDOWN:
  425.                     dn =  rc.bottom / 16 + 1;
  426.                     break;
  427.  
  428.                 case SB_LINEUP:
  429.                     dn = -rc.bottom / 16 + 1;
  430.                     break;
  431.  
  432.                 case SB_PAGEDOWN:
  433.                     dn =  rc.bottom / 2  + 1;
  434.                     break;
  435.  
  436.                 case SB_PAGEUP:
  437.                     dn = -rc.bottom / 2  + 1;
  438.                     break;
  439.  
  440.                 case SB_THUMBTRACK:
  441.                 case SB_THUMBPOSITION:
  442.                     dn = GET_WM_VSCROLL_POS(wParam, lParam)-iPos;
  443.                     break;
  444.  
  445.                 default:
  446.                     dn = 0;
  447.                     break;
  448.             }
  449.             /* Limit scrolling to current scroll range */
  450.             if (dn = BOUND (iPos + dn, iMin, iMax) - iPos) {
  451.                 ScrollWindow (hWnd, 0, -dn, NULL, NULL);
  452.                 SetScrollPos (hWnd, SB_VERT, iPos + dn, TRUE);
  453.             }
  454.             break;
  455.  
  456.         case WM_HSCROLL:
  457.             /* Calculate new horizontal scroll position */
  458.             GetScrollRange (hWnd, SB_HORZ, &iMin, &iMax);
  459.             iPos = GetScrollPos (hWnd, SB_HORZ);
  460.             GetClientRect (hWnd, &rc);
  461.  
  462.             switch (GET_WM_HSCROLL_CODE(wParam, lParam)) {
  463.                 case SB_LINEDOWN:
  464.                     dn =  rc.right / 16 + 1;
  465.                     break;
  466.  
  467.                 case SB_LINEUP:
  468.                     dn = -rc.right / 16 + 1;
  469.                     break;
  470.  
  471.                 case SB_PAGEDOWN:
  472.                     dn =  rc.right / 2  + 1;
  473.                     break;
  474.  
  475.                 case SB_PAGEUP:
  476.                     dn = -rc.right / 2  + 1;
  477.                     break;
  478.  
  479.                 case SB_THUMBTRACK:
  480.                 case SB_THUMBPOSITION:
  481.                     dn = GET_WM_HSCROLL_POS(wParam, lParam)-iPos;
  482.                     break;
  483.  
  484.                 default:
  485.                     dn = 0;
  486.                     break;
  487.             }
  488.             /* Limit scrolling to current scroll range */
  489.             if (dn = BOUND (iPos + dn, iMin, iMax) - iPos) {
  490.                 ScrollWindow (hWnd, -dn, 0, NULL, NULL);
  491.                 SetScrollPos (hWnd, SB_HORZ, iPos + dn, TRUE);
  492.             }
  493.             break;
  494.  
  495.         case WM_LBUTTONDOWN:
  496.             /* Start rubberbanding a rect. and track it's dimensions.
  497.              * set the clip rectangle to it's dimensions.
  498.              */
  499.             TrackMouse (hWnd, MAKEMPOINT(lParam));
  500.             break;
  501.  
  502.         case WM_LBUTTONDBLCLK:
  503.             break;
  504.  
  505.         case WM_INITMENU:
  506.             /* check/uncheck menu items depending on state  of related
  507.              * flags
  508.              */
  509.  
  510.             CheckMenuItem((HMENU)wParam, IDM_UPDATECOL,
  511.                 (bUpdateColors ? MF_CHECKED : MF_UNCHECKED));
  512.             CheckMenuItem((HMENU)wParam, IDM_TRANSPARENT,
  513.                 (wTransparent == TRANSPARENT ? MF_CHECKED : MF_UNCHECKED));
  514.             CheckMenuItem((HMENU)wParam, IDM_DIBSCREEN,
  515.                 (bDIBToDevice ? MF_CHECKED : MF_UNCHECKED));
  516.             CheckMenuItem((HMENU)wParam, IDM_NOUGLY,
  517.                 (bNoUgly ? MF_CHECKED : MF_UNCHECKED));
  518.             CheckMenuItem((HMENU)wParam, IDM_MEMORYDIB, MF_CHECKED);
  519.             EnableMenuItem((HMENU)wParam, IDM_PASTEDIB,
  520.                 IsClipboardFormatAvailable(CF_DIB)?MF_ENABLED:MF_GRAYED);
  521.             EnableMenuItem((HMENU)wParam, IDM_PASTEDDB,
  522.                 IsClipboardFormatAvailable(CF_BITMAP)?MF_ENABLED:MF_GRAYED);
  523.             EnableMenuItem((HMENU)wParam, IDM_PASTEPAL,
  524.                 IsClipboardFormatAvailable(CF_PALETTE)?MF_ENABLED:MF_GRAYED);
  525.             EnableMenuItem((HMENU)wParam, IDM_PRINT,
  526.                 bLegitDraw ? MF_ENABLED : MF_GRAYED);
  527.             EnableMenuItem((HMENU)wParam, IDM_SAVE,
  528.                 bLegitDraw ? MF_ENABLED : MF_GRAYED);
  529.             EnableMenuItem((HMENU)wParam, IDM_COPY,
  530.                 bLegitDraw ? MF_ENABLED : MF_GRAYED);
  531.  
  532.             EnableMenuItem((HMENU)wParam, IDM_ANIMATE0,
  533.                 bLegitDraw ? MF_ENABLED : MF_GRAYED);
  534.             EnableMenuItem((HMENU)wParam, IDM_ANIMATE5,
  535.                 bLegitDraw ? MF_ENABLED : MF_GRAYED);
  536.             EnableMenuItem((HMENU)wParam, IDM_ANIMATE50,
  537.                 bLegitDraw ? MF_ENABLED : MF_GRAYED);
  538.             EnableMenuItem((HMENU)wParam, IDM_ANIMATE100,
  539.                 bLegitDraw ? MF_ENABLED : MF_GRAYED);
  540.             EnableMenuItem((HMENU)wParam, IDM_ANIMATE200,
  541.                 bLegitDraw ? MF_ENABLED : MF_GRAYED);
  542.             EnableMenuItem((HMENU)wParam, IDM_ANIMATE201,
  543.                 bLegitDraw ? MF_ENABLED : MF_GRAYED);
  544.             EnableMenuItem((HMENU)wParam, IDM_STEALCOL,
  545.                 bLegitDraw ? MF_ENABLED : MF_GRAYED);
  546.             break;
  547.  
  548.         default:
  549.             return DefWindowProc (hWnd, iMessage, wParam, lParam) ;
  550.  
  551.     }
  552.     return 0L ;
  553.  
  554. }
  555. /****************************************************************************
  556.  *                                                                          *
  557.  *  FUNCTION   : MenuCommand ( HWND hWnd, WPARAM wParam)                            *
  558.  *                                                                          *
  559.  *  PURPOSE    : Processes menu commands.                                   *
  560.  *                                                                          *
  561.  *  RETURNS    : TRUE  - if command could be processed.                     *
  562.  *               FALSE - otherwise                                          *
  563.  *                                                                          *
  564.  ****************************************************************************/
  565. BOOL MenuCommand (
  566.     HWND hWnd,
  567.     UINT id)
  568.  
  569. {
  570.     BITMAPINFOHEADER bi;
  571.     HDC              hDC;
  572.     HANDLE           h;
  573.     HBITMAP          hbm;
  574.     HPALETTE         hpal;
  575.     WORD             i;
  576.     CHAR             Name[40];
  577.     BOOL             bSave;
  578.     INT              xSize, ySize, xRes, yRes, dx, dy;
  579.     RECT             Rect;
  580.     HFILE            fh;
  581.     WORD             fFileOptions;
  582.     CHAR             lpBuffer[128];
  583.  
  584.     switch (id) {
  585.         case IDM_ABOUT:
  586.                 /* Show About .. box */
  587.                 fDialog ((INT)ABOUTBOX, hWnd,(FARPROC)AppAbout);
  588.                 break;
  589.  
  590.         case IDM_COPY:
  591.                 if (!bLegitDraw)
  592.                     return 0L;
  593.  
  594.                 /* Clean clipboard of contents */
  595.                 if (OpenClipboard(hWnd)) {
  596.                     EmptyClipboard ();
  597.                     SetClipboardData (CF_DIB     ,NULL);
  598.                     SetClipboardData (CF_BITMAP  ,NULL);
  599.                     SetClipboardData (CF_PALETTE ,NULL);
  600.                     CloseClipboard ();
  601.                 }
  602.                 break;
  603.  
  604.         case IDM_PASTEPAL:
  605.                 if (OpenClipboard (hWnd)) {
  606.                     if (h = GetClipboardData (CF_PALETTE)) {
  607.                         /* Delete current palette and get the CF_PALETTE data
  608.                          * from the clipboard
  609.                          */
  610.                         if (hpalCurrent)
  611.                             DeleteObject (hpalCurrent);
  612.  
  613.                         hpalCurrent = CopyPalette (h);
  614.  
  615.                         /*
  616.                          * If we have a bitmap realized against the old palette
  617.                          * delete the bitmap and rebuild it using the new palette.
  618.                          */
  619.                         if (hbmCurrent){
  620.                             DeleteObject (hbmCurrent);
  621.                             hbmCurrent = NULL;
  622.  
  623.                             if (hdibCurrent)
  624.                                 hbmCurrent = BitmapFromDib (hdibCurrent, hpalCurrent);
  625.                         }
  626.                     }
  627.                     CloseClipboard();
  628.                 }
  629.                 break;
  630.  
  631.         case IDM_PASTEDIB:
  632.                 if (OpenClipboard (hWnd)) {
  633.                     if (h = GetClipboardData (CF_DIB)) {
  634.                         /* Delete current DIB and get CF_DIB and
  635.                          * CF_PALETTE format data from the clipboard
  636.                          */
  637.                         hpal = GetClipboardData (CF_PALETTE);
  638.  
  639.                         FreeDib();
  640.                         hdibCurrent = CopyHandle (h);
  641.                         if (hdibCurrent) {
  642.                             bLegitDraw = TRUE;
  643.                             lstrcpy(achFileName,"<Clipboard>");
  644.                             hbiCurrent = hdibCurrent;
  645.  
  646.                             /* If there is a CF_PALETTE object in the
  647.                              * clipboard, this is the palette to assume
  648.                              * the DIB should be realized against, otherwise
  649.                              * create a palette for it.
  650.                              */
  651.                             if (hpal)
  652.                                 hpalCurrent = CopyPalette (hpal);
  653.                             else
  654.                                 hpalCurrent = CreateDibPalette (hdibCurrent);
  655.  
  656.                             SizeWindow(hWnd);
  657.                         }
  658.                         else {
  659.                             bLegitDraw = FALSE;
  660.                             LoadString(hInst, IDS_NOMEM, lpBuffer, sizeof(lpBuffer));
  661.                             ErrMsg(lpBuffer);
  662.                         }
  663.                     }
  664.                     CloseClipboard();
  665.                 }
  666.                 break;
  667.  
  668.         case IDM_PASTEDDB:
  669.                 if (OpenClipboard (hWnd)) {
  670.                     if (hbm = GetClipboardData(CF_BITMAP)) {
  671.                         hpal = GetClipboardData(CF_PALETTE);
  672.                         FreeDib();
  673.  
  674.                         /*
  675.                          * If there is a CF_PALETTE object in the
  676.                          * clipboard, this is the palette to assume
  677.                          * the bitmap is realized against.
  678.                          */
  679.                         if (hpal)
  680.                             hpalCurrent = CopyPalette(hpal);
  681.                         else
  682.                             hpalCurrent = GetStockObject(DEFAULT_PALETTE);
  683.  
  684.                         hdibCurrent = DibFromBitmap(hbm,BI_RGB,0,hpalCurrent);
  685.  
  686.                         if (hdibCurrent) {
  687.                             bLegitDraw = TRUE;
  688.                             lstrcpy(achFileName,"<Clipboard>");
  689.                             hbiCurrent = hdibCurrent;
  690.  
  691.                             hbmCurrent = BitmapFromDib(hdibCurrent,hpalCurrent);
  692.  
  693.                             SizeWindow(hWnd);
  694.                         }
  695.                         else {
  696.                             bLegitDraw = FALSE;
  697.                             LoadString(hInst, IDS_NOMEM, lpBuffer, sizeof(lpBuffer));
  698.                             ErrMsg(lpBuffer);
  699.                         }
  700.                     }
  701.                     CloseClipboard ();
  702.                 }
  703.                 break;
  704.  
  705.         case IDM_PRINT:
  706.                 GetWindowText(hWnd, Name, sizeof(Name));
  707.  
  708.                 DibInfo(hbiCurrent, &bi);
  709.  
  710.                 if (!IsRectEmpty(&rcClip))
  711.                 {
  712.                     bi.biWidth  = rcClip.right  - rcClip.left;
  713.                     bi.biHeight = rcClip.bottom - rcClip.top;
  714.                 }
  715.  
  716.                 /* Initialise printer stuff */
  717.                 if (!(hDC = GetPrinterDC()))
  718.                         break;
  719.  
  720.                 xSize = GetDeviceCaps(hDC, HORZRES);
  721.                 ySize = GetDeviceCaps(hDC, VERTRES);
  722.                 xRes  = GetDeviceCaps(hDC, LOGPIXELSX);
  723.                 yRes  = GetDeviceCaps(hDC, LOGPIXELSY);
  724.  
  725.                 /* Use half inch margins on left and right
  726.                  * and one inch on top. Maintain the same aspect ratio.
  727.                  */
  728.  
  729.                 dx = xSize - xRes;
  730.                 dy = (INT)((LONG)dx * bi.biHeight/bi.biWidth);
  731.  
  732.                 /* Fix bounding rectangle for the picture .. */
  733.                 Rect.top    = yRes;
  734.                 Rect.left   = xRes / 2;
  735.                 Rect.bottom = yRes + dy;
  736.                 Rect.right  = xRes / 2 + dx;
  737.  
  738.                 /* ... and inform the driver */
  739.                 Escape(hDC, SET_BOUNDS, sizeof(RECT), (LPSTR)&Rect, NULL);
  740.  
  741.                 bSave = TRUE;
  742.  
  743.                 //
  744.                 // Use new Windows NT printing APIs...Petrus Wong 12-May-1993
  745.                 //
  746.                 if (InitPrinting(hDC, hWnd, hInst, Name)) {
  747.  
  748.                         StartPage(hDC);
  749.                         PrintDIB(hWnd, hDC, xRes/2, yRes, dx, dy);
  750.  
  751.                         /* Signal to the driver to begin translating the drawing
  752.                          * commands to printer output...
  753.                          */
  754.                         EndPage(hDC);
  755.                         TermPrinting(hDC);
  756.                 }
  757.  
  758.                 DeleteDC(hDC);
  759.                 break;
  760.  
  761.         case IDM_OPEN:
  762.                 {
  763.  
  764.                 /* Bring up File/Open ... dialog */
  765.                 LoadString(hInst, IDS_OPENDIBPROMPT, lpBuffer, sizeof(lpBuffer));
  766.                 fh = DlgOpenFile (hWnd,
  767.                                   lpBuffer,
  768.                                   (LONG)OF_EXIST | OF_MUSTEXIST | OF_NOOPTIONS,
  769.                                   szBitmapExt,
  770.                                   achFileName,
  771.                                   NULL
  772.                                   );
  773.                 /*  Load up the DIB if the user did not press cancel */
  774.                 if (fh > 0) {
  775.                    StartWait();
  776.                    if (InitDIB (hWnd))
  777.                        InvalidateRect (hWnd, NULL, FALSE);
  778.                    else
  779.                        bLegitDraw = FALSE;
  780.                    EndWait();
  781.                 }
  782.                 break;
  783.                 }
  784.         case IDM_SAVE:
  785.                 DibInfo(hbiCurrent,&bi);
  786.                 fFileOptions = 0;
  787.  
  788.                 /* Depending on compression type for current DIB,
  789.                  * set the appropriate bit in the fFileOptions flag
  790.                  */
  791.                 if (bi.biCompression == BI_RGB)
  792.                     fFileOptions |= F_RGB;
  793.                 else if (bi.biCompression == BI_RLE4)
  794.                     fFileOptions |= F_RLE4;
  795.                 else if (bi.biCompression == BI_RLE8)
  796.                     fFileOptions |= F_RLE8;
  797.  
  798.                 /* Depending on bits/pixel type for current DIB,
  799.                  * set the appropriate bit in the fFileOptions flag
  800.                  */
  801.                 switch (bi.biBitCount){
  802.                     case  1:
  803.                         fFileOptions |= F_1BPP;
  804.                         break;
  805.  
  806.                     case  4:
  807.                         fFileOptions |= F_4BPP;
  808.                         break;
  809.  
  810.                     case  8:
  811.                         fFileOptions |= F_8BPP;
  812.                         break;
  813.  
  814.                     case 24:
  815.                         fFileOptions |= F_24BPP;
  816.                 }
  817.  
  818.                 /* Bring up File/Save... dialog and get info. about filename,
  819.                  * compression, and bits/pix. of DIB to be written.
  820.                  */
  821.                 LoadString(hInst, IDS_SAVEDIBPROMPT, lpBuffer, sizeof(lpBuffer));
  822.                 fh = DlgOpenFile (hWnd,
  823.                                   lpBuffer,
  824.                                   (LONG)OF_EXIST | OF_SAVE | OF_NOSHOWSPEC,
  825.                                   szBitmapExt,
  826.                                   achFileName,
  827.                                   &fFileOptions);
  828.  
  829.                 /* Extract DIB specs. if the user did not press cancel */
  830.                 if (fh != 0){
  831.                     if (fFileOptions & F_RGB)
  832.                         bi.biCompression = BI_RGB;
  833.  
  834.                     if (fFileOptions & F_RLE4)
  835.                         bi.biCompression = BI_RLE4;
  836.  
  837.                     if (fFileOptions & F_RLE8)
  838.                         bi.biCompression = BI_RLE8;
  839.  
  840.                     if (fFileOptions & F_1BPP)
  841.                         bi.biBitCount = 1;
  842.  
  843.                     if (fFileOptions & F_4BPP)
  844.                         bi.biBitCount = 4;
  845.  
  846.                     if (fFileOptions & F_8BPP)
  847.                         bi.biBitCount = 8;
  848.  
  849.                     if (fFileOptions & F_24BPP)
  850.                         bi.biBitCount = 24;
  851.  
  852.                     /* Realize a DIB in the specified format and obtain a
  853.                      * handle to it.
  854.                      */
  855.                     hdibCurrent = RealizeDibFormat(bi.biCompression,bi.biBitCount);
  856.                     if (!hdibCurrent){
  857.                         LoadString(hInst, IDS_CANTSAVEFILE, lpBuffer, sizeof(lpBuffer));
  858.                         ErrMsg(lpBuffer);
  859.                         return 0L;
  860.                     }
  861.  
  862.                     /* Write the DIB */
  863.                     StartWait();
  864.                     if (!WriteDIB(achFileName,hdibCurrent)) {
  865.                         LoadString(hInst, IDS_CANTSAVEFILE, lpBuffer, sizeof(lpBuffer));
  866.                         ErrMsg(lpBuffer);
  867.                     }
  868.                     EndWait();
  869.                 }
  870.                 break;
  871.  
  872.         case IDM_EXIT:
  873.                 PostMessage(hWnd, WM_SYSCOMMAND, SC_CLOSE, 0L);
  874.                 break;
  875.  
  876.         case IDM_UPDATECOL:
  877.                 /* Toggle state of "update screen colors" flag. If it is
  878.                  * off, clear the "hide changes" flag
  879.                  */
  880.                 bUpdateColors = !bUpdateColors;
  881.                 if (bUpdateColors)
  882.                     bNoUgly = 0;
  883.                 break;
  884.  
  885.         case IDM_DIBSCREEN:
  886.                 bDIBToDevice = !bDIBToDevice;
  887.                 InvalidateRect(hWnd, (LPRECT) (NULL), 1);
  888.                 break;
  889.  
  890.         case IDM_MEMORYDIB:
  891.                 break;
  892.  
  893.         case IDM_NOUGLY:
  894.                 /* Toggle state of "hide changes" flag. If it is off, clear
  895.                  * the "update screen colors" flag. This will tell SHOWDIB
  896.                  * to paint itself black while the palette is changing.
  897.                  */
  898.                 bNoUgly = !bNoUgly;
  899.                 if (bNoUgly)
  900.                     bUpdateColors = 0;
  901.                 break;
  902.  
  903.         case IDM_TRANSPARENT:
  904.                 /* Toggle DC mode */
  905.                 wTransparent = (WORD) (wTransparent == TRANSPARENT ?
  906.                     OPAQUE : TRANSPARENT);
  907.                 break;
  908.  
  909.         case IDM_ANIMATE0:
  910.                 if (!hpalSave)
  911.                     break;
  912.  
  913.                 /* Reset animation count and stop timer */
  914.                 KillTimer(hWnd, 1);
  915.                 nAnimating = 0;
  916.  
  917.                 /* Restore palette which existed before animation started */
  918.                 DeleteObject(hpalCurrent);
  919.                 hpalCurrent = hpalSave;
  920.  
  921.                 /* Rebuild bitmap based on newly realized information */
  922.                 hDC = GetDC (hWnd);
  923.                 SelectPalette (hDC, hpalCurrent, 0);
  924.                 RealizePalette (hDC);
  925.                 ReleaseDC (hWnd, hDC);
  926.  
  927.                 if (hbmCurrent){
  928.                     DeleteObject (hbmCurrent);
  929.                     hbmCurrent = NULL;
  930.  
  931.                     if (hdibCurrent)
  932.                        hbmCurrent = BitmapFromDib (hdibCurrent, hpalCurrent);
  933.                 }
  934.                 hpalSave = NULL;
  935.  
  936.                 /* Force redraw with new palette for everyone */
  937.                 InvalidateRect(hWnd, NULL, TRUE);
  938.                 break;
  939.  
  940.         case IDM_STEALCOL:
  941.         case IDM_ANIMATE5:
  942.         case IDM_ANIMATE20:
  943.         case IDM_ANIMATE50:
  944.         case IDM_ANIMATE100:
  945.         case IDM_ANIMATE200:
  946.         case IDM_ANIMATE201:
  947.                 /* Set animation count i.e number of times animation is to
  948.                  * take place.
  949.                  */
  950.                 nAnimating = id;
  951.                 if (id == IDM_STEALCOL)
  952.                         nAnimating = 0;
  953.  
  954.                 /* Save current palette */
  955.                 hpalSave = CopyPalette(hpalCurrent);
  956.  
  957.                 GetObject(hpalCurrent, sizeof(INT), (LPSTR)&pLogPal->palNumEntries);
  958.                 GetPaletteEntries(hpalCurrent, 0, pLogPal->palNumEntries, pLogPal->palPalEntry);
  959.  
  960.                 /* Reserve all entries in the palette otherwise AnimatePalette()
  961.                  * will not modify them
  962.                  */
  963.                 for (i = 0; i < pLogPal->palNumEntries; i++) {
  964.                      pLogPal->palPalEntry[i].peFlags = (BYTE)PC_RESERVED;
  965.                 }
  966.  
  967.                 SetPaletteEntries(hpalCurrent, 0, pLogPal->palNumEntries, pLogPal->palPalEntry);
  968.  
  969.                 /* Rebuild bitmap based on newly realized information */
  970.                 if (hbmCurrent){
  971.                     DeleteObject (hbmCurrent);
  972.                     hbmCurrent = NULL;
  973.  
  974.                     if (hdibCurrent)
  975.                        hbmCurrent = BitmapFromDib (hdibCurrent, hpalCurrent);
  976.                 }
  977.  
  978.                 /* Force redraw with new palette for everyone */
  979.                 InvalidateRect(hWnd, NULL, TRUE);
  980.  
  981.                 /* Initiate the timer so that palette can be animated in
  982.                  * response to a WM_TIMER message
  983.                  */
  984.                 if (nAnimating && !SetTimer(hWnd, 1, 250, (TIMERPROC)(LPSTR) NULL))
  985.                         nAnimating = 0;
  986.  
  987.         default:
  988.                 break;
  989.     }
  990.  
  991.     return TRUE;
  992. }
  993.  
  994. /****************************************************************************
  995.  *                                                                          *
  996.  *  FUNCTION   : InitDIB(hWnd)                                              *
  997.  *                                                                          *
  998.  *  PURPOSE    : Reads a DIB from a file, obtains a handle to it's          *
  999.  *               BITMAPINFO struct., sets up the palette and loads the DIB. *
  1000.  *                                                                          *
  1001.  *  RETURNS    : TRUE  - DIB loads ok                                       *
  1002.  *               FALSE - otherwise                                          *
  1003.  *                                                                          *
  1004.  ****************************************************************************/
  1005. INT InitDIB(HWND hWnd)
  1006. {
  1007.     HFILE              fh;
  1008.     LPBITMAPINFOHEADER lpbi;
  1009.     WORD FAR *         pw;
  1010.     INT                i;
  1011.     BITMAPINFOHEADER   bi;
  1012.     OFSTRUCT           of;
  1013.     CHAR               lpBuffer[128];
  1014.  
  1015.     FreeDib();
  1016.  
  1017.     /* Open the file and get a handle to it's BITMAPINFO */
  1018.  
  1019.     fh = OpenFile(achFileName, (LPOFSTRUCT)&of, (UINT)OF_READ);
  1020.     if (fh == -1) {
  1021.         LoadString(hInst, IDS_CANTOPENFILE, lpBuffer, sizeof(lpBuffer));
  1022.         ErrMsg(lpBuffer, (LPSTR)achFileName);
  1023.         return FALSE;
  1024.     }
  1025.     hbiCurrent = ReadDibBitmapInfo(fh);
  1026.  
  1027.     dwOffset = _llseek(fh, 0L, (UINT)SEEK_CUR);
  1028.     _lclose(fh);
  1029.  
  1030.     if (hbiCurrent == NULL) {
  1031.         LoadString(hInst, IDS_BADDIBFILE, lpBuffer, sizeof(lpBuffer));
  1032.         ErrMsg(lpBuffer, (LPSTR)achFileName);
  1033.         return FALSE;
  1034.     }
  1035.     DibInfo(hbiCurrent,&bi);
  1036.  
  1037.     /* Set up the palette */
  1038.     hpalCurrent = CreateDibPalette(hbiCurrent);
  1039.     if (hpalCurrent == NULL) {
  1040.         LoadString(hInst, IDS_CREATEPALFAIL, lpBuffer, sizeof(lpBuffer));
  1041.         ErrMsg(lpBuffer);
  1042.         return FALSE;
  1043.     }
  1044.  
  1045.     /*  Convert the DIB color table to palette relative indexes, so
  1046.      *  SetDIBits() and SetDIBitsToDevice() can avoid color matching.
  1047.      *  We can do this because the palette we realize is identical
  1048.      *  to the color table of the bitmap, ie the indexes match 1 to 1
  1049.      *
  1050.      *  Now that the DIB color table is palette indexes not RGB values
  1051.      *  we must use DIB_PAL_COLORS as the wUsage parameter to SetDIBits()
  1052.      */
  1053.     lpbi = (VOID FAR *)GlobalLock(hbiCurrent);
  1054.     if (lpbi->biBitCount != 24) {
  1055.         fPalColors = TRUE;
  1056.  
  1057.         pw = (WORD FAR *)((LPSTR)lpbi + lpbi->biSize);
  1058.  
  1059.         for (i=0; i<(INT)lpbi->biClrUsed; i++)
  1060.             *pw++ = (WORD)i;
  1061.     }
  1062.     GlobalUnlock(hbiCurrent);
  1063.     bLegitDraw = TRUE;
  1064.  
  1065.     /*  If the input bitmap is not in RGB FORMAT the banding code will
  1066.      *  not work!  we need to load the DIB bits into memory.
  1067.      *  if memory DIB, load it all NOW!  This will avoid calling the
  1068.      *  banding code.
  1069.      */
  1070.     hdibCurrent = OpenDIB(achFileName);
  1071.  
  1072.     /*  If the RLE could not be loaded all at once, exit gracefully NOW,
  1073.      *  to avoid calling the banding code
  1074.      */
  1075.     if ((bi.biCompression != BI_RGB) && !hdibCurrent){
  1076.         LoadString(hInst, IDS_CANTLOADRLE, lpBuffer, sizeof(lpBuffer));
  1077.         ErrMsg (lpBuffer);
  1078.         FreeDib();
  1079.         return FALSE;
  1080.     }
  1081.  
  1082.     if (hdibCurrent && !bDIBToDevice){
  1083.         hbmCurrent = BitmapFromDib(hdibCurrent,hpalCurrent);
  1084.         if (!hbmCurrent){
  1085.             LoadString(hInst, IDS_CANTCREATEBMP, lpBuffer, sizeof(lpBuffer));
  1086.             ErrMsg (lpBuffer);
  1087.             FreeDib();
  1088.             return FALSE;
  1089.         }
  1090.     }
  1091.  
  1092.     SizeWindow(hWnd);
  1093.  
  1094.     return TRUE;
  1095. }
  1096. /****************************************************************************
  1097.  *                                                                          *
  1098.  *  FUNCTION   : FreeDib(void)                                              *
  1099.  *                                                                          *
  1100.  *  PURPOSE    : Frees all currently active bitmap, DIB and palette objects *
  1101.  *               and initializes their handles.                             *
  1102.  *                                                                          *
  1103.  ****************************************************************************/
  1104. VOID FreeDib()
  1105. {
  1106.     if (hpalCurrent)
  1107.         DeleteObject(hpalCurrent);
  1108.  
  1109.     if (hbmCurrent)
  1110.         DeleteObject(hbmCurrent);
  1111.  
  1112.     if (hdibCurrent)
  1113.         GlobalFree(hdibCurrent);
  1114.  
  1115.     if (hbiCurrent && hbiCurrent != hdibCurrent)
  1116.         GlobalFree(hbiCurrent);
  1117.  
  1118.     fPalColors  = FALSE;
  1119.     bLegitDraw  = FALSE;
  1120.     hpalCurrent = NULL;
  1121.     hdibCurrent = NULL;
  1122.     hbmCurrent  = NULL;
  1123.     hbiCurrent  = NULL;
  1124.     SetRectEmpty (&rcClip);
  1125. }
  1126.