home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / windows / crane.zip / CRANE.C < prev    next >
C/C++ Source or Header  |  1990-03-30  |  53KB  |  2,083 lines

  1. /******************************************************************************
  2.  
  3.    Module Name: crane
  4.    Description: 3D Origami Crane Animator
  5.    Version:     v1.00
  6.    Authors:     Mike Robert
  7.    Date:        3/30/90
  8.  
  9.    For Jennifer Lee.
  10.  
  11.    Revision History:
  12.  
  13.    Bugs:
  14.  
  15.    Enhancements:
  16.  
  17. ******************************************************************************/
  18.  
  19. /* INCLUDE FILES
  20. */
  21.  
  22. #define  NOCOMM
  23.  
  24. #include <Windows.h>
  25. #include <math.h>
  26. #include <process.h>
  27. #include "WinUnDoc.h"
  28. #include "crane.h"
  29. #include "dialogs.h"
  30.  
  31. /* SYMBOLIC CONSTANTS
  32. */
  33.  
  34. /*  Miscellaneous.  */
  35.  
  36. #define  PI                   3.14159265     /* The value of π */
  37.  
  38. #define  CNT_ANIMATE          4              /* Animate count */
  39.  
  40. #define  MAX_MOVE             100.           /* Maximum movement */
  41.  
  42. #define  MAX_POINTS            56            /* Maximum points */
  43.  
  44. #define  MAX_SHAPES            11            /* Maximum shapes */
  45.  
  46. /*  Crane Point Flags.  */
  47.  
  48. #define  CPF_NORMAL           0x0000         /* Normal point */
  49. #define  CPF_START            0x0001         /* New line sequence start */
  50. #define  CPF_MOVE             0x0002         /* Movement point */
  51. #define  CPF_EOL              0x8000         /* End of point list */
  52.  
  53. /*  ROTation.  */
  54.  
  55. #define  ROT_INC              ( PI / 18. )   /* Rotation degree increment */
  56. #define  ROT_MIN              ( 0. )         /* Rotation minimum */
  57. #define  ROT_MAX              ( PI * 2. )    /* Rotation maximum */
  58.  
  59. /*  Z-SiZing.  */
  60.  
  61. #define  ZSZ_ATMINSIZ         -5000.
  62. #define  ZSZ_ATMAXSIZ         5000.
  63.  
  64. #define  ZSZ_WINORG           -1500
  65. #define  ZSZ_WINEXT           3000
  66.  
  67. /* MACROS
  68. */
  69.  
  70. #define  WITHIN(a,b,c)        ( (a) >= (b) && (a) <= (c) )
  71.  
  72. /* TYPEDEFS
  73. */
  74.  
  75. typedef struct _POINT3D
  76. {
  77.    double         x, y, z;                   /* XYZ coordinates (floating) */
  78. }
  79.    POINT3D;                                  /* 3-dimensional point */
  80.  
  81. typedef POINT3D FAR *LPPOINT3D;
  82.  
  83. typedef struct _ANIMATEPT
  84. {
  85.    WORD           unPtIndex;                 /* Point index */
  86.    double         dfMinRot,                  /* Minimum rotation */
  87.                   dfMaxRot,                  /* Maximum rotation */
  88.                   dfCurRot,                  /* Current rotation */
  89.                   dfIncRot,                  /* Rotation increment */
  90.                   dfDst;                     /* Distance */
  91. }
  92.    ANIMATEPT;                                /* Animate point structure */
  93.  
  94. typedef ANIMATEPT FAR *LPANIMATEPT;
  95.  
  96. typedef struct _SHAPE
  97. {
  98.    WORD           unIndex,                   /* Index */
  99.                   unCnt;                     /* Point count */
  100. }
  101.    SHAPE;                                    /* Shape structure */
  102.  
  103. typedef SHAPE FAR *LPSHAPE;
  104.  
  105. typedef struct _CRANEPT
  106. {
  107.    WORD           unFlags;                   /* Flags */
  108.    POINT3D        pt3dOrg,                   /* Original point */
  109.                   pt3dNew;                   /* New point */
  110. }
  111.    CRANEPT;                                  /* Crane point structure */
  112.  
  113. typedef CRANEPT FAR *LPCRANEPT;
  114.  
  115. /* GLOBAL VARIABLES
  116. */
  117.  
  118. static   HANDLE         hModule;             /* Module instance handle */
  119.  
  120. static   HWND           hClientWnd;          /* Client window handle */
  121. static   HDC            hClientDC;           /* Client display context handle */
  122.  
  123. static   FARPROC        lpfnXYZDataDlgProc;  /* XYZ data dialog function pointer */
  124. static   HWND           hXYZDataDlg = NULL;  /* Data dialog window handle */
  125.  
  126. static   BOOL           bAnimate = FALSE;    /* Animation flag */
  127.  
  128. static   BOOL           bRecording = FALSE;  /* Recording flag */
  129. static   WORD           unRecordCnt = 0;     /* Record count */
  130. static   int            fhRecordFile;        /* Record file handle */
  131.  
  132. static   RECT           rErase,              /* Erase rectangle */
  133.                         rOldErase,           /* Old erase rectangle */
  134.                         rUpdate;             /* Update rectangle */
  135.  
  136. static   POINT          aptList[ MAX_POINTS ];
  137.                                              /* Point list */
  138.  
  139. static   POINT3D        pt3dRot;             /* Rotation amounts */
  140.  
  141. static   POINT3D        pt3dLoc;             /* Current location */
  142.  
  143. static   CRANEPT        cptMove =            /* Movement crane point */
  144.                         {
  145.                            CPF_MOVE,
  146.                            { 0., 0., MAX_MOVE },
  147.                            { 0., 0., 0. }
  148.                         };
  149.  
  150. static   ANIMATEPT      aaptList[ CNT_ANIMATE ] =
  151.                                              /* Animate point list */
  152.                         {
  153.                            {
  154.                               33,
  155.                               PI * 3. / 4. + PI / 40.,
  156.                               PI * 5. / 4. - PI / 40.,
  157.                               PI,
  158.                               -PI / 20.,
  159.                               1050.
  160.                            },
  161.                            {
  162.                               37,
  163.                               PI * 3. / 4. + PI / 40.,
  164.                               PI * 5. / 4. - PI / 40.,
  165.                               PI,
  166.                               -PI / 20.,
  167.                               1050.
  168.                            },
  169.                            {
  170.                               41,
  171.                               -PI / 4. + PI / 40.,
  172.                               PI / 4. - PI / 40.,
  173.                               0.,
  174.                               PI / 20.,
  175.                               1050.
  176.                            },
  177.                            {
  178.                               45,
  179.                               -PI / 4. + PI / 40.,
  180.                               PI / 4. - PI / 40.,
  181.                               0.,
  182.                               PI / 20.,
  183.                               1050.
  184.                            }
  185.                         };
  186.  
  187. static   POINT3D        pt3dMin =            /* Coordinate minimums */
  188.                         { -1050., -405., -810. },
  189.                         pt3dMax =            /* Coordinate maximums */
  190.                         { 1050., 405., 810. };
  191.  
  192. static   SHAPE          ashpList[ ] =        /* Shape list */
  193.                         {
  194.                            { 0, 4 },
  195.                            { 4, 7 },
  196.                            { 11, 5 },
  197.                            { 16, 5 },
  198.                            { 21, 5 },
  199.                            { 26, 5 },
  200.                            { 31, 4 },
  201.                            { 35, 4 },
  202.                            { 39, 4 },
  203.                            { 43, 4 },
  204.                            { 47, 9 }
  205.                         };
  206.  
  207. static   CRANEPT        acptList[ ] =        /* Crane points */
  208.                         {
  209.                            {                 /* 0 */
  210.                               CPF_START,
  211.                               { 0., -405., -810. },
  212.                               { 0., 0., 0. }
  213.                            },
  214.                            {                 /* 1 */
  215.                               CPF_NORMAL,
  216.                               { 0., 405., -180. },
  217.                               { 0., 0., 0. }
  218.                            },
  219.                            {                 /* 2 */
  220.                               CPF_NORMAL,
  221.                               { 0., 255., 60. },
  222.                               { 0., 0., 0. }
  223.                            },
  224.                            {                 /* 3 */
  225.                               CPF_NORMAL,
  226.                               { 0., -405., -810. },
  227.                               { 0., 0., 0. }
  228.                            },
  229.                            {                 /* 4 */
  230.                               CPF_START,
  231.                               { 0., 255., 60. },
  232.                               { 0., 0., 0. }
  233.                            },
  234.                            {                 /* 5 */
  235.                               CPF_NORMAL,
  236.                               { 0., 405., 300. },
  237.                               { 0., 0., 0. }
  238.                            },
  239.                            {                 /* 6 */
  240.                               CPF_NORMAL,
  241.                               { 0., -135., 720. },
  242.                               { 0., 0., 0. }
  243.                            },
  244.                            {                 /* 7 */
  245.                               CPF_NORMAL,
  246.                               { 0., 135., 810. },
  247.                               { 0., 0., 0. }
  248.                            },
  249.                            {                 /* 8 */
  250.                               CPF_NORMAL,
  251.                               { 0., -195., 780. },
  252.                               { 0., 0., 0. }
  253.                            },
  254.                            {                 /* 9 */
  255.                               CPF_NORMAL,
  256.                               { 0., -225., 690. },
  257.                               { 0., 0., 0. }
  258.                            },
  259.                            {                 /* 10 */
  260.                               CPF_NORMAL,
  261.                               { 0., 255., 60. },
  262.                               { 0., 0., 0. }
  263.                            },
  264.                            {                 /* 11 */
  265.                               CPF_START,
  266.                               { 0., 255., 60. },
  267.                               { 0., 0., 0. }
  268.                            },
  269.                            {                 /* 12 */
  270.                               CPF_NORMAL,
  271.                               { 0., 405., -180. },
  272.                               { 0., 0., 0. }
  273.                            },
  274.                            {                 /* 13 */
  275.                               CPF_NORMAL,
  276.                               { -450., 75., -270. },
  277.                               { 0., 0., 0. }
  278.                            },
  279.                            {                 /* 14 */
  280.                               CPF_NORMAL,
  281.                               { -90., 195., 60. },
  282.                               { 0., 0., 0. }
  283.                            },
  284.                            {                 /* 15 */
  285.                               CPF_NORMAL,
  286.                               { 0., 255., 60. },
  287.                               { 0., 0., 0. }
  288.                            },
  289.                            {                 /* 16 */
  290.                               CPF_START,
  291.                               { 0., 255., 60. },
  292.                               { 0., 0., 0. }
  293.                            },
  294.                            {                 /* 17 */
  295.                               CPF_NORMAL,
  296.                               { 0., 405., 300. },
  297.                               { 0., 0., 0. }
  298.                            },
  299.                            {                 /* 18 */
  300.                               CPF_NORMAL,
  301.                               { -450., 75., 390. },
  302.                               { 0., 0., 0. }
  303.                            },
  304.                            {                 /* 19 */
  305.                               CPF_NORMAL,
  306.                               { -90., 195., 60. },
  307.                               { 0., 0., 0. }
  308.                            },
  309.                            {                 /* 20 */
  310.                               CPF_NORMAL,
  311.                               { 0., 255., 60. },
  312.                               { 0., 0., 0. }
  313.                            },
  314.                            {                 /* 21 */
  315.                               CPF_START,
  316.                               { 450., 75., -270. },
  317.                               { 0., 0., 0. }
  318.                            },
  319.                            {                 /* 22 */
  320.                               CPF_NORMAL,
  321.                               { 90., 195., 60. },
  322.                               { 0., 0., 0. }
  323.                            },
  324.                            {                 /* 23 */
  325.                               CPF_NORMAL,
  326.                               { 0., 255., 60. },
  327.                               { 0., 0., 0. }
  328.                            },
  329.                            {                 /* 24 */
  330.                               CPF_NORMAL,
  331.                               { 0., 405., -180. },
  332.                               { 0., 0., 0. }
  333.                            },
  334.                            {                 /* 25 */
  335.                               CPF_NORMAL,
  336.                               { 450., 75., -270. },
  337.                               { 0., 0., 0. }
  338.                            },
  339.                            {                 /* 26 */
  340.                               CPF_START,
  341.                               { 90., 195., 60. },
  342.                               { 0., 0., 0. }
  343.                            },
  344.                            {                 /* 27 */
  345.                               CPF_NORMAL,
  346.                               { 450., 75., 390. },
  347.                               { 0., 0., 0. }
  348.                            },
  349.                            {                 /* 28 */
  350.                               CPF_NORMAL,
  351.                               { 0., 405., 300. },
  352.                               { 0., 0., 0. }
  353.                            },
  354.                            {                 /* 29 */
  355.                               CPF_NORMAL,
  356.                               { 0., 255., 60. },
  357.                               { 0., 0., 0. }
  358.                            },
  359.                            {                 /* 30 */
  360.                               CPF_NORMAL,
  361.                               { 90., 195., 60. },
  362.                               { 0., 0., 0. }
  363.                            },
  364.                            {                 /* 31 */
  365.                               CPF_START,
  366.                               { -90., 195., 60. },
  367.                               { 0., 0., 0. }
  368.                            },
  369.                            {                 /* 32 */
  370.                               CPF_NORMAL,
  371.                               { -450., 75., -270. },
  372.                               { 0., 0., 0. }
  373.                            },
  374.                            {                 /* 33 */
  375.                               CPF_NORMAL,
  376.                               { -1050., 0., 60. },
  377.                               { 0., 0., 0. }
  378.                            },
  379.                            {                 /* 34 */
  380.                               CPF_NORMAL,
  381.                               { -90., 195., 60. },
  382.                               { 0., 0., 0. }
  383.                            },
  384.                            {                 /* 35 */
  385.                               CPF_START,
  386.                               { -90., 195., 60. },
  387.                               { 0., 0., 0. }
  388.                            },
  389.                            {                 /* 36 */
  390.                               CPF_NORMAL,
  391.                               { -450., 75., 390. },
  392.                               { 0., 0., 0. }
  393.                            },
  394.                            {                 /* 37 */
  395.                               CPF_NORMAL,
  396.                               { -1050., 0., 60. },
  397.                               { 0., 0., 0. }
  398.                            },
  399.                            {                 /* 38 */
  400.                               CPF_NORMAL,
  401.                               { -90., 195., 60. },
  402.                               { 0., 0., 0. }
  403.                            },
  404.                            {                 /* 39 */
  405.                               CPF_START,
  406.                               { 90., 195., 60. },
  407.                               { 0., 0., 0. }
  408.                            },
  409.                            {                 /* 40 */
  410.                               CPF_NORMAL,
  411.                               { 450., 75., -270. },
  412.                               { 0., 0., 0. }
  413.                            },
  414.                            {                 /* 41 */
  415.                               CPF_NORMAL,
  416.                               { 1050., 0., 60. },
  417.                               { 0., 0., 0. }
  418.                            },
  419.                            {                 /* 42 */
  420.                               CPF_NORMAL,
  421.                               { 90., 195., 60. },
  422.                               { 0., 0., 0. }
  423.                            },
  424.                            {                 /* 43 */
  425.                               CPF_START,
  426.                               { 90., 195., 60. },
  427.                               { 0., 0., 0. }
  428.                            },
  429.                            {                 /* 44 */
  430.                               CPF_NORMAL,
  431.                               { 450., 75., 390. },
  432.                               { 0., 0., 0. }
  433.                            },
  434.                            {                 /* 45 */
  435.                               CPF_NORMAL,
  436.                               { 1050., 0., 60. },
  437.                               { 0., 0., 0. }
  438.                            },
  439.                            {                 /* 46 */
  440.                               CPF_NORMAL,
  441.                               { 90., 195., 60. },
  442.                               { 0., 0., 0. }
  443.                            },
  444.                            {                 /* 47 */
  445.                               CPF_START,
  446.                               { -270., 135., 390. },
  447.                               { 0., 0., 0. }
  448.                            },
  449.                            {                 /* 48 */
  450.                               CPF_NORMAL,
  451.                               { 0., -15., 330. },
  452.                               { 0., 0., 0. }
  453.                            },
  454.                            {                 /* 49 */
  455.                               CPF_NORMAL,
  456.                               { 270., 135., 390. },
  457.                               { 0., 0., 0. }
  458.                            },
  459.                            {                 /* 50 */
  460.                               CPF_NORMAL,
  461.                               { 270., 45., 60. },
  462.                               { 0., 0., 0. }
  463.                            },
  464.                            {                 /* 51 */
  465.                               CPF_NORMAL,
  466.                               { 270., 135., -270. },
  467.                               { 0., 0., 0. }
  468.                            },
  469.                            {                 /* 52 */
  470.                               CPF_NORMAL,
  471.                               { 0., -45., -210. },
  472.                               { 0., 0., 0. }
  473.                            },
  474.                            {                 /* 53 */
  475.                               CPF_NORMAL,
  476.                               { -270., 135., -270. },
  477.                               { 0., 0., 0. }
  478.                            },
  479.                            {                 /* 54 */
  480.                               CPF_NORMAL,
  481.                               { -270., 45., 60. },
  482.                               { 0., 0., 0. }
  483.                            },
  484.                            {                 /* 55 */
  485.                               CPF_NORMAL,
  486.                               { -270., 135., 390. },
  487.                               { 0., 0., 0. }
  488.                            },
  489.                            {                 /* 56 */
  490.                               CPF_EOL,
  491.                               { 0., 0., 0. },
  492.                               { 0., 0., 0. }
  493.                            }
  494.                         };
  495.  
  496. #define  MAX_POINTS            56            /* Maximum points */
  497.  
  498. #define  MAX_SHAPES            11            /* Maximum shapes */
  499.  
  500. /* FUNCTION PROTOYPES
  501. */
  502.  
  503. void PASCAL WinMain(
  504.  
  505.    HANDLE hInstance,    /* Instance handle.
  506.                         */
  507.       
  508.    HANDLE hPrevInstance,
  509.                         /* Previous instance handle.
  510.                         */
  511.       
  512.    LPSTR lpszCmdLine,   /* Command line string pointer.
  513.                         */
  514.       
  515.    int nCmdShow         /* Show command parameter.
  516.                         */
  517.       
  518.    );
  519.  
  520. long FAR PASCAL WindowProc( 
  521.  
  522.    HWND hWnd,           /* Window handle.
  523.                         */
  524.  
  525.    unsigned nMsg,       /* Message type.
  526.                         */
  527.  
  528.    WORD wParam,         /* 16-bit parameter.
  529.                         */
  530.  
  531.    LONG lParam          /* 32-bit parameter.
  532.                         */
  533.  
  534.    );
  535.  
  536. BOOL NEAR PASCAL Init( 
  537.  
  538.    HANDLE hInstance,    /* Instance handle.
  539.                         */
  540.       
  541.    HANDLE hPrevInstance,
  542.                         /* Previous instance handle.
  543.                         */
  544.       
  545.    LPSTR lpszCmdLine,   /* Command line string pointer.
  546.                         */
  547.       
  548.    int nCmdShow         /* Show command parameter.
  549.                         */
  550.       
  551.    );
  552.  
  553. void NEAR PASCAL Menu( 
  554.  
  555.    HWND hWnd,           /* Window handle.
  556.                         */
  557.  
  558.    WORD wID             /* Command ID.
  559.                         */
  560.  
  561.    );
  562.  
  563. void NEAR PASCAL InitMenu(
  564.  
  565.    HWND hWnd,           /* Window handle.
  566.                         */
  567.  
  568.    HMENU hMenu          /* Menu handle.
  569.                         */
  570.  
  571.    );
  572.  
  573. BOOL FAR PASCAL XYZDataDlgProc( 
  574.  
  575.    HWND hDlg,           /* Dialog window handle.
  576.                         */
  577.  
  578.    unsigned nMsg,       /* Message to dialog.
  579.                         */
  580.  
  581.    WORD wParam,         /* Word parameter.
  582.                         */
  583.  
  584.    LONG lParam          /* Long parameter.
  585.                         */
  586.  
  587.    );
  588.  
  589. void NEAR PASCAL UpdateXYZDataDlg( void );
  590.  
  591. BOOL FAR PASCAL AboutDlgProc( 
  592.  
  593.    HWND hDlg,           /* Dialog window handle.
  594.                         */
  595.  
  596.    unsigned nMsg,       /* Message type.
  597.                         */
  598.  
  599.    WORD wParam,         /* 16-bit parameter.
  600.                         */
  601.  
  602.    LONG lParam          /* 32-bit parameter.
  603.                         */
  604.  
  605.    );
  606.  
  607. void NEAR PASCAL AnimateCranePts(
  608.  
  609.    HWND hWnd            /* Window handle.
  610.                         */
  611.  
  612.    );
  613.  
  614. void NEAR PASCAL RecordPlayback( 
  615.  
  616.    HWND hWnd            /* Window handle.
  617.                         */
  618.  
  619.    );
  620.       
  621. void NEAR PASCAL RecordRead( void );
  622.  
  623. void NEAR PASCAL RecordWrite( void );
  624.  
  625. void NEAR PASCAL Key( 
  626.  
  627.    HWND hWnd,           /* Window handle.
  628.                         */
  629.  
  630.    WORD wId             /* Key ID.
  631.                         */
  632.  
  633.    );
  634.       
  635. void NEAR PASCAL CalcNewCranePts( void );
  636.  
  637. void NEAR PASCAL CalcNewPt(
  638.  
  639.    LPCRANEPT lpcpt      /* Crane point pointer.
  640.                         */
  641.  
  642.    );
  643.  
  644. void NEAR PASCAL Size(
  645.  
  646.    HWND hWnd,           /* Window handle.
  647.                         */
  648.  
  649.    LONG lParam          /* 32-bit parameter.
  650.                         */
  651.  
  652.    );
  653.  
  654. void NEAR PASCAL Paint( 
  655.  
  656.    HWND hWnd            /* Window handle.
  657.                         */
  658.  
  659.    );
  660.  
  661. void NEAR PASCAL ResetCranePts( void );
  662.  
  663. void NEAR PASCAL myYield( void );
  664.  
  665. /******************************************************************************
  666.  
  667.    Function Name: WinMain
  668.  
  669.    Description:
  670.  
  671.       Top level procedure called by windows on application startup.
  672.  
  673.    Control Flow:
  674.  
  675.    Return Values:
  676.  
  677.       None.
  678.  
  679.    Notes:
  680.  
  681. ******************************************************************************/
  682.  
  683. void PASCAL WinMain(
  684.  
  685.    HANDLE hInstance,    /* Instance handle.
  686.                         */
  687.       
  688.    HANDLE hPrevInstance,
  689.                         /* Previous instance handle.
  690.                         */
  691.       
  692.    LPSTR lpszCmdLine,   /* Command line string pointer.
  693.                         */
  694.       
  695.    int nCmdShow         /* Show command parameter.
  696.                         */
  697.       
  698.    )
  699.  
  700. {
  701.    /*  Variable definition.  */
  702.  
  703.    MSG            stMsg;                     /* Message structure */
  704.  
  705.    /*  Initialize ourselves.  */
  706.  
  707.    if ( !Init( hInstance, hPrevInstance, lpszCmdLine, nCmdShow ) )
  708.       exit( 1 );
  709.  
  710.    /*  Process messages until exit.  */
  711.  
  712.    while ( GetMessage( &stMsg, NULL, 0, 0 ) )
  713.    {
  714.       /*  Translate and dispatch the message.  */
  715.  
  716.       TranslateMessage( &stMsg );
  717.       DispatchMessage( &stMsg );
  718.  
  719.    }
  720.  
  721.    exit( stMsg.wParam );
  722.  
  723. }
  724.  
  725. /******************************************************************************
  726.  
  727.    Function Name: Init
  728.  
  729.    Description:
  730.  
  731.       Provides initialization for the first instance and every following
  732.       instance.
  733.  
  734.    Control Flow:
  735.  
  736.    Return Values:
  737.  
  738.       Failure: FALSE
  739.       Success: TRUE
  740.  
  741.    Notes:
  742.  
  743. ******************************************************************************/
  744.  
  745. BOOL NEAR PASCAL Init( 
  746.  
  747.    HANDLE hInstance,    /* Instance handle.
  748.                         */
  749.       
  750.    HANDLE hPrevInstance,
  751.                         /* Previous instance handle.
  752.                         */
  753.       
  754.    LPSTR lpszCmdLine,   /* Command line string pointer.
  755.                         */
  756.       
  757.    int nCmdShow         /* Show command parameter.
  758.                         */
  759.       
  760.    )
  761.       
  762. {
  763.    /*  Variable definition.  */
  764.  
  765.    WNDCLASS       wcClass;                   /* Class information storage */
  766.  
  767.    OFSTRUCT       ofRecord;                  /* Record open file structure */
  768.  
  769.    /*  Perform the appropiate initialization.  */
  770.  
  771.    if ( !hPrevInstance )
  772.    {
  773.       wcClass.lpszClassName    = "Crane";
  774.       wcClass.hInstance        = hInstance;
  775.       wcClass.lpfnWndProc      = WindowProc;
  776.       wcClass.hCursor          = LoadCursor( NULL, IDC_ARROW );
  777.       wcClass.hIcon            = LoadIcon( hInstance, "CraneIcon" );
  778.       wcClass.lpszMenuName     = "CraneMenu";
  779.       wcClass.hbrBackground    = GetStockObject( WHITE_BRUSH );
  780.       wcClass.style            = CS_OWNDC;
  781.       wcClass.cbClsExtra       = 0;
  782.       wcClass.cbWndExtra       = 0;
  783.  
  784.       RegisterClass( &wcClass );
  785.  
  786.    }
  787.  
  788.    /*  Store this instance so window procedures can use it.  */
  789.  
  790.    hModule = hInstance;
  791.  
  792.    /*  Create the window.  */
  793.  
  794.    hClientWnd = CreateWindow( "Crane",
  795.                               " Crane ",
  796.                               WS_OVERLAPPEDWINDOW,
  797.                               CW_USEDEFAULT,
  798.                               SW_SHOWNORMAL,
  799.                               CW_USEDEFAULT,
  800.                               0,
  801.                               NULL,
  802.                               NULL,
  803.                               hInstance,
  804.                               NULL
  805.                             );
  806.  
  807.    /*  Get our display context and initialize it.  */
  808.  
  809.    hClientDC = GetDC( hClientWnd );
  810.  
  811.    SetMapMode( hClientDC, MM_ANISOTROPIC );
  812.    SetWindowOrg( hClientDC, ZSZ_WINORG, ZSZ_WINORG );
  813.    SetWindowExt( hClientDC, ZSZ_WINEXT, ZSZ_WINEXT );
  814.  
  815.    SelectObject( hClientDC, GetStockObject( BLACK_PEN ) );
  816.  
  817.    /*  Initialize the crane data.  */
  818.  
  819.    ResetCranePts( );
  820.  
  821.    /*  Create the dialog procedure pointer.  */
  822.  
  823.    lpfnXYZDataDlgProc = MakeProcInstance( XYZDataDlgProc, hModule );
  824.  
  825.    /*  Open the record file.  */
  826.  
  827.    fhRecordFile = OpenFile( "RECORD.DAT", &ofRecord, OF_CREATE | OF_READWRITE );
  828.    if ( !fhRecordFile )
  829.       MessageBox( hClientWnd,
  830.                   "Unable to open record file",
  831.                   "Error",
  832.                   MB_ICONEXCLAMATION | MB_OK
  833.                 );
  834.  
  835.    unRecordCnt = 0;
  836.  
  837.    /*  Display this window on the screen.  */
  838.  
  839.    ShowWindow( hClientWnd, nCmdShow );
  840.  
  841.    /*  Force immediate paint of the client area.  */
  842.  
  843.    UpdateWindow( hClientWnd );
  844.  
  845.    return ( TRUE );
  846.  
  847. }
  848.  
  849. /******************************************************************************
  850.  
  851.    Function Name: WindowProc
  852.  
  853.    Description:
  854.  
  855.       Processes the messages for the Crane window.
  856.  
  857.    Control Flow:
  858.  
  859.    Return Values:
  860.  
  861.       DefWindowProc specific return values if message not processed
  862.       else 0L signalling message was processed.
  863.  
  864.    Notes:
  865.  
  866. ******************************************************************************/
  867.  
  868. long FAR PASCAL WindowProc( 
  869.  
  870.    HWND hWnd,           /* Window handle.
  871.                         */
  872.  
  873.    unsigned nMsg,       /* Message type.
  874.                         */
  875.  
  876.    WORD wParam,         /* 16-bit parameter.
  877.                         */
  878.  
  879.    LONG lParam          /* 32-bit parameter.
  880.                         */
  881.  
  882.    )
  883.  
  884. {
  885.    /*  Process the message.  */
  886.  
  887.    switch ( nMsg )
  888.    {
  889.       case WM_INITMENU:
  890.          InitMenu( hWnd, wParam );
  891.          break;
  892.  
  893.       case WM_COMMAND:
  894.          Menu( hWnd, wParam );
  895.          break;
  896.  
  897.       case WM_KEYUP:
  898.          Key( hWnd, wParam );
  899.          break;
  900.  
  901.       case WM_SIZE:
  902.          Size( hWnd, lParam );
  903.          break;
  904.  
  905.       case WM_PAINT:
  906.          Paint( hWnd );
  907.          break;
  908.  
  909.       case WM_CLOSE:
  910.  
  911.          if ( bAnimate )
  912.          {
  913.             bAnimate = FALSE;
  914.             PostMessage( hWnd, nMsg, wParam, lParam );
  915.             break;
  916.          }
  917.  
  918.          DestroyWindow( hWnd );
  919.          break;
  920.  
  921.       case WM_DESTROY:
  922.  
  923.          _lclose( fhRecordFile );
  924.  
  925.          FreeProcInstance( lpfnXYZDataDlgProc );
  926.  
  927.          ReleaseDC( hWnd, hClientDC );
  928.  
  929.          PostQuitMessage( 0 );
  930.          break;
  931.  
  932.       default:
  933.          return ( DefWindowProc( hWnd, nMsg, wParam, lParam ) );
  934.          break;
  935.  
  936.    }
  937.  
  938.    return ( 0L );
  939.  
  940. }
  941.  
  942. /******************************************************************************
  943.  
  944.    Function Name: Menu
  945.  
  946.    Description:
  947.  
  948.       Provides processing for menu commands.
  949.  
  950.    Control Flow:
  951.  
  952.    Return Values:
  953.  
  954.       None.
  955.  
  956.    Notes:
  957.  
  958. ******************************************************************************/
  959.  
  960. void NEAR PASCAL Menu( 
  961.  
  962.    HWND hWnd,           /* Window handle.
  963.                         */
  964.  
  965.    WORD wId             /* Command ID.
  966.                         */
  967.  
  968.    )
  969.       
  970. {
  971.    /*  Variable definition.  */
  972.  
  973.    FARPROC        lpfnProc;                  /* Procedure pointer */
  974.  
  975.    /*  Check for a Control command.  */
  976.  
  977.    if ( WITHIN( wId, MI_CONTROL_MIN, MI_CONTROL_MAX ) )
  978.    {
  979.       switch ( wId )
  980.       {
  981.          /*  Check for the Reset command.  */
  982.  
  983.          case MI_CONTROL_RESET:
  984.  
  985.             ResetCranePts( );
  986.  
  987.             InvalidateRect( hWnd, NULL, TRUE );
  988.  
  989.             break;
  990.  
  991.          /*  Check for the About... command.  */
  992.  
  993.          case MI_CONTROL_DATA:
  994.  
  995.             hXYZDataDlg = CreateDialog( hModule,
  996.                                         "DATABOX",
  997.                                         hWnd,
  998.                                         lpfnXYZDataDlgProc
  999.                                       );
  1000.  
  1001.             break;
  1002.  
  1003.          /*  Check for the About... command.  */
  1004.  
  1005.          case MI_CONTROL_ABOUT:
  1006.  
  1007.             lpfnProc = MakeProcInstance( AboutDlgProc, hModule );
  1008.             DialogBox( hModule, "ABOUTBOX", hWnd, lpfnProc );
  1009.             FreeProcInstance( lpfnProc );
  1010.  
  1011.             break;
  1012.  
  1013.       }
  1014.  
  1015.    }
  1016.  
  1017.    /*  Check for an Animate command.  */
  1018.  
  1019.    else if ( WITHIN( wId, MI_ANIMATE_MIN, MI_ANIMATE_MAX ) )
  1020.    {
  1021.       switch ( wId )
  1022.       {
  1023.          /*  Check for the Start command.  */
  1024.  
  1025.          case MI_ANIMATE_START:
  1026.  
  1027.             bAnimate = TRUE;
  1028.  
  1029.             rOldErase.left   = ZSZ_WINORG;
  1030.             rOldErase.top    = ZSZ_WINORG;
  1031.             rOldErase.right  = ZSZ_WINORG + ZSZ_WINEXT + 1;
  1032.             rOldErase.bottom = ZSZ_WINORG + ZSZ_WINEXT + 1;
  1033.  
  1034.             AnimateCranePts( hWnd );
  1035.  
  1036.             break;
  1037.  
  1038.          /*  Check for the Stop command.  */
  1039.  
  1040.          case MI_ANIMATE_STOP:
  1041.  
  1042.             bAnimate = FALSE;
  1043.  
  1044.             break;
  1045.  
  1046.       }
  1047.  
  1048.    }
  1049.  
  1050.    /*  Check for a Record command.  */
  1051.  
  1052.    else if ( WITHIN( wId, MI_RECORD_MIN, MI_RECORD_MAX ) )
  1053.    {
  1054.       switch ( wId )
  1055.       {
  1056.          /*  Check for the Start command.  */
  1057.  
  1058.          case MI_RECORD_START:
  1059.  
  1060.             bRecording = TRUE;
  1061.  
  1062.             break;
  1063.  
  1064.          /*  Check for the Stop command.  */
  1065.  
  1066.          case MI_RECORD_STOP:
  1067.  
  1068.             bRecording = FALSE;
  1069.  
  1070.             break;
  1071.  
  1072.          /*  Check for the Playback command.  */
  1073.  
  1074.          case MI_RECORD_PLAYBACK:
  1075.  
  1076.             RecordPlayback( hWnd );
  1077.  
  1078.             break;
  1079.  
  1080.          /*  Check for the Reset command.  */
  1081.  
  1082.          case MI_RECORD_RESET:
  1083.  
  1084.             unRecordCnt = 0;
  1085.  
  1086.             _llseek( fhRecordFile, 0L, 0 );
  1087.  
  1088.             break;
  1089.  
  1090.       }
  1091.  
  1092.    }
  1093.  
  1094.    return;
  1095.  
  1096. }
  1097.  
  1098. /******************************************************************************
  1099.  
  1100.    Function Name: InitMenu
  1101.  
  1102.    Description:
  1103.  
  1104.       Changes the status of any of the menuitems that require moment to
  1105.       moment changes.
  1106.  
  1107.    Control Flow:
  1108.  
  1109.    Return Values:
  1110.  
  1111.       None.
  1112.  
  1113.    Notes:
  1114.  
  1115. ******************************************************************************/
  1116.  
  1117. void NEAR PASCAL InitMenu(
  1118.  
  1119.    HWND hWnd,           /* Window handle.
  1120.                         */
  1121.  
  1122.    HMENU hMenu          /* Menu handle.
  1123.                         */
  1124.  
  1125.    )
  1126.  
  1127. {
  1128.    /*  Update the apropiate menu items.  */
  1129.  
  1130.    if ( !hXYZDataDlg )
  1131.       EnableMenuItem( hMenu, MI_CONTROL_DATA, MF_ENABLED );
  1132.    else
  1133.       EnableMenuItem( hMenu, MI_CONTROL_DATA, MF_DISABLED | MF_GRAYED );
  1134.  
  1135.    if ( !bAnimate )
  1136.    {
  1137.       EnableMenuItem( hMenu, MI_ANIMATE_START, MF_ENABLED );
  1138.       EnableMenuItem( hMenu, MI_ANIMATE_STOP, MF_DISABLED | MF_GRAYED );
  1139.    }
  1140.    else
  1141.    {
  1142.       EnableMenuItem( hMenu, MI_ANIMATE_START, MF_DISABLED | MF_GRAYED );
  1143.       EnableMenuItem( hMenu, MI_ANIMATE_STOP, MF_ENABLED );
  1144.    }
  1145.  
  1146.    if ( !bRecording )
  1147.       EnableMenuItem( hMenu, MI_RECORD_START, MF_ENABLED );
  1148.    else
  1149.       EnableMenuItem( hMenu, MI_RECORD_START, MF_DISABLED | MF_GRAYED );
  1150.  
  1151.    if ( bRecording )
  1152.       EnableMenuItem( hMenu, MI_RECORD_STOP, MF_ENABLED );
  1153.    else
  1154.       EnableMenuItem( hMenu, MI_RECORD_STOP, MF_DISABLED | MF_GRAYED );
  1155.  
  1156.    if ( !bRecording && !bAnimate && unRecordCnt != 0 )
  1157.       EnableMenuItem( hMenu, MI_RECORD_PLAYBACK, MF_ENABLED );
  1158.    else
  1159.       EnableMenuItem( hMenu, MI_RECORD_PLAYBACK, MF_DISABLED | MF_GRAYED );
  1160.  
  1161.    return;
  1162.  
  1163. }
  1164.  
  1165. /******************************************************************************
  1166.  
  1167.    Function Name: XYZDataDlgProc
  1168.  
  1169.    Description:
  1170.  
  1171.       This routine will process the XYZ data dialog box.
  1172.  
  1173.    Control Flow:
  1174.  
  1175.    Return Values:
  1176.  
  1177.       Success: TRUE
  1178.       Failure: FALSE
  1179.  
  1180.    Notes:
  1181.  
  1182. ******************************************************************************/
  1183.  
  1184. BOOL FAR PASCAL XYZDataDlgProc( 
  1185.  
  1186.    HWND hDlg,           /* Dialog window handle.
  1187.                         */
  1188.  
  1189.    unsigned nMsg,       /* Message to dialog.
  1190.                         */
  1191.  
  1192.    WORD wParam,         /* Word parameter.
  1193.                         */
  1194.  
  1195.    LONG lParam          /* Long parameter.
  1196.                         */
  1197.  
  1198.    )
  1199.  
  1200. {
  1201.    /*  Process the message.  */
  1202.  
  1203.    switch ( nMsg )
  1204.    {
  1205.       /*  Process the init dialog message.  */
  1206.  
  1207.       case WM_INITDIALOG:
  1208.  
  1209.          /*  Update the data fields.  */
  1210.  
  1211.          UpdateXYZDataDlg( );
  1212.  
  1213.          SetFocus( GetDlgItem( hDlg, IDOK ) );
  1214.  
  1215.          return ( FALSE );
  1216.  
  1217.          break;
  1218.  
  1219.       /*  Process the command message.  */
  1220.  
  1221.       case WM_COMMAND:
  1222.  
  1223.          /*  Parse the control ID.  */
  1224.  
  1225.          switch ( wParam )
  1226.          {
  1227.             /*  Process the Ok button. */
  1228.  
  1229.             case IDOK:
  1230.  
  1231.                DestroyWindow( hDlg );
  1232.                break;
  1233.  
  1234.             /*  Default processing.  */
  1235.  
  1236.             default:
  1237.                return ( FALSE );
  1238.                break;
  1239.  
  1240.          }
  1241.  
  1242.          break;
  1243.  
  1244.       /*  Process the destroy message.  */
  1245.  
  1246.       case WM_DESTROY:
  1247.  
  1248.          hXYZDataDlg = NULL;
  1249.  
  1250.          break;
  1251.  
  1252.       /*  Default processing.  */
  1253.  
  1254.       default:
  1255.  
  1256.          return ( FALSE );
  1257.          break;
  1258.  
  1259.    }
  1260.  
  1261.    return ( TRUE );
  1262.  
  1263. }
  1264.  
  1265. /******************************************************************************
  1266.  
  1267.    Function Name: UpdateXYZDataDlg
  1268.  
  1269.    Description:
  1270.  
  1271.       Updates the controls in the XYZ data dialog.
  1272.  
  1273.    Control Flow:
  1274.  
  1275.    Return Values:
  1276.  
  1277.       None.
  1278.  
  1279.    Notes:
  1280.  
  1281. ******************************************************************************/
  1282.  
  1283. void NEAR PASCAL UpdateXYZDataDlg( void )
  1284.  
  1285. {
  1286.    /*  Update the controls.  */
  1287.  
  1288.    SetDlgItemInt( hXYZDataDlg, ID_XROT, (int) ( pt3dRot.x / PI * 180. ), TRUE );
  1289.    SetDlgItemInt( hXYZDataDlg, ID_YROT, (int) ( pt3dRot.y / PI * 180. ), TRUE );
  1290.    SetDlgItemInt( hXYZDataDlg, ID_ZROT, (int) ( pt3dRot.z / PI * 180. ), TRUE );
  1291.  
  1292.    SetDlgItemInt( hXYZDataDlg, ID_XLOC, (int) ( pt3dLoc.x ), TRUE );
  1293.    SetDlgItemInt( hXYZDataDlg, ID_YLOC, (int) ( pt3dLoc.y ), TRUE );
  1294.    SetDlgItemInt( hXYZDataDlg, ID_ZLOC, (int) ( pt3dLoc.z ), TRUE );
  1295.  
  1296.    SetDlgItemInt( hXYZDataDlg, ID_XMOV, (int) ( cptMove.pt3dNew.x ), TRUE );
  1297.    SetDlgItemInt( hXYZDataDlg, ID_YMOV, (int) ( cptMove.pt3dNew.y ), TRUE );
  1298.    SetDlgItemInt( hXYZDataDlg, ID_ZMOV, (int) ( cptMove.pt3dNew.z ), TRUE );
  1299.  
  1300.    return;
  1301.  
  1302. }
  1303.  
  1304. /******************************************************************************
  1305.  
  1306.    Function Name: AboutDlgProc
  1307.  
  1308.    Description:
  1309.  
  1310.       Processes the messages for the About dialog window.
  1311.  
  1312.    Control Flow:
  1313.  
  1314.    Return Values:
  1315.  
  1316.       Dialog function dependent.
  1317.  
  1318.    Notes:
  1319.  
  1320. ******************************************************************************/
  1321.  
  1322. BOOL FAR PASCAL AboutDlgProc( 
  1323.  
  1324.    HWND hDlg,           /* Dialog window handle.
  1325.                         */
  1326.  
  1327.    unsigned nMsg,       /* Message type.
  1328.                         */
  1329.  
  1330.    WORD wParam,         /* 16-bit parameter.
  1331.                         */
  1332.  
  1333.    LONG lParam          /* 32-bit parameter.
  1334.                         */
  1335.  
  1336.    )
  1337.  
  1338. {
  1339.    /*  Process the message.  */
  1340.  
  1341.    switch ( nMsg )
  1342.    {
  1343.       /*  Process the command message.  */
  1344.  
  1345.       case WM_COMMAND:
  1346.  
  1347.          /*  Parse the control ID.  */
  1348.  
  1349.          switch ( wParam )
  1350.          {
  1351.             /*  Process the OK button.  */
  1352.  
  1353.             case IDOK:
  1354.                EndDialog( hDlg, TRUE );
  1355.                break;
  1356.  
  1357.             /*  Default processing.  */
  1358.  
  1359.             default:
  1360.                return ( FALSE );
  1361.                break;
  1362.  
  1363.          }
  1364.  
  1365.          break;
  1366.  
  1367.       /*  Default processing.  */
  1368.  
  1369.       default:
  1370.          return ( FALSE );
  1371.          break;
  1372.  
  1373.    }
  1374.  
  1375.    return ( TRUE );
  1376.  
  1377. }
  1378.  
  1379. /******************************************************************************
  1380.  
  1381.    Function Name: AnimateCranePts
  1382.  
  1383.    Description:
  1384.  
  1385.       Performs animation on the specific crane points.
  1386.  
  1387.    Control Flow:
  1388.  
  1389.    Return Values:
  1390.  
  1391.       None.
  1392.  
  1393.    Notes:
  1394.  
  1395. ******************************************************************************/
  1396.  
  1397. void NEAR PASCAL AnimateCranePts(
  1398.  
  1399.    HWND hWnd            /* Window handle.
  1400.                         */
  1401.  
  1402.    )
  1403.  
  1404. {
  1405.    /*  Variable definition.  */
  1406.  
  1407.    WORD           unI,                       /* Indexing variable */
  1408.                   unIndex;                   /* Index */
  1409.  
  1410.    /*  Animate the points while animation is requested.  */
  1411.  
  1412.    while ( bAnimate )
  1413.    {
  1414.       /*  Initialize the erase rectangle.  */
  1415.  
  1416.       rErase.left   = 32767;
  1417.       rErase.top    = 32767;
  1418.       rErase.right  = -32767;
  1419.       rErase.bottom = -32767;
  1420.  
  1421.       /*  Loop and animate the points.  */
  1422.  
  1423.       for ( unI = 0; unI < CNT_ANIMATE; ++unI )
  1424.       {
  1425.          aaptList[ unI ].dfCurRot += aaptList[ unI ].dfIncRot;
  1426.  
  1427.          if ( aaptList[ unI ].dfCurRot <= aaptList[ unI ].dfMinRot ||
  1428.               aaptList[ unI ].dfCurRot >= aaptList[ unI ].dfMaxRot
  1429.             )
  1430.             aaptList[ unI ].dfIncRot = -aaptList[ unI ].dfIncRot;
  1431.  
  1432.          unIndex = aaptList[ unI ].unPtIndex;
  1433.  
  1434.          acptList[ unIndex ].pt3dOrg.x = cos( aaptList[ unI ].dfCurRot ) *
  1435.                                           aaptList[ unI ].dfDst;
  1436.          acptList[ unIndex ].pt3dOrg.y = sin( aaptList[ unI ].dfCurRot ) *
  1437.                                           aaptList[ unI ].dfDst;
  1438.  
  1439.       }
  1440.  
  1441.       /*  Compute the location offset.  */
  1442.  
  1443.       CalcNewPt( &cptMove );
  1444.  
  1445.       pt3dLoc.x += cptMove.pt3dNew.x;
  1446.       pt3dLoc.y += cptMove.pt3dNew.y;
  1447.       pt3dLoc.z += cptMove.pt3dNew.z;
  1448.  
  1449.       /*  Calculate the new points.  */
  1450.  
  1451.       CalcNewCranePts( );
  1452.  
  1453.       /*  Compute and erase the update rectangle.  */
  1454.  
  1455.       UnionRect( &rUpdate, &rErase, &rOldErase );
  1456.  
  1457.       rOldErase = rErase;
  1458.  
  1459.       /*  Convert the update rectangle to device units.  */
  1460.  
  1461.       LPtoDP( hClientDC, (LPPOINT) &rUpdate, 2 );
  1462.  
  1463.       rUpdate.left   -= 2;
  1464.       rUpdate.top    -= 2;
  1465.       rUpdate.right  += 2;
  1466.       rUpdate.bottom += 2;
  1467.  
  1468.       InvalidateRect( hWnd, &rUpdate, TRUE );
  1469.  
  1470.       /*  Convert back to logical units.  */
  1471.  
  1472.       DPtoLP( hClientDC, (LPPOINT) &rUpdate, 2 );
  1473.  
  1474.       /*  If recording then write the data.  */
  1475.  
  1476.       if ( bRecording )
  1477.          RecordWrite( );
  1478.  
  1479.       /*  Update the dialog.  */
  1480.  
  1481.       if ( hXYZDataDlg )
  1482.          UpdateXYZDataDlg( );
  1483.  
  1484.       /*  Yield.  */
  1485.  
  1486.       myYield( );
  1487.  
  1488.    }
  1489.  
  1490.    return;
  1491.  
  1492. }
  1493.  
  1494. /******************************************************************************
  1495.  
  1496.    Function Name: CalcNewCranePts
  1497.  
  1498.    Description:
  1499.  
  1500.       Calculate the new crane points.
  1501.  
  1502.    Control Flow:
  1503.  
  1504.    Return Values:
  1505.  
  1506.       None.
  1507.  
  1508.    Notes:
  1509.  
  1510. ******************************************************************************/
  1511.  
  1512. void NEAR PASCAL CalcNewCranePts( void )
  1513.  
  1514. {
  1515.    /*  Variable definition.  */
  1516.  
  1517.    WORD           unI;                       /* Indexing variable */
  1518.  
  1519.    /*  Recalculate the points.  */
  1520.  
  1521.    for ( unI = 0; acptList[ unI ].unFlags != CPF_EOL; ++unI )
  1522.    {
  1523.       CalcNewPt( &acptList[ unI ] );
  1524.  
  1525.       aptList[ unI ].x = (int) acptList[ unI ].pt3dNew.x;
  1526.       aptList[ unI ].y = (int) acptList[ unI ].pt3dNew.y;
  1527.  
  1528.       if ( aptList[ unI ].x < rErase.left )
  1529.          rErase.left = aptList[ unI ].x;
  1530.  
  1531.       if ( aptList[ unI ].y < rErase.top )
  1532.          rErase.top = aptList[ unI ].y;
  1533.  
  1534.       if ( aptList[ unI ].x > rErase.right )
  1535.          rErase.right = aptList[ unI ].x;
  1536.  
  1537.       if ( aptList[ unI ].y > rErase.bottom )
  1538.          rErase.bottom = aptList[ unI ].y;
  1539.  
  1540.    }
  1541.  
  1542.    return;
  1543.  
  1544. }
  1545.  
  1546. /******************************************************************************
  1547.  
  1548.    Function Name: CalcNewPt
  1549.  
  1550.    Description:
  1551.  
  1552.       Calculates the new point.
  1553.  
  1554.    Control Flow:
  1555.  
  1556.    Return Values:
  1557.  
  1558.       None.
  1559.  
  1560.    Notes:
  1561.  
  1562. ******************************************************************************/
  1563.  
  1564. void NEAR PASCAL CalcNewPt(
  1565.  
  1566.    LPCRANEPT lpcpt      /* Crane point pointer.
  1567.                         */
  1568.  
  1569.    )
  1570.  
  1571. {
  1572.    /*  Variable definition.  */
  1573.  
  1574.    double         dfRot,                     /* Rotation */
  1575.                   dfDst;                     /* Distance */
  1576.  
  1577.    /*  Reset the point.  */
  1578.  
  1579.    lpcpt->pt3dNew = lpcpt->pt3dOrg;
  1580.  
  1581.    /*  Perform Z rotation.  */
  1582.  
  1583.    if ( lpcpt->pt3dNew.x != 0. || lpcpt->pt3dNew.y != 0. )
  1584.    {
  1585.       dfRot = atan2( lpcpt->pt3dNew.y, lpcpt->pt3dNew.x ) + pt3dRot.z;
  1586.  
  1587.       dfDst = sqrt( lpcpt->pt3dNew.x * lpcpt->pt3dNew.x +
  1588.                     lpcpt->pt3dNew.y * lpcpt->pt3dNew.y
  1589.                   );
  1590.  
  1591.       lpcpt->pt3dNew.x = ( cos( dfRot ) * dfDst );
  1592.       lpcpt->pt3dNew.y = ( sin( dfRot ) * dfDst );
  1593.  
  1594.    }
  1595.  
  1596.    /*  Perform X rotation.  */
  1597.  
  1598.    if ( lpcpt->pt3dNew.z != 0. || lpcpt->pt3dNew.y != 0. )
  1599.    {
  1600.       dfRot = atan2( lpcpt->pt3dNew.y, lpcpt->pt3dNew.z ) + pt3dRot.x;
  1601.  
  1602.       dfDst = sqrt( lpcpt->pt3dNew.z * lpcpt->pt3dNew.z +
  1603.                     lpcpt->pt3dNew.y * lpcpt->pt3dNew.y
  1604.                   );
  1605.  
  1606.       lpcpt->pt3dNew.z = ( cos( dfRot ) * dfDst );
  1607.       lpcpt->pt3dNew.y = ( sin( dfRot ) * dfDst );
  1608.  
  1609.    }
  1610.  
  1611.    /*  Perform Y rotation.  */
  1612.  
  1613.    if ( lpcpt->pt3dNew.x != 0. || lpcpt->pt3dNew.z != 0. )
  1614.    {
  1615.       dfRot = atan2( lpcpt->pt3dNew.z, lpcpt->pt3dNew.x ) + pt3dRot.y;
  1616.  
  1617.       dfDst = sqrt( lpcpt->pt3dNew.x * lpcpt->pt3dNew.x +
  1618.                     lpcpt->pt3dNew.z * lpcpt->pt3dNew.z
  1619.                   );
  1620.  
  1621.       lpcpt->pt3dNew.x = ( cos( dfRot ) * dfDst );
  1622.       lpcpt->pt3dNew.z = ( sin( dfRot ) * dfDst );
  1623.  
  1624.    }
  1625.  
  1626.    /*  Exit if move point.  */
  1627.  
  1628.    if ( lpcpt->unFlags == CPF_MOVE )
  1629.       return;
  1630.  
  1631.    /*  Adjust relative location and size in space.  */
  1632.  
  1633.    lpcpt->pt3dNew.x += pt3dLoc.x;
  1634.    lpcpt->pt3dNew.y += pt3dLoc.y;
  1635.    lpcpt->pt3dNew.z += pt3dLoc.z;
  1636.  
  1637.    if ( lpcpt->pt3dNew.x != 0. || lpcpt->pt3dNew.y != 0. )
  1638.    {
  1639.       dfRot = atan2( lpcpt->pt3dNew.y, lpcpt->pt3dNew.x );
  1640.  
  1641.       dfDst = sqrt( lpcpt->pt3dNew.x * lpcpt->pt3dNew.x +
  1642.                     lpcpt->pt3dNew.y * lpcpt->pt3dNew.y
  1643.                   );
  1644.  
  1645.       dfDst *= ( lpcpt->pt3dNew.z - ZSZ_ATMINSIZ ) / ZSZ_ATMAXSIZ;
  1646.  
  1647.       if ( dfDst < 0. )
  1648.          dfDst = 0.;
  1649.  
  1650.       lpcpt->pt3dNew.x = ( cos( dfRot ) * dfDst );
  1651.       lpcpt->pt3dNew.y = ( sin( dfRot ) * dfDst );
  1652.  
  1653.    }
  1654.  
  1655.    return;
  1656.  
  1657. }
  1658.  
  1659. /******************************************************************************
  1660.  
  1661.    Function Name: RecordPlayback
  1662.  
  1663.    Description:
  1664.  
  1665.       Plays back the recording.
  1666.  
  1667.    Control Flow:
  1668.  
  1669.    Return Values:
  1670.  
  1671.       None.
  1672.  
  1673.    Notes:
  1674.  
  1675. ******************************************************************************/
  1676.  
  1677. void NEAR PASCAL RecordPlayback( 
  1678.  
  1679.    HWND hWnd            /* Window handle.
  1680.                         */
  1681.  
  1682.    )
  1683.       
  1684. {
  1685.    /*  Variable definition.  */
  1686.  
  1687.    RECT           rClient;                   /* Client rectangle */
  1688.  
  1689.    HBRUSH         hEraseBrush;               /* Brush handle */
  1690.  
  1691.    WORD           unC,                       /* Counting variable */
  1692.                   unI;                       /* Indexing variable */
  1693.  
  1694.    /*  Erase the background.  */
  1695.  
  1696.    hEraseBrush = GetStockObject( WHITE_BRUSH );
  1697.  
  1698.    GetClientRect( hWnd, &rClient );
  1699.  
  1700.    DPtoLP( hClientDC, (LPPOINT) &rClient, 2 );
  1701.  
  1702.    FillRect( hClientDC, &rClient, hEraseBrush );
  1703.  
  1704.    /*  Playback the records.  */
  1705.  
  1706.    _llseek( fhRecordFile, 0L, 0 );
  1707.  
  1708.    for ( unC = 0; unC < unRecordCnt; ++unC )
  1709.    {
  1710.       /*  Read the next set of points.  */
  1711.  
  1712.       RecordRead( );
  1713.  
  1714.       /*  Perform our painting.  */
  1715.  
  1716.       FillRect( hClientDC, &rUpdate, hEraseBrush );
  1717.  
  1718.       for ( unI = 0; unI < MAX_SHAPES; ++unI )
  1719.          Polyline( hClientDC,
  1720.                    &aptList[ ashpList[ unI ].unIndex ],
  1721.                    ashpList[ unI ].unCnt
  1722.                  );
  1723.  
  1724.    }
  1725.  
  1726.    return;
  1727.  
  1728. }
  1729.  
  1730. /******************************************************************************
  1731.  
  1732.    Function Name: RecordRead
  1733.  
  1734.    Description:
  1735.  
  1736.       Reads one set of points from the file.
  1737.  
  1738.    Control Flow:
  1739.  
  1740.    Return Values:
  1741.  
  1742.       None.
  1743.  
  1744.    Notes:
  1745.  
  1746. ******************************************************************************/
  1747.  
  1748. void NEAR PASCAL RecordRead( void )
  1749.  
  1750. {
  1751.    /*  Read the points in.  */
  1752.  
  1753.    _lread( fhRecordFile, (LPSTR) &rUpdate, sizeof ( RECT ) );
  1754.    _lread( fhRecordFile, (LPSTR) aptList, sizeof ( POINT ) * MAX_POINTS );
  1755.  
  1756.    return;
  1757.  
  1758. }
  1759.  
  1760. /******************************************************************************
  1761.  
  1762.    Function Name: RecordWrite
  1763.  
  1764.    Description:
  1765.  
  1766.       Writes one set of points to the file.
  1767.  
  1768.    Control Flow:
  1769.  
  1770.    Return Values:
  1771.  
  1772.       None.
  1773.  
  1774.    Notes:
  1775.  
  1776. ******************************************************************************/
  1777.  
  1778. void NEAR PASCAL RecordWrite( void )
  1779.  
  1780. {
  1781.    /*  Read the points in.  */
  1782.  
  1783.    _lwrite( fhRecordFile, (LPSTR) &rUpdate, sizeof ( RECT ) );
  1784.    _lwrite( fhRecordFile, (LPSTR) aptList, sizeof ( POINT ) * MAX_POINTS );
  1785.  
  1786.    ++unRecordCnt;
  1787.  
  1788.    return;
  1789.  
  1790. }
  1791.  
  1792. /******************************************************************************
  1793.  
  1794.    Function Name: Key
  1795.  
  1796.    Description:
  1797.  
  1798.       Provides processing for key events.
  1799.  
  1800.    Control Flow:
  1801.  
  1802.    Return Values:
  1803.  
  1804.       None.
  1805.  
  1806.    Notes:
  1807.  
  1808. ******************************************************************************/
  1809.  
  1810. void NEAR PASCAL Key( 
  1811.  
  1812.    HWND hWnd,           /* Window handle.
  1813.                         */
  1814.  
  1815.    WORD wId             /* Key ID.
  1816.                         */
  1817.  
  1818.    )
  1819.       
  1820. {
  1821.    /*  Parse the key pressed and adjust the appropiate rotation amount.  */
  1822.  
  1823.    switch ( wId )
  1824.    {
  1825.       case VK_NUMPAD2:
  1826.  
  1827.          pt3dRot.x -= ROT_INC;
  1828.  
  1829.          if ( pt3dRot.x <= ROT_MIN )
  1830.             pt3dRot.x = ROT_MAX;
  1831.  
  1832.          break;
  1833.  
  1834.       case VK_NUMPAD8:
  1835.  
  1836.          pt3dRot.x += ROT_INC;
  1837.  
  1838.          if ( pt3dRot.x >= ROT_MAX )
  1839.             pt3dRot.x = ROT_MIN;
  1840.  
  1841.          break;
  1842.  
  1843.       case VK_NUMPAD4:
  1844.  
  1845.          pt3dRot.y -= ROT_INC;
  1846.  
  1847.          if ( pt3dRot.y <= ROT_MIN )
  1848.             pt3dRot.y = ROT_MAX;
  1849.  
  1850.          break;
  1851.  
  1852.       case VK_NUMPAD6:
  1853.  
  1854.          pt3dRot.y += ROT_INC;
  1855.  
  1856.          if ( pt3dRot.y >= ROT_MAX )
  1857.             pt3dRot.y = ROT_MIN;
  1858.  
  1859.          break;
  1860.  
  1861.       case VK_NUMPAD1:
  1862.  
  1863.          pt3dRot.z -= ROT_INC;
  1864.  
  1865.          if ( pt3dRot.z <= ROT_MIN )
  1866.             pt3dRot.z = ROT_MAX;
  1867.  
  1868.          break;
  1869.  
  1870.       case VK_NUMPAD9:
  1871.  
  1872.          pt3dRot.z += ROT_INC;
  1873.  
  1874.          if ( pt3dRot.z >= ROT_MAX )
  1875.             pt3dRot.z = ROT_MIN;
  1876.  
  1877.          break;
  1878.  
  1879.       default:
  1880.  
  1881.          return;
  1882.          break;
  1883.  
  1884.    }
  1885.  
  1886.    /*  If not animating then calculate the new points and paint them.  */
  1887.  
  1888.    if ( !bAnimate )
  1889.    {
  1890.       CalcNewCranePts( );
  1891.       InvalidateRect( hWnd, NULL, TRUE );
  1892.    }
  1893.  
  1894.    return;
  1895.  
  1896. }
  1897.  
  1898. /******************************************************************************
  1899.  
  1900.    Function Name: Size
  1901.  
  1902.    Description:
  1903.  
  1904.       Performs processing for re-sizing of the client window.
  1905.  
  1906.    Control Flow:
  1907.  
  1908.    Return Values:
  1909.  
  1910.       None.
  1911.  
  1912.    Notes:
  1913.  
  1914. ******************************************************************************/
  1915.  
  1916. void NEAR PASCAL Size(
  1917.  
  1918.    HWND hWnd,           /* Window handle.
  1919.                         */
  1920.  
  1921.    LONG lParam          /* 32-bit parameter.
  1922.                         */
  1923.  
  1924.    )
  1925.  
  1926. {
  1927.    /*  Variable definition.  */
  1928.  
  1929.    POINT          ptExt,                     /* Extents */
  1930.                   ptOrg;                     /* Origin */
  1931.  
  1932.    /*  Get the new size and update the mapping.  */
  1933.  
  1934.    ptExt = MAKEPOINT( lParam );
  1935.  
  1936.    if ( ptExt.x < ptExt.y )
  1937.    {
  1938.       ptOrg.x = 0;
  1939.       ptOrg.y = ( ptExt.y - ptExt.x ) / 2;
  1940.       ptExt.y = ptExt.x;
  1941.    }
  1942.    else
  1943.    {
  1944.       ptOrg.x = ( ptExt.x - ptExt.y ) / 2;
  1945.       ptOrg.y = 0;
  1946.       ptExt.x = ptExt.y;
  1947.    }
  1948.  
  1949.    SetViewportOrg( hClientDC, ptOrg.x, ptOrg.y );
  1950.    SetViewportExt( hClientDC, ptExt.x, ptExt.y );
  1951.  
  1952.    InvalidateRect( hWnd, NULL, TRUE );
  1953.  
  1954.    return;
  1955.  
  1956. }
  1957.  
  1958. /******************************************************************************
  1959.  
  1960.    Function Name: Paint
  1961.  
  1962.    Description:
  1963.  
  1964.       Performs updates on the client area as requested by window messages.
  1965.  
  1966.    Control Flow:
  1967.  
  1968.    Return Values:
  1969.  
  1970.       None.
  1971.  
  1972.    Notes:
  1973.  
  1974. ******************************************************************************/
  1975.  
  1976. void NEAR PASCAL Paint( 
  1977.  
  1978.    HWND hWnd            /* Window handle.
  1979.                         */
  1980.  
  1981.    )
  1982.  
  1983. {
  1984.    /*  Variable definition.  */
  1985.  
  1986.    PAINTSTRUCT    stPS;                      /* Painting structure */
  1987.  
  1988.    WORD           unI;                       /* Indexing variable */
  1989.  
  1990.    /*  Prepare the client area for painting.  */
  1991.  
  1992.    BeginPaint( hWnd, &stPS );
  1993.  
  1994.    /*  Perform our painting.  */
  1995.  
  1996.    for ( unI = 0; unI < MAX_SHAPES; ++unI )
  1997.       Polyline( hClientDC,
  1998.                 &aptList[ ashpList[ unI ].unIndex ],
  1999.                 ashpList[ unI ].unCnt
  2000.               );
  2001.  
  2002.    /*  We're done so exit.  */
  2003.  
  2004.    EndPaint( hWnd, &stPS );
  2005.  
  2006.    return;
  2007.  
  2008. }
  2009.  
  2010. /******************************************************************************
  2011.  
  2012.    Function Name: ResetCranePts
  2013.  
  2014.    Description:
  2015.  
  2016.       Resets the crane points back to the origin.
  2017.  
  2018.    Control Flow:
  2019.  
  2020.    Return Values:
  2021.  
  2022.       None.
  2023.  
  2024.    Notes:
  2025.  
  2026. ******************************************************************************/
  2027.  
  2028. void NEAR PASCAL ResetCranePts( void )
  2029.       
  2030. {
  2031.    /*  Reset the points.  */
  2032.  
  2033.    pt3dRot.x = 0.;
  2034.    pt3dRot.y = 0.;
  2035.    pt3dRot.z = 0.;
  2036.  
  2037.    pt3dLoc.x = 0.;
  2038.    pt3dLoc.y = 0.;
  2039.    pt3dLoc.z = 0.;
  2040.  
  2041.    CalcNewCranePts( );
  2042.  
  2043.    return;
  2044.  
  2045. }
  2046.  
  2047. /******************************************************************************
  2048.  
  2049.    Function Name: myYield
  2050.  
  2051.    Description:
  2052.  
  2053.       Uses PeekMessage to yield control.
  2054.  
  2055.    Control Flow:
  2056.  
  2057.    Return Values:
  2058.  
  2059.       None.
  2060.  
  2061.    Notes:
  2062.  
  2063. ******************************************************************************/
  2064.  
  2065. void NEAR PASCAL myYield( void )
  2066.  
  2067. {
  2068.    /*  Variable definition.  */
  2069.  
  2070.    MSG            stMsg;                     /* Buffer to hold message */
  2071.  
  2072.    /*  Process messages until exit.  */
  2073.  
  2074.    while ( PeekMessage( &stMsg, NULL, 0, 0, PM_REMOVE ) )
  2075.    {
  2076.       TranslateMessage( &stMsg );
  2077.       DispatchMessage( &stMsg );
  2078.    }
  2079.  
  2080.    return;
  2081.  
  2082. }
  2083.