home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pmstars.zip / PMStars.c next >
C/C++ Source or Header  |  1999-08-13  |  13KB  |  290 lines

  1. #include "pmstars.h"
  2.  
  3. HAB hab;
  4. int track=0;  /* Star will 'track' */
  5. LONG back_clr=CLR_BLACK;  /* (client) Window background color */
  6.  
  7. void main(int argc, char *argv[]) {
  8.   HMQ hmq;
  9.   QMSG qmsg;
  10.   HWND hwndFrame, hwndDrawing;
  11.   ULONG flFrameFlags= FCF_TITLEBAR | FCF_SYSMENU | FCF_MAXBUTTON |
  12.                       FCF_SIZEBORDER | FCF_TASKLIST;
  13.   char szClientClass[]="PMStars";
  14.  
  15. /* Standard PM window creation stuff */
  16.   hab=WinInitialize( 0 );
  17.   hmq=WinCreateMsgQueue( hab, 0 );
  18.   WinRegisterClass( hab, szClientClass, (PFNWP)ClientWndProc,
  19.            CS_SIZEREDRAW, (ULONG)0 );
  20.   hwndFrame=WinCreateStdWindow( HWND_DESKTOP, WS_VISIBLE,
  21.                  &flFrameFlags, szClientClass, szClientClass,
  22.                  0L, NULLHANDLE, 0L, &hwndDrawing );
  23. /* Check that window was created then set window location on the screen and display */
  24.   if ( hwndFrame != NULLHANDLE )
  25.     WinSetWindowPos ( hwndFrame, NULLHANDLE, 10L, 10L, SCREEN_WIDTH, SCREEN_HEIGHT,
  26.                       SWP_ACTIVATE | SWP_MOVE | SWP_SIZE | SWP_SHOW ) ;
  27.  
  28. /* Window message handling loop */
  29.   while( WinGetMsg( hab,&qmsg,NULLHANDLE,0L,0L ) )
  30.     WinDispatchMsg( hab,&qmsg );
  31.  
  32. /* Application has been terminated (close, etc), so clean-up and exit */
  33.   WinDestroyWindow( hwndFrame );
  34.   WinDestroyMsgQueue( hmq );
  35.   WinTerminate( hab );
  36.   return;
  37. }
  38.  
  39. MRESULT EXPENTRY ClientWndProc(HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2) {
  40.   static LONG width, height, /* (client) Window width (x-coord) and height (y-coord) */
  41.               center_x, center_y;  /* Star origin */
  42.   static HDC hdc;  /* PM device context (GPI Presentation Space needs this) */
  43.   static HPS hps;  /* GPI Presentation Space; graphics calls draw into this */
  44.   static POINTL star[STARS*2];  /* Star array:  even indexes are previous coords,
  45.                                                 odd indexes are current coords;
  46.                                                 0 is an even index
  47.                                 */
  48.   static int index,  /* Loop variable indicating an index into the star array */
  49.              star_speed[STARS*2],  /* Star 'speed', an offset from a star's current pos'n:
  50.                                       even indexes are for x-coords,
  51.                                       odd indexes are for y-coords;
  52.                                       0 is an even index.
  53.                                       Ranges from 1 to SPEED
  54.                                      */
  55.              signum[STARS*2];  /* Star 'direction':  even indexes are for x-coords,
  56.                                                      odd indexes are for y-coords;
  57.                                                      0 is an even index.
  58.                                                      value is either (+1) or (-1)
  59.                                */
  60.   static ULONG my_timer;  /* System (PM) number indicating unique (system) timer number
  61.                              for this app
  62.                           */
  63. #ifdef DEBUG
  64.   static LONG my_marker;  /* Marker type (defined by PM) */
  65. #endif
  66.  
  67.   switch(msg) {
  68.   case WM_CREATE: {  /* App has just started, so setup any data needed to continue */
  69.     SIZEL size;  /* (PM) struct indicating (client) window size
  70.                     (contains both x- and y-coords)
  71.                  */
  72.     int rn;
  73.  
  74.     srand( (unsigned int)time(0) );
  75.     width=size.cx=SCREEN_WIDTH; center_x=(SHORT)(width/2);
  76.     height=size.cy=SCREEN_HEIGHT; center_y=(SHORT)(height/2);
  77.   /* Open Window Device Context (screen), create GPI Presentation Space
  78.      in that device context, and tell PM to only draw elements to the
  79.      GPI Presentation Space created
  80.   */
  81.     hdc=WinOpenWindowDC( hwnd );
  82.     hps=GpiCreatePS(hab, hdc, &size,
  83.                     PU_PELS | GPIF_DEFAULT | GPIT_NORMAL | GPIA_ASSOC);
  84.     GpiSetDrawingMode( hps, DM_DRAW );
  85.   /* Initialize all stars (current and previous), their x,y speeds and x,y directions */
  86.     for( index=0; index<STARS*2; index+=2) {  /* Spin through all the previous stars */
  87.       star[index].x=0L; star[index].y=0L;
  88.       star[index+1].x=center_x; star[index+1].y=center_y;
  89.       rn=(rand() % SPEED) +1; star_speed[index] = rn;
  90.       rn=(rand() % SPEED) +1; star_speed[index+1] = rn;
  91.       signum[index]=( (rand() % 2) ? 1 : -1 );
  92.       signum[index+1]=( (rand() % 2) ? 1 : -1 );
  93.     } /* endfor index */
  94. #ifdef DEBUG
  95.   /* Define the display marker symbol (small circle, others are available) */
  96.     my_marker=MARKSYM_SMALLCIRCLE;
  97.     GpiSetMarker( hps, my_marker );
  98. #endif
  99.   /* Start the animation timer -- note hab is global, 50 mS timeout */
  100.     my_timer=WinStartTimer( hab, hwnd, 0L, (ULONG)50 );
  101.     break; }  /* endcase WM_CREATE */
  102.  
  103.   case WM_USET: {  /* Message processed when stars must be set (shown) in window */
  104.     LONG nc; int rn;
  105.     for( index=1; index<STARS*2; index+=2) {  /* Spin through the current loc'ns */
  106.   /* Select a color for the (new) star */
  107.       rn=rand() % 8;
  108.       switch ( rn ) {
  109.         case 0: nc=CLR_WHITE; break;
  110.         case 1: nc=CLR_BLUE; break;
  111.         case 2: nc=CLR_RED; break;
  112.         case 3: nc=CLR_GREEN; break;
  113.         case 4: nc=CLR_YELLOW; break;
  114.         case 5: nc=CLR_CYAN; break;
  115.         case 6: nc=CLR_PINK; break;
  116.         case 7: nc=CLR_NEUTRAL; break;
  117.         default: nc=CLR_WHITE;
  118.       }  /* endswitch rand() */
  119.       GpiSetColor( hps, nc );
  120.   /* 'Track' processing: */
  121.       if(track)  /* Stars should not have a 'track' */
  122. #ifdef DEBUG
  123.       {
  124.       /* Marker processing:  Produce an ASCII string for the star number,
  125.          then draw the string and marker at the new point
  126.       */
  127.         char outstr[10]; long ret;
  128.         sprintf( outstr, "%d", index/2+1);
  129.         ret=GpiCharStringAt( hps, &star[index-1], strlen(outstr), outstr );
  130.         GpiMarker( hps, &star[index-1] );
  131.       }
  132. #else
  133.         GpiSetPel( hps, &star[index] );  /* Draw the new point */
  134. #endif
  135.       else {  /* Stars should have a 'track' */
  136.       /* Get the last point drawn then draw a line to the new point */
  137.         GpiMove( hps, &star[index-1] );
  138.         GpiLine( hps, &star[index] );
  139.       }  /* endif track */
  140.     }  /* endfor index */
  141.     break; }  /* endcase WM_USET */
  142.  
  143.   case WM_UUNSET:  /* Message processed when stars must be unset (erased) in window */
  144.   /* Draw color is now the background color (thereby 'erasing' the point) */
  145.     GpiSetColor( hps, back_clr );
  146.   /* 'Track' processing: */
  147.     if(track)  /* Stars should not have a 'track' */
  148.       for( index=0; index<STARS*2; index+=2)  /* Spin through all the previous stars... */
  149. #ifdef DEBUG
  150.     {
  151.     /* Marker processing:  Produce an ASCII string for the star number,
  152.        then (un)draw the string and marker at the new point
  153.     */
  154.       char outstr[10]; long ret;
  155.       sprintf( outstr, "%d", index/2+1);
  156.       ret=GpiCharStringAt( hps, &star[index], strlen(outstr), outstr );
  157.       GpiMarker( hps, &star[index] );
  158.     }
  159. #else
  160.     GpiSetPel( hps, &star[index+1] );  /* Undraw the point
  161.                                           (note current point, not previous one !)
  162.                                        */
  163. #endif
  164.     else  /* Stars should have a 'track' */
  165.     /* Get the last point drawn then undraw the line ('track') */
  166.       for( index=0; index<STARS*2; index+=2) {
  167.         GpiMove( hps, &star[index] );
  168.         GpiLine( hps, &star[index+1] );
  169.       }  /* endfor index */
  170.     break;  /* endcase WM_UUNSET */
  171.  
  172.   case WM_PAINT: { /* Fill a neutral (black) background in the (client) window */
  173.     RECTL rcl;
  174.     HPS hpsX;
  175.     hpsX=WinBeginPaint( hwnd, NULLHANDLE, &rcl );
  176.     WinFillRect( hps, &rcl, back_clr );
  177.     WinEndPaint( hpsX );
  178.     WinSendMsg( hwnd, WM_UUNSET, 0L, 0L );
  179.     WinSendMsg( hwnd, WM_USET, 0L, 0L );
  180.     break;
  181.   }  /* endcase WM_PAINT */
  182.  
  183.   case WM_CLOSE:  /* Message processed when a request to close the application was received */
  184.   /* Delete the current GPI Presentation Space, then signal app termination
  185.      to the caller (main)
  186.   */
  187.     GpiDestroyPS(hps);
  188.     WinPostMsg( hwnd, WM_QUIT, 0L, 0L );
  189.     break;
  190.  
  191.   case WM_SIZE: {  /* Message processed when user has resized the (client) window */
  192.   /* Compute new size from input params and undraw old points & 'tracks' */
  193.     width=SHORT1FROMMP(mp2); height=SHORT2FROMMP(mp2);
  194.     WinSendMsg( hwnd, WM_UUNSET, 0L, 0L );
  195.   /* Calc star loc'ns from the new origin (if req'd):
  196.        - previous x-coord is calc'd if new window size is smaller than previous (x-coord)
  197.        - previous y-coord is calc'd if new window size is smaller than previous (y-coord)
  198.      Note:  x- and y-coords are recalculated are independantly ! (a Feature)
  199.             this method creates the 'runner' lines when 'tracking' (also a Feature)
  200.   */
  201.     for( index=1; index<STARS*2; index+=2) {
  202.       if(center_x > width ) star[index].x=width/2;
  203.       if(center_y > height) star[index].y=height/2;
  204.     }  /* endfor index */
  205.   /* Calc new x,y origins if req'd, then draw all the points / 'tracks' */
  206.     if(center_x > width) center_x=width/2;
  207.     if(center_y > height) center_y=height/2;
  208.     WinPostMsg( hwnd, WM_USET, 0L, 0L);
  209.     break;
  210.   }  /* endcase WM_SIZE */
  211.  
  212.   case WM_BUTTON2DOWN:  /* Message processed when RMB (mouse button 2) is pressed:
  213.                            RMB means toggle from line ('track') to marker (if
  214.                            DEBUG is defined), or line to point (if DEBUG is
  215.                            not defined)
  216.                         */
  217.   /* Erase current or previous points / 'tracks', toggle track variable to
  218.      signal RMB-requested change, then redraw the points / 'tracks'
  219.   */
  220.     WinSendMsg( hwnd, WM_UUNSET, 0L, 0L);
  221.     track=(track ? 0 : 1);
  222.     WinPostMsg( hwnd, WM_USET, 0L, 0L);
  223.     break;  /* endcase WM_BUTTON1DBLCLK */
  224.  
  225.   case WM_BUTTON1DOWN:  /* Message processed when LMB (mouse button 1) is pressed:
  226.                            LMB means redefine a new star origin from the current
  227.                            mouse pos'n (found in input params) and toggle the
  228.                            marker (if DEBUG is defined)
  229.                         */
  230.   /* Change origin to current mouse coords then undraw old points / 'tracks' */
  231.     center_x=SHORT1FROMMP(mp1); center_y=SHORT2FROMMP(mp1);
  232.     WinSendMsg( hwnd, WM_UUNSET, 0L, 0L );
  233. #ifdef DEBUG
  234.   /* Toggle the marker */
  235.     my_marker=( my_marker==MARKSYM_SMALLCIRCLE ? MARKSYM_CROSS : MARKSYM_SMALLCIRCLE );
  236.     GpiSetMarker( hps, my_marker );
  237. #endif
  238.   /* Calc star loc'ns for the new origin:
  239.        - previous x-coord is current loc'n, current x-coord is new origin x-coord
  240.        - previous y-coord is current loc'n, current y-coord is new origin y-coord
  241.      Note:  this method creates the 'runner' lines when 'tracking' (also a Feature)
  242.   */
  243.     for( index=1; index<STARS*2; index+=2) {
  244.       star[index-1].x=star[index].x; star[index].x=center_x;
  245.       star[index-1].y=star[index].y; star[index].y=center_y;
  246.     }  /* endfor index */
  247.     WinPostMsg( hwnd, WM_USET, 0L, 0L);  /* Draw the points / 'tracks' */
  248.     break;  /* endcase WM_BUTTON1DOWN */
  249.  
  250.   case WM_TIMER: {  /* Message processed when timer has 'timed-out' (i.e., expired),
  251.                        so its time to move the stars !
  252.                     */
  253.     int rn;
  254.   /* Undraw old points / 'track' (Note: this MUST be synchronous, i.e. Send is req'd) */
  255.     WinSendMsg( hwnd, WM_UUNSET, 0L, 0L);
  256.   /* Move the current star points to the previous star points array loc'ns */
  257.     for( index = 0; index < STARS*2; index+=2 ) {
  258.       star[index].x=star[index+1].x; star[index].y=star[index+1].y;
  259.     }  /* endfor index */
  260.   /* Calc current (new) point loc'ns using each star's SPEED */
  261.     for ( index = 1 ; index < STARS*2 ; index+=2) {
  262.     /* Check if this star is out-of-bounds: */
  263.       if ( star[index].x < 0L || star[index].y < 0L  ||
  264.            star[index].x > width || star[index].y > height ) {
  265.       /* Star is out-of-bounds: define current and previous star loc'n as
  266.          current origin (long cast is req'd by PM for Pel loc'ns), then define
  267.          new (star) speed and (star) direction.
  268.       */
  269.         star[index].x = star[index-1].x = (long)center_x;
  270.         star[index].y = star[index-1].y = (long)center_y;
  271.         rn=(rand() % SPEED) +1; star_speed[index] = rn;
  272.         rn=(rand() % SPEED) +1; star_speed[index-1] = rn;
  273.         signum[index]=( (rand() % 2) ? 1 : -1 );
  274.         signum[index-1]=( (rand() % 2) ? 1 : -1 );
  275.       } else {  /* Star is not out-of-bounds, so calc new loc'n from current */
  276.         star[index].x += (signum[index-1] * (long) star_speed[index-1]);
  277.         star[index].y += (signum[index] * (long) star_speed[index]);
  278.       }  /* endif star[index].x */
  279.     } /* End for index */
  280.     WinSendMsg( hwnd, WM_USET, 0L, 0L );  /* Draw the points / 'tracks' */
  281.     return MRFROMSHORT( TRUE ); }  /* endcase WM_TIMER */
  282.   default:
  283.     return WinDefWindowProc(hwnd,msg,mp1,mp2);  /* Message not processed here,
  284.                                                    so process normally
  285.                                                 */
  286.   }  /* endswitch msg */
  287.   return MRFROMSHORT( FALSE );
  288. }
  289.  
  290.