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