home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / win_sdk / showdib / showdib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-01  |  28.8 KB  |  1,080 lines

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