home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tolkit45.zip / os2tk45 / samples / open32 / toybox2 / toybox.c < prev    next >
Text File  |  1999-05-11  |  38KB  |  874 lines

  1. /*************************************************************************
  2.  * Copyright (C) International Business Machines Corp., 1995.
  3.  *
  4.  * ToyBox is a basic Win32 application that uses BITBLT to display a
  5.  * large number of simple bitmaps on the display screen and give them
  6.  * motion. It moves the objects both around the client portion of the
  7.  * screen, and makes the objects appear to change shape and rotate.
  8.  *
  9.  * This program displays a menu with five choices:
  10.  *
  11.  *      Main               - Display a submenu with the following five items:
  12.  *        Start            - Start movement on the screen.
  13.  *        Stop             - Stop movement on the screen.
  14.  *        Maximum Toys     - Display maximum number of objects.
  15.  *        Minimum Toys     - Remove All objects from the screen.
  16.  *      Quit               - Terminate this program.
  17.  *
  18.  *      Add Toy            - Display an additional object, up to a preset limit.
  19.  *
  20.  *      Delete Toy         - Remove an object from the screen.
  21.  *
  22.  *  Step Toys              - If the objects are not in motion, move them one
  23.  *                           step per press of the control
  24.  *
  25.  *  Help              - Display a submenu with two subitems:
  26.  *  General Help      - Explain the basic program operation to the user.
  27.  *  About             - Display program and author information.
  28.  *
  29.  *
  30.  ************************************************************************/
  31.  
  32.  
  33. /*************************************************************************
  34.  * include files of common stuff that we need to use.
  35.  ************************************************************************/
  36.  
  37. #include "toybox.h"
  38. #include <stdlib.h>
  39. #include <string.h>
  40.  
  41. /*************************************************************************
  42.  * These are the function prototypes for functions that we call.
  43.  ************************************************************************/
  44.  
  45. LRESULT CALLBACK WndProc(HWND hWnd,UINT messg,WPARAM wParam,LPARAM lParam);
  46. LRESULT CALLBACK AboutProc(HWND hWnd,UINT messg,WPARAM wParam,LPARAM lParam);
  47. void NewObject(int ObjIndex);
  48. void MoveObject(HWND InhWnd, int DoMoveObject);
  49. int iRand_Num(int lower_limit, int upper_limit);
  50. int iRand_Range(int lower_limit, int upper_limit, int low_excld, int up_excld);
  51. void SetWinText(HWND InhWnd);
  52. void LoadBMP(HANDLE InInstance);
  53. void AnimateObjects(HDC hToDC);
  54.  
  55. /*************************************************************************
  56.  * Generic variables needed by this program.
  57.  ************************************************************************/
  58.  
  59. char TitleText[]="Toy Box Demo - [Toys ";   /* default title        */
  60. int iScreenX;                               /* client X in pixels   */
  61. int iScreenY;;                              /* client Y in pixles   */
  62. int Screen_OK;                              /* screen status        */
  63. int ObjCount;                               /* # of active objects  */
  64. int ObjActive=0;                            /* no active objects    */
  65. int MaxBmpX=0;                              /* Max in X direction   */
  66. int MaxBmpY=0;                              /* Max in Y direction   */
  67. HWND hAbout;                                /* about windows hwnd   */
  68. RECT ChildDrawRect;                         /* child drawing rect   */
  69. HDC hToDC;                                  /* DC we display on     */
  70. HBITMAP hObjBMP[MAX_OBJ_TYPE][MAX_OBJ_FRAME];   /* bitmap for all   */
  71. HDC PixDC[MAX_OBJ_TYPE][MAX_OBJ_FRAME];         /* preselected DCs  */
  72. char AboutText[]="\n\nToy Box Bit Blit Demo\nVersion 1.01"
  73.                  "\nCopyright 1995\nIBM Corporation\nby Daniel Mendrala\n";
  74.  
  75. /*************************************************************************
  76.  * A structure to hold information about each object on the screen.
  77.  ************************************************************************/
  78.  
  79. typedef struct tagObjArrayType
  80.  { int ObjX;                                /* Objects's X                  */
  81.    int ObjY;                                /* Objects's Y                  */
  82.    int ObjWX;                               /* Width of X                   */
  83.    int ObjWY;                               /* Width of Y                   */
  84.    int ObjType;                             /* what Object ?                */
  85.    int ObjFrame;                            /* picture frame                */
  86.    int ObjDX;                               /* Object Delta X               */
  87.    int ObjDY;                               /* Object Delta Y               */
  88.    int ObjStatus;                           /* Object Status                */
  89.    int SpinCnt;                             /* curr spin cycle count        */
  90.    int SpinWait;                            /* # cycles before spin         */
  91.  } ObjArrayType;
  92.  
  93.  ObjArrayType ObjArray[MAX_OBJ+1];          /* 1 based, all objects */
  94.  ObjArrayType RollObj[MAX_OBJ_TYPE+1];      /* 1 based, one of each */
  95.  
  96. /*************************************************************************
  97.  * A structure to hold info about each type of object. Picture data.
  98.  ************************************************************************/
  99.  
  100. typedef struct tagPixType
  101.  {
  102.   int X;                                    /* bitmap size in X             */
  103.   int Y;                                    /* bitmap size in Y             */
  104.   int Frame;                                /* # frames animation           */
  105.   int Speed;                                /* Wait time for frames         */
  106.   int MDX;                                  /* Max Delta X                  */
  107.   int MDY;                                  /* Max Delta Y                  */
  108.  } PixType;
  109.  
  110.  PixType Pix[MAX_OBJ_TYPE];                 /* all possible types           */
  111.  
  112. /*************************************************************************
  113.  *
  114.  * The main program sets up all of the information needed to register the
  115.  * window class. It then creates the window, shows it then enters the
  116.  * message loop that processes all of the messages until the user
  117.  * exits the program.
  118.  *
  119.  ************************************************************************/
  120.  
  121. int WINAPI WinMain (HINSTANCE hInstance,HINSTANCE hPreInst,
  122.                                         LPSTR lpszCmdLine,int nCmdShow) {
  123.  
  124. HWND hWnd;
  125. MSG Msg;
  126. WNDCLASS wcApp;
  127.  
  128. if (!hPreInst)
  129. {
  130.  wcApp.style=                   CS_HREDRAW|CS_VREDRAW;
  131.  wcApp.hInstance=               hInstance;
  132.  wcApp.lpfnWndProc=     WndProc;
  133.  wcApp.hCursor=                 LoadCursor(NULL,IDC_ARROW);
  134.  wcApp.hIcon=                   LoadIcon(hInstance,MAKEINTRESOURCE(ToyIcon));
  135.  wcApp.lpszMenuName=    (const unsigned char *)ToyMenu;
  136.  wcApp.lpszClassName=   "ToyClass";
  137.  wcApp.hbrBackground=   GetStockObject(BLACK_BRUSH);
  138.  wcApp.cbClsExtra=              0;
  139.  wcApp.cbWndExtra=              0;
  140.  
  141.  if (!RegisterClass(&wcApp))
  142.    return FALSE;
  143.  
  144.  wcApp.style=                   CS_HREDRAW|CS_VREDRAW;
  145.  wcApp.hInstance=               hInstance;
  146.  wcApp.lpfnWndProc=     AboutProc;;
  147.  wcApp.hCursor=                 LoadCursor(NULL,IDC_ARROW);
  148.  wcApp.hIcon=                   LoadIcon(hInstance,MAKEINTRESOURCE(ToyIcon));
  149.  wcApp.lpszMenuName=    NULL;
  150.  wcApp.lpszClassName=   "AboutClass";
  151.  wcApp.hbrBackground=   GetStockObject(BLACK_BRUSH);
  152.  wcApp.cbClsExtra=              0;
  153.  wcApp.cbWndExtra=              0;
  154.  
  155.  if (!RegisterClass(&wcApp))
  156.    return FALSE;
  157.  
  158. }
  159.  
  160. hWnd = CreateWindow("ToyClass",
  161.                     "Toy Box Demo",
  162.                     WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN,
  163.                     CW_USEDEFAULT,
  164.                     CW_USEDEFAULT,
  165.                     CW_USEDEFAULT,
  166.                     CW_USEDEFAULT,
  167.                     NULL,
  168.                     NULL,
  169.                     hInstance,
  170.                     NULL);
  171.  
  172. ShowWindow(hWnd,nCmdShow);
  173.  
  174. /*************************************************************************
  175.  *
  176.  * Now we peek to see if a message is in the queue. If their is one, then
  177.  * we dispatch the message, otherwise if the 'Start' option has selected
  178.  * we move all of the objects on the screen and then sleep for a short
  179.  * amount of time. The repeats until the user quits the program.
  180.  *
  181.  ************************************************************************/
  182.  
  183. while (TRUE)
  184.  {
  185.   if (PeekMessage (&Msg,NULL,0,0,PM_REMOVE))
  186.   {
  187.    if (Msg.message==WM_QUIT)
  188.     return Msg.wParam;
  189.    else
  190.    {
  191.     TranslateMessage(&Msg);
  192.         DispatchMessage(&Msg);
  193.    }
  194.   }                                         /* end if message wait          */
  195.   else if (ObjActive)
  196.    {
  197.     MoveObject(hWnd,TRUE);
  198.     Sleep(10);                              /* sleep 10 MS                  */
  199.    }
  200.  }                                          /* end While                    */
  201. }                                           /* end WinMain                  */
  202.  
  203. /*************************************************************************
  204.  *
  205.  * This is the window procedure for the main window. The following
  206.  * messages are processed by this procedure:
  207.  *
  208.  * WM_CREATE               Get the destination DC, initial setup, load bitmaps
  209.  * WM_SIZE                 Save the new X and Y client sizes and repaint client
  210.  * WM_MOVE                 Repaint client
  211.  * WM_DESTROY              Post a quit message
  212.  * WM_PAINT                Just re-draw the objects in the client window
  213.  * WM_COMMAND
  214.  *         IDM_START       Toggle checkmarks and active the objects movement
  215.  *         IDM_STOP        Toggle checkmarks and deactive the object movement
  216.  *         IDM_DELOBJ      If any objects exist, remove the last one and redraw
  217.  *         IDM_ADDOBJ      If below limit, add a new object and redraw
  218.  *         IDM_MINOBJ      While any objects exist, mark for delete and redraw
  219.  *         IDM_MAXOBJ      While below limit, add a new object, then redraw
  220.  *         IDM_STEP        Move the objects one step
  221.  *         IDM_HELP        Display some minimal help
  222.  *         IDM_ABOUT       Display title, version and author information in
  223.  *                                   an animated dialog box
  224.  *         IDM_QUIT        For all frames, delete DC and delete BMP
  225.  *
  226.  ************************************************************************/
  227. LRESULT CALLBACK WndProc(HWND hWnd,UINT messg,WPARAM wParam,LPARAM lParam)
  228. {
  229.  HDC hdc;
  230.  PAINTSTRUCT ps;
  231.  HMENU hmenu;
  232.  HANDLE hInstance;
  233.  
  234.  hInstance = (HANDLE) GetWindowLong (hWnd,GWL_HINSTANCE);
  235.  hmenu=GetMenu(hWnd);
  236.  
  237.  switch (messg) {
  238.  
  239.   case WM_CREATE:
  240.    {
  241.     hToDC=GetDC(hWnd);
  242.         ObjCount=0;
  243.         ObjActive=FALSE;
  244.         CheckMenuItem(hmenu,IDM_STOP,MF_CHECKED|MF_BYCOMMAND);
  245.         Screen_OK=FALSE;                    /* assume bad screen */
  246.         SetWinText(hWnd);
  247.         LoadBMP(hInstance);
  248.     /*DrawText(hToDC,AboutText,-1,&ChildDrawRect,DT_CENTER|DT_CALCRECT);*/
  249.     ChildDrawRect.left=0;
  250.     ChildDrawRect.top=0;
  251.     ChildDrawRect.right=144+MaxBmpX*2;
  252.         ChildDrawRect.bottom=128+MaxBmpY*2;
  253.    }
  254.   break;                                    /* WM_CREATE                    */
  255.  
  256.   case WM_SIZE:
  257.    {
  258.         iScreenX=LOWORD(lParam);            /* save screen X                */
  259.         iScreenY=HIWORD(lParam);            /* save screen Y                */
  260.         InvalidateRect(hWnd,NULL,TRUE);
  261.    }
  262.   break;                                    /* WM_SIZE                      */
  263.  
  264.   case WM_MOVE:
  265.    {
  266.     InvalidateRect(hWnd,NULL,TRUE);
  267.    }
  268.   break;                                    /* WM_MOVE                      */
  269.  
  270.   case WM_DESTROY:
  271.    {
  272.         PostQuitMessage(0);
  273.    }
  274.   break;                                    /* WM_DESTROY                   */
  275.  
  276.   case WM_PAINT:
  277.    {
  278.         hdc = BeginPaint(hWnd,&ps);
  279.         Screen_OK=FALSE;                    /* fix up redraws               */
  280.         MoveObject(hWnd,FALSE);
  281.         EndPaint(hWnd,&ps);
  282.    }
  283.   break;                                    /* WM_PAINT                     */
  284.  
  285.   case WM_COMMAND:
  286.    switch (LOWORD(wParam))
  287.     {
  288.      case IDM_START:
  289.           {
  290.            CheckMenuItem(hmenu,IDM_START,MF_CHECKED|MF_BYCOMMAND);
  291.            CheckMenuItem(hmenu,IDM_STOP,MF_UNCHECKED|MF_BYCOMMAND);
  292.            ObjActive=TRUE;
  293.           }
  294.          break;                             /* IDM_START                    */
  295.  
  296.          case IDM_STOP:
  297.           {
  298.            CheckMenuItem(hmenu,IDM_START,MF_UNCHECKED|MF_BYCOMMAND);
  299.            CheckMenuItem(hmenu,IDM_STOP,MF_CHECKED|MF_BYCOMMAND);
  300.            ObjActive=FALSE;
  301.           }
  302.          break;
  303.  
  304.          case IDM_DELOBJ:
  305.           {
  306.            if (ObjCount>0)
  307.             {
  308.              ObjArray[ObjCount].ObjStatus=BIT_DELOBJ;  /* tag for delete    */
  309.                  MoveObject(hWnd,FALSE);
  310.                  SetWinText(hWnd);
  311.             }                               /* if any objects exist         */
  312.           }
  313.          break;                             /* IDM_DELOBJ                   */
  314.  
  315.          case IDM_ADDOBJ:
  316.           {
  317.            if (ObjCount+1<=MAX_OBJ)
  318.             {
  319.                  ObjCount++;
  320.                  NewObject(ObjCount);       /* make the new object          */
  321.                  MoveObject(hWnd,FALSE);
  322.                  SetWinText(hWnd);
  323.                 }                           /* if below add limit           */
  324.           }
  325.          break;                             /* IDM_ADDOBJ                   */
  326.  
  327.          case IDM_MINOBJ:
  328.           {
  329.            int TempCtr;
  330.            for (TempCtr=1;TempCtr<=ObjCount;TempCtr++)
  331.             {
  332.          ObjArray[TempCtr].ObjStatus=BIT_DELOBJ;  /* tag for delete         */
  333.             }                                     /* if object exist        */
  334.            MoveObject(hWnd,FALSE);                /* force redraw           */
  335.            SetWinText(hWnd);
  336.           }
  337.          break;                             /* IDM_MINOBJ                   */
  338.  
  339.          case IDM_MAXOBJ:
  340.           {
  341.            while (ObjCount+1<=MAX_OBJ)
  342.            {
  343.             ObjCount++;
  344.             NewObject(ObjCount);            /* make the object              */
  345.            }
  346.            MoveObject(hWnd,FALSE);          /* force redraw                 */
  347.            SetWinText(hWnd);
  348.           }
  349.          break;                             /* IDM_ADDOBJ                   */
  350.  
  351.     case IDM_STEP:
  352.          {
  353.           MoveObject(hWnd,TRUE);
  354.          }
  355.         break;                              /* IDM_STEP                     */
  356.  
  357.         case IDM_HELP:
  358.          {
  359.           MessageBox(hWnd,"Click on 'Main' then 'Start', then 'Add Toy' to "
  360.                      "add additional toys to the screen or 'Delete Toy' "
  361.                      "to remove toys.",
  362.                      "Help for Toy Box Bit Blit Demo",
  363.                       MB_ICONINFORMATION | MB_OK);
  364.          }
  365.         break;                              /* IDM_HELP                      */
  366.  
  367.         case IDM_QUIT:
  368.          {
  369.           int Type;
  370.           int Frame;
  371.            for (Type=0;Type<MAX_OBJ_TYPE;Type++)
  372.             {
  373.                  for (Frame=0;Frame<Pix[Type].Frame;Frame++)
  374.                   {
  375.                    DeleteDC(PixDC[Type][Frame]);
  376.                    DeleteObject(hObjBMP[Type][Frame]);
  377.                   }
  378.             }
  379.            DestroyWindow(hWnd);
  380.          }                                  /* IDM_QUIT                     */
  381.         break;
  382.  
  383.         case IDM_ABOUT:
  384.          {
  385.           if (!hAbout)                      /* only allow one               */
  386.            {
  387.         hAbout= CreateWindow("AboutClass",
  388.                  "About Toy Box",
  389.                  WS_POPUP|WS_VISIBLE|WS_CAPTION|WS_BORDER,
  390.                  CW_USEDEFAULT,
  391.                  CW_USEDEFAULT,
  392.                  ChildDrawRect.right,       /* so text fits                 */
  393.                  ChildDrawRect.bottom,      /* for text                     */
  394.                  hWnd,
  395.                  NULL,
  396.                  hInstance,
  397.                  NULL);
  398.        CheckMenuItem(hmenu,IDM_ABOUT,MF_CHECKED|MF_BYCOMMAND);
  399.           }
  400.           else
  401.           {
  402.            DestroyWindow(hAbout);
  403.        CheckMenuItem(hmenu,IDM_ABOUT,MF_UNCHECKED|MF_BYCOMMAND);
  404.           }
  405.          }
  406.         break;                              /* IDM_ABOUT                    */
  407.  
  408.         default:
  409.         break;
  410.    }                                        /* WM_COMMAND                   */
  411.    break;
  412.    default:
  413.    return(DefWindowProc(hWnd,messg,wParam,lParam));
  414.   }                                         /* end Switch                   */
  415.  return(0L);
  416. }                                           /* end WndProc                  */
  417.  
  418. /*************************************************************************
  419.  * This moves all of the objects displayed on the screen. First it erases
  420.  * any object already on the screen, then if the objects are to be moved
  421.  * it moves them and makes sure that they do not overdraw the edge of the
  422.  * screen, then it draws them back on the screen. Finally, if any of them
  423.  * are marked for delete, it deletes them.
  424.  *
  425.  * Note: If DoMoveObject flag is FALSE, we just re-draw the objects,
  426.  *       otherwise we move and redraw the objects.
  427.  ************************************************************************/
  428. void MoveObject(HWND InhWnd, int DoMoveObject)
  429. {
  430.  int TempCtr;
  431.  int Tx,Ty;
  432.  int TFrame;
  433.  int TType;
  434.  int tWX,tWY;
  435.  int DelObjCount=0;
  436.  
  437.  if (Screen_OK==FALSE)                      /* if bad screen, erase */
  438.   {
  439.    SelectObject(hToDC,GetStockObject(BLACK_BRUSH));
  440.    Rectangle(hToDC,0,0,iScreenX,iScreenY);
  441.   }
  442.  for (TempCtr=1;TempCtr<=ObjCount;TempCtr++)
  443.   {
  444.    Tx=ObjArray[TempCtr].ObjX;
  445.    Ty=ObjArray[TempCtr].ObjY;
  446.    tWX=ObjArray[TempCtr].ObjWX;
  447.    tWY=ObjArray[TempCtr].ObjWY;
  448.    TFrame=ObjArray[TempCtr].ObjFrame;
  449.    TType=ObjArray[TempCtr].ObjType;
  450.    if (ObjArray[TempCtr].ObjStatus==BIT_NEWOBJ)
  451.     {
  452.      ObjArray[TempCtr].ObjStatus=BIT_ACTOBJ; /* make object active      */
  453.     }
  454.    else
  455.         {
  456.          if (Screen_OK==TRUE)               /* erase if scrren OK       */
  457.          BitBlt(hToDC,Tx,Ty,tWX,tWY,PixDC[TType][TFrame],0,0,SRCINVERT);
  458.         }
  459.    if (DoMoveObject==TRUE)                  /* if move mode, move em    */
  460.         {
  461.          Tx+=ObjArray[TempCtr].ObjDX;
  462.          Ty+=ObjArray[TempCtr].ObjDY;
  463.          ObjArray[TempCtr].SpinCnt++;       /* do frame animation       */
  464.          if (ObjArray[TempCtr].SpinCnt>ObjArray[TempCtr].SpinWait)
  465.          {
  466.           ObjArray[TempCtr].SpinCnt=1;
  467.           TFrame++;
  468.           if (TFrame>=Pix[TType].Frame)
  469.           {
  470.            TFrame=0;
  471.           }
  472.           ObjArray[TempCtr].ObjFrame=TFrame;
  473.          }
  474.          if ((Tx+tWX)>iScreenX)             /* off screen right ?       */
  475.           {
  476.            Tx=iScreenX-tWX;
  477.            ObjArray[TempCtr].ObjDX=-iRand_Num(1,Pix[TType].MDX);
  478.           }                                 /* if Tx+Delta > Screen     */
  479.          else
  480.          if (Tx<0)                          /* of screen left ?         */
  481.           {
  482.        Tx=0;
  483.            ObjArray[TempCtr].ObjDX=iRand_Num(1,Pix[TType].MDX);
  484.           }                                 /* Tx < Screen              */
  485.          if ((Ty+tWY)>iScreenY)             /* off screen bottom        */
  486.           {
  487.            Ty=iScreenY-tWY;
  488.            ObjArray[TempCtr].ObjDY=-iRand_Num(1,Pix[TType].MDY);
  489.           }                                 /* if Ty+Delta > Screen     */
  490.          else
  491.          if (Ty<0)                          /* off top of screen        */
  492.           {
  493.        Ty=0;
  494.            ObjArray[TempCtr].ObjDY=iRand_Num(1,Pix[TType].MDY);
  495.           }                                 /* Tx < Screen              */
  496.          ObjArray[TempCtr].ObjX=Tx;
  497.          ObjArray[TempCtr].ObjY=Ty;
  498.          }                                  /* if DoMoveObject          */
  499.          if (ObjArray[TempCtr].ObjStatus==BIT_DELOBJ)
  500.           {
  501.            DelObjCount++;                          /* we delete later    */
  502.            ObjArray[TempCtr].ObjStatus=BIT_NONOBJ; /* mark unused        */
  503.           }                                        /* if deleting object */
  504.          else
  505.           {
  506.            BitBlt(hToDC,Tx,Ty,tWX,tWY,PixDC[TType][TFrame],0,0,SRCINVERT);
  507.           }                                 /* if we can see object         */
  508.    }                                        /* end TempCtr                  */
  509.  ObjCount-=DelObjCount;                     /* remove the objects           */
  510.  Screen_OK=TRUE;                            /* Objects are now OK           */
  511. }                                           /* end MoveObject               */
  512.  
  513. /*************************************************************************
  514.  *
  515.  * This routine creats a new object and places it somewhere on the
  516.  * client area. The object gets a random delta in X and Y directions
  517.  * and a random type and starting frame number.
  518.  * We don't care about the object possibly being off the screen, since it
  519.  * will be fixed up when it is moved.
  520.  *
  521.  ************************************************************************/
  522. void NewObject(int ObjIndex)
  523. {
  524.  int TempType;
  525.  TempType=iRand_Num(1,MAX_OBJ_TYPE)-1;
  526.  ObjArray[ObjIndex].ObjX=iRand_Num(1,iScreenX);
  527.  ObjArray[ObjIndex].ObjY=iRand_Num(1,iScreenY);
  528.  ObjArray[ObjIndex].ObjType=TempType;
  529.  ObjArray[ObjIndex].ObjFrame=iRand_Num(1,Pix[TempType].Frame)-1;
  530.  ObjArray[ObjIndex].SpinCnt=1;
  531.  ObjArray[ObjIndex].SpinWait=Pix[TempType].Speed;
  532.  ObjArray[ObjIndex].ObjWX=Pix[TempType].X;
  533.  ObjArray[ObjIndex].ObjWY=Pix[TempType].Y;
  534.  ObjArray[ObjIndex].ObjDX=iRand_Range(0,Pix[TempType].MDX*2,
  535.     Pix[TempType].MDX,Pix[TempType].MDX)-Pix[TempType].MDX;
  536.  ObjArray[ObjIndex].ObjDY=iRand_Range(0,Pix[TempType].MDY*2,
  537.     Pix[TempType].MDY,Pix[TempType].MDY)-Pix[TempType].MDY;
  538.  ObjArray[ObjIndex].ObjStatus=BIT_NEWOBJ;
  539. }                                           /* end NewObject                 */
  540.  
  541. /*************************************************************************
  542.  *
  543.  * This routine sets the text displayed in the title bar of the InhWnd
  544.  * equal to the predefined string TitleText and the number of objects
  545.  * currently on the screen.
  546.  *
  547.  ************************************************************************/
  548. void SetWinText(HWND InhWnd)
  549. {
  550.  char TempBuff[32];                         /* temporary                    */
  551.  char NewWinText[128];                      /* new window title             */
  552.  
  553.  strcpy(NewWinText,TitleText);              /* get default text             */
  554.  wsprintf(TempBuff,"%i",ObjCount);          /* format object count          */
  555.  strcat(NewWinText,TempBuff);               /* add it to title              */
  556.  strcat(NewWinText,"]");                    /* add ending character         */
  557.  SetWindowText(InhWnd,NewWinText);          /* set the text                 */
  558. }                                           /* SetWinText                   */
  559.  
  560. /*************************************************************************
  561.  *
  562.  * This routine generates a random number that is between (and including)
  563.  * the lower_limit and the upper_limit.
  564.  *
  565.  * For example, to generate a number inclusive to +5 and +15:
  566.  *
  567.  *  x=iRand_Num(5,15);
  568.  *
  569.  ************************************************************************/
  570. int iRand_Num(int lower_limit, int upper_limit)
  571. {
  572.  int i;
  573.  i=(rand()%(upper_limit-lower_limit+1))+lower_limit;
  574.  return (i);
  575. }                                           /* end iRand_Num                */
  576.  
  577. /*************************************************************************
  578.  *
  579.  * This routine generates a random number that is between (and including)
  580.  * the lower_limit and the upper_limit, and does NOT contain any number
  581.  * between (and including) the low_excld and the up_excld.
  582.  *
  583.  * For example, to generate a number between -5 and +5 and not allow zero:
  584.  *
  585.  *  x=iRand_Range(-5,5,0,0);
  586.  *
  587.  ************************************************************************/
  588. int iRand_Range(int lower_limit, int upper_limit, int low_excld, int up_excld)
  589. {
  590.  int i;
  591.  retry:
  592.  i=(rand()%(upper_limit-lower_limit+1))+lower_limit;
  593.  if (i>=low_excld && i<=up_excld)           /* is it between limits         */
  594.   { goto retry;}                            /* nope, try again              */
  595.  return (i);
  596. }                                           /* end iRand_Range              */
  597.  
  598. /*************************************************************************
  599.  *
  600.  * This routine just loads in all of the bitmaps used for this program
  601.  * and sets all of the information needed for each group of objects
  602.  * (the Pix[].xxx data fields).
  603.  *
  604.  * The really important step is done at the end of this routine, which is
  605.  * to create a DC for each frame of each object group and then select
  606.  * into the DC the bitmap. This step, done during initial program startup
  607.  * really speeds up the display of the bitmaps. The CreateCompatibleDC
  608.  * and the SelectObject into the DC is done once, not like would be needed
  609.  * if this was not done.
  610.  *
  611.  ************************************************************************/
  612. void LoadBMP(HANDLE InInstance)
  613. {
  614.  int Type;                                   /* type of object              */
  615.  int Frame;                                  /* animation frame             */
  616.  
  617. /*************************************************************************
  618.  * Load in the first group of object bitmaps and then set relevant data.
  619.  ************************************************************************/
  620.  
  621.   hObjBMP[0][0]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallR1));
  622.   hObjBMP[0][1]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallR2));
  623.   hObjBMP[0][2]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallR3));
  624.   hObjBMP[0][3]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallR4));
  625.   hObjBMP[0][4]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallR5));
  626.   hObjBMP[0][5]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallR6));
  627.   Pix[0].X=23;                              /* Bitmap X                     */
  628.   Pix[0].Y=23;                              /* Bitmap Y                     */
  629.   Pix[0].Frame=6;                           /* # of animate frames          */
  630.   Pix[0].Speed=2;                           /* wait time to animate         */
  631.   Pix[0].MDX=4;                             /* Max Delta X                  */
  632.   Pix[0].MDY=4;                             /* Max Delta Y                  */
  633.  
  634. /*************************************************************************
  635.  * Load in the second group of object bitmaps and then set relevant data.
  636.  ************************************************************************/
  637.  
  638.   hObjBMP[1][0]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallB1));
  639.   hObjBMP[1][1]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallB2));
  640.   hObjBMP[1][2]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallB3));
  641.   hObjBMP[1][3]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallB4));
  642.   Pix[1].X=15;                              /* Bitmap X                     */
  643.   Pix[1].Y=15;                              /* Bitmap Y                     */
  644.   Pix[1].Frame=4;                           /* # of animate frames          */
  645.   Pix[1].Speed=3;                           /* wait time to animate         */
  646.   Pix[1].MDX=3;                             /* Max Delta X                  */
  647.   Pix[1].MDY=3;                             /* Max Delta Y                  */
  648.  
  649. /*************************************************************************
  650.  * Load in the third group of object bitmaps and then set relevant data.
  651.  ************************************************************************/
  652.  
  653.   hObjBMP[2][0]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallY1));
  654.   hObjBMP[2][1]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallY2));
  655.   hObjBMP[2][2]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallY3));
  656.   hObjBMP[2][3]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallY4));
  657.   hObjBMP[2][4]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallY5));
  658.   hObjBMP[2][5]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallY6));
  659.   Pix[2].X=15;                              /* Bitmap X                     */
  660.   Pix[2].Y=15;                              /* Bitmap Y                     */
  661.   Pix[2].Frame=6;                           /* # of animate frames          */
  662.   Pix[2].Speed=5;                           /* wait time to animate         */
  663.   Pix[2].MDX=3;                             /* Max Delta X                  */
  664.   Pix[2].MDY=3;                             /* Max Delta Y                  */
  665.  
  666. /*************************************************************************
  667.  * Load in the fourth group of object bitmaps and then set relevant data.
  668.  ************************************************************************/
  669.  
  670.   hObjBMP[3][0]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallG1));
  671.   hObjBMP[3][1]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallG2));
  672.   hObjBMP[3][2]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallG3));
  673.   hObjBMP[3][3]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallG4));
  674.   hObjBMP[3][4]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallG5));
  675.   hObjBMP[3][5]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallG6));
  676.   Pix[3].X=27;                              /* Bitmap X                     */
  677.   Pix[3].Y=13;                              /* Bitmap Y                     */
  678.   Pix[3].Frame=6;                           /* # of animate frames          */
  679.   Pix[3].Speed=5;                           /* wait time to animate         */
  680.   Pix[3].MDX=4;                             /* Max Delta X                  */
  681.   Pix[3].MDY=2;                             /* Max Delta Y                  */
  682.  
  683. /*************************************************************************
  684.  * Load in fifth group of object bitmaps and then set relevant data.
  685.  ************************************************************************/
  686.  
  687.   hObjBMP[4][0]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallL1));
  688.   hObjBMP[4][1]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallL2));
  689.   hObjBMP[4][2]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallL3));
  690.   hObjBMP[4][3]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallL4));
  691.   Pix[4].X=16;                              /* Bitmap X                     */
  692.   Pix[4].Y=8;                               /* Bitmap Y                     */
  693.   Pix[4].Frame=4;                           /* # of animate frames          */
  694.   Pix[4].Speed=4;                           /* wait time to animate         */
  695.   Pix[4].MDX=3;                             /* Max Delta X                  */
  696.   Pix[4].MDY=3;                             /* Max Delta Y                  */
  697.  
  698. /*************************************************************************
  699.  * Load in the sixth group of object bitmaps and then set relevant data.
  700.  ************************************************************************/
  701.  
  702.   hObjBMP[5][0]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallP1));
  703.   hObjBMP[5][1]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallP2));
  704.   hObjBMP[5][2]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallP3));
  705.   hObjBMP[5][3]=LoadBitmap (InInstance,MAKEINTRESOURCE(BallP4));
  706.   Pix[5].X=8;                               /* Bitmap X                     */
  707.   Pix[5].Y=16;                              /* Bitmap Y                     */
  708.   Pix[5].Frame=4;                           /* # of animate frames          */
  709.   Pix[5].Speed=4;                           /* wait time to animate         */
  710.   Pix[5].MDX=2;                             /* Max Delta X                  */
  711.   Pix[5].MDY=3;                             /* Max Delta Y                  */
  712.  
  713. /*************************************************************************
  714.  * Now we loop thru all object groups and for each frame of the animation
  715.  * we create a Device Context (DC) and into that DC we select the current
  716.  * animation and save it for faster access into the PixDC array.
  717.  ************************************************************************/
  718.  
  719. for (Type=0;Type<MAX_OBJ_TYPE;Type++)           /* do for all groups    */
  720.  {
  721.  for (Frame=0;Frame<Pix[Type].Frame;Frame++)    /* for all valid frames */
  722.   {
  723.    PixDC[Type][Frame]=CreateCompatibleDC(hToDC);
  724.    SelectObject(PixDC[Type][Frame],hObjBMP[Type][Frame]);
  725.   }
  726.  MaxBmpX=((Pix[Type].X>MaxBmpX)?Pix[Type].X:MaxBmpX);
  727.  MaxBmpY=((Pix[Type].Y>MaxBmpY)?Pix[Type].Y:MaxBmpY);
  728.  RollObj[Type].ObjWX=Pix[Type].X;
  729.  RollObj[Type].ObjWY=Pix[Type].Y;
  730.  RollObj[Type].ObjType=Type;
  731.  RollObj[Type].ObjFrame=1;
  732.  RollObj[Type].SpinCnt=1;
  733.  RollObj[Type].SpinWait=Pix[Type].Speed;
  734.  }
  735. }                                               /* end LoadBMP          */
  736.  
  737. /*************************************************************************
  738.  *
  739.  * This routine does the special processing needed to display the ABOUT
  740.  * Toy Box animated about box. The box displays a centered multi-line
  741.  * about box with the six defined 'Toys' located three across the top
  742.  * and three across the bottom, centered (relative to the largest one)
  743.  * and animated.
  744.  *
  745.  *      WM_CREATE               Create a timer for the animation, and get a DC
  746.  *      WM_MOVE                 Just force a re-draw
  747.  *      WM_SIZE                 Compute positions of animation and force re-draw
  748.  *      WM_PAINT                Erase the screen and draw the text onto the window
  749.  *      WM_TIMER                Update the animation of the balls
  750.  *      WM_QUIT         Delete the timer and reset hAbout to null
  751.  *
  752.  ************************************************************************/
  753. LRESULT CALLBACK AboutProc(HWND hChild,UINT messg,WPARAM wParam,LPARAM lParam)
  754. {
  755.  static HDC TheDC;
  756.  PAINTSTRUCT ps;
  757.  static int ChildTimer;
  758.  static int ChildX,ChildY;
  759.  
  760.  switch (messg) {
  761.  
  762.   case WM_CREATE:
  763.    {
  764.     ChildTimer=SetTimer(hChild,2,50,NULL);
  765.     TheDC=GetDC(hChild);
  766.    }                                        /* WM_CREATE                    */
  767.   break;
  768.  
  769.   case WM_MOVE:
  770.    {
  771.         InvalidateRect(hChild,NULL,TRUE);
  772.    }
  773.   break;
  774.  
  775.   case WM_SIZE:
  776.    {
  777.     int TempSpace;
  778.         ChildX=LOWORD(lParam);             /* save screen X                */
  779.         ChildY=HIWORD(lParam);             /* save screen Y                */
  780.         TempSpace=(ChildX-(MAX_OBJ_TYPE/2)*MaxBmpX)/(MAX_OBJ_TYPE/2);
  781.          RollObj[0].ObjX=6+((MaxBmpX-RollObj[0].ObjWX)/2);
  782.          RollObj[0].ObjY=6+((MaxBmpY-RollObj[0].ObjWY)/2);
  783.  
  784.          RollObj[1].ObjX=(ChildX-MaxBmpX)/2+((MaxBmpX-RollObj[1].ObjWX)/2);
  785.          RollObj[1].ObjY=6+((MaxBmpY-RollObj[1].ObjWY)/2);
  786.  
  787.          RollObj[2].ObjX=ChildX-MaxBmpX-6+((MaxBmpX-RollObj[2].ObjWX)/2);
  788.          RollObj[2].ObjY=6+((MaxBmpY-RollObj[2].ObjWY)/2);
  789.  
  790.          RollObj[3].ObjX=6+((MaxBmpX-RollObj[3].ObjWX)/2);
  791.          RollObj[3].ObjY=ChildY-MaxBmpY-6+((MaxBmpY-RollObj[3].ObjWY)/2);
  792.  
  793.          RollObj[4].ObjX=(ChildX-MaxBmpX)/2+((MaxBmpX-RollObj[4].ObjWX)/2);
  794.          RollObj[4].ObjY=ChildY-MaxBmpY-6+((MaxBmpY-RollObj[4].ObjWY)/2);
  795.  
  796.          RollObj[5].ObjX=ChildX-MaxBmpX-6+((MaxBmpX-RollObj[5].ObjWX)/2);
  797.          RollObj[5].ObjY=ChildY-MaxBmpY-6+((MaxBmpY-RollObj[5].ObjWY)/2);
  798.  
  799.         InvalidateRect(hChild,NULL,TRUE);
  800.    }
  801.   break;                                    /* WM_SIZE                      */
  802.  
  803.   case WM_PAINT:
  804.    {
  805.     BeginPaint(hChild,&ps);
  806.     SetTextColor(TheDC,RGB(255,0,255));
  807.         SetBkColor(TheDC,RGB(0,0,0));
  808.         PatBlt(TheDC,0,0,ChildX,ChildY,BLACKNESS);
  809.         DrawText(TheDC,AboutText,-1,&ChildDrawRect,DT_CENTER);
  810.         EndPaint(hChild,&ps);
  811.    }
  812.   break;                                    /* WM_PAINT                     */
  813.  
  814.   case WM_TIMER:
  815.    {
  816.     AnimateObjects(TheDC);
  817.    }
  818.   break;                                    /* WM_TIMER                     */
  819.  
  820.   case WM_DESTROY:
  821.    {
  822.     if (ChildTimer!=0)
  823.      KillTimer(hChild,ChildTimer);
  824.         ReleaseDC(hChild,TheDC);
  825.         hAbout=NULL;                        /* allow to make again          */
  826.    }
  827.   break;                                    /* WM_DESTROY                   */
  828.  
  829.   default:
  830.   return(DefWindowProc(hChild,messg,wParam,lParam));
  831.   }                                         /* end Switch                   */
  832.  return(0L);
  833. }                                           /* end WndProc                  */
  834.  
  835. /*************************************************************************
  836.  *
  837.  * This routine takes each object that is displayed in the about
  838.  * box and animates it. For each object, it PatBlts the object to
  839.  * black, then updates the object frame and BitBlts the object back
  840.  * on the screen.
  841.  *
  842.  ************************************************************************/
  843. void AnimateObjects(HDC hToDC)
  844. {
  845.  int TempCtr;
  846.  int Tx,Ty;
  847.  int TFrame;
  848.  int TType;
  849.  int tWX,tWY;
  850.  
  851.  for (TempCtr=0;TempCtr<MAX_OBJ_TYPE;TempCtr++)
  852.   {
  853.    Tx=RollObj[TempCtr].ObjX;
  854.    Ty=RollObj[TempCtr].ObjY;
  855.    tWX=RollObj[TempCtr].ObjWX;
  856.    tWY=RollObj[TempCtr].ObjWY;
  857.    TFrame=RollObj[TempCtr].ObjFrame;
  858.    TType=RollObj[TempCtr].ObjType;
  859.    PatBlt(hToDC,Tx,Ty,tWX,tWY,BLACKNESS);
  860.    RollObj[TempCtr].SpinCnt++;              /* do frame animation   */
  861.          if (RollObj[TempCtr].SpinCnt>RollObj[TempCtr].SpinWait)
  862.          {
  863.           RollObj[TempCtr].SpinCnt=1;
  864.           TFrame++;
  865.           if (TFrame>=Pix[TType].Frame)
  866.           {
  867.            TFrame=0;
  868.           }
  869.           RollObj[TempCtr].ObjFrame=TFrame;
  870.          }
  871.            BitBlt(hToDC,Tx,Ty,tWX,tWY,PixDC[TType][TFrame],0,0,SRCCOPY);
  872.    }                                        /* end TempCtr                  */
  873. }                                           /* end AnimateObjects           */
  874.