home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / MTHREAD.PAK / LINE.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  7.0 KB  |  226 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // Copyright (c) 1991, 1995 by Borland International, All Rights Reserved
  4. //
  5. // MoveToLineTo demo window
  6. //----------------------------------------------------------------------------
  7. #include <owl/pch.h>
  8. #include <owl/dc.h>
  9. #include "line.h"
  10. #include <math.h>
  11.  
  12. //
  13. //
  14. //
  15. DEFINE_RESPONSE_TABLE1(TMoveToLineToWindow, TBaseDemoWindow)
  16.   EV_WM_SIZE,
  17. END_RESPONSE_TABLE;
  18.  
  19. IMPLEMENT_CASTABLE1(TMoveToLineToWindow, TBaseDemoWindow);
  20.  
  21. //
  22. //
  23. //
  24. TMoveToLineToWindow::TMoveToLineToWindow()
  25. :
  26.   TBaseDemoWindow()
  27. {
  28.   Rotation = 0;
  29.   PointCount = MaxPoints;
  30.   Iconized = false;
  31.   MemDC = new TMemoryDC;
  32.   Bitmap = 0;
  33.  
  34.   RotatePoints();
  35.   Start();
  36. }
  37.  
  38. //
  39. //
  40. //
  41. TMoveToLineToWindow::~TMoveToLineToWindow()
  42. {
  43.   delete MemDC;
  44.   delete Bitmap;
  45. }
  46.  
  47. //
  48. //
  49. //
  50. void
  51. TMoveToLineToWindow::EvSize(uint sizeType, TSize& size)
  52. {
  53.   TBaseDemoWindow::EvSize(sizeType, size);
  54.   Invalidate();
  55.   TRect rect;
  56.  
  57.   if (sizeType == SIZE_MINIMIZED) {
  58.     if (!Iconized) {
  59.       Rotation = 0;
  60.       Iconized = true;
  61.       PointCount = IconicPoints;
  62.       RotatePoints();
  63.     }
  64.     Parent->GetClientRect(rect);
  65.   }
  66.   else {
  67.     if (Iconized) {
  68.       Rotation = 0;
  69.       Iconized = false;
  70.       PointCount = MaxPoints;
  71.       RotatePoints();
  72.     }
  73.     GetClientRect(rect);
  74.   }
  75.  
  76.   int centerX = rect.right / 2;
  77.   int centerY = rect.bottom / 2;
  78.   int radius = min(centerY, centerX);
  79.  
  80.   // The follow memory DC operations are not required to draw lines, but
  81.   // were added to reduce screen flicker and speed up screen updates.
  82.   //
  83.   delete Bitmap;
  84.   Bitmap = new TBitmap(TScreenDC(), radius*2, radius*2);
  85.   MemDC->SelectObject(*Bitmap);
  86. }
  87.  
  88. //
  89. // The main do-er function for this thread window. Beware that any form of
  90. // SendMessage() to a window in this app here will deadlock this thread with
  91. // the app. This is because this window is really 'owned' by the app thread.
  92. //
  93. void
  94. TMoveToLineToWindow::ClockTick()
  95. {
  96.   RotatePoints();
  97.   if (Iconized) {
  98.     // Iconized windows don't process paint messages, so we'll manually
  99.     // update the image here.  Doing this painting during the timer tick
  100.     // will slow things down a bit, especially with several of these
  101.     // windows iconized at the same time.
  102.     //
  103.     Paint(TClientDC(*Parent), false, TRect());
  104.   }
  105.   else {
  106. #if 1
  107.     // In terms of Windows resources and system wide performance, letting
  108.     // paint do the work is 'faster' because it reduces the CPU time spent
  109.     // handling each timer tick.  Paint messages are low priority, so other
  110.     // messages like mouse clicks and other user input get processed first.
  111.     // The downside is that the paint messages are handled last, when
  112.     // there's nothing else to do, which can make animation look a bit jerky
  113.     // on a busy machine.
  114.     //
  115.     Invalidate(false);  // Let the Paint method draw the new figure...
  116.  
  117.     // Optional direct paint call allows paint during window manipulation.
  118.     // This makes the animation a bit smoother, and its kinda fun to watch the
  119.     // animation adjust on the fly to the resizing of its window.
  120. #else
  121.     Paint(TClientDC(*this), false, TRect());
  122. #endif
  123.   }
  124. }
  125.  
  126. //
  127. //
  128. //
  129. void
  130. TMoveToLineToWindow::RotatePoints()
  131. {
  132.   // NOTE: all figures are in radians
  133.   //
  134.   const float M_2PI = 2 * M_PI;           // 2 pi radians in a circle
  135.   float StepAngle = M_2PI / PointCount;   // angular distance between points
  136.  
  137.   Rotation += M_PI / 32;   // Increment the angle of rotation of figure
  138.   if (Rotation > StepAngle)
  139.     Rotation -= StepAngle;   // Keep rotation less than distance between points
  140.  
  141.   // The loop below has i walking through the Points array, while j walks
  142.   // simultaneously through the angles to each point on the circle.
  143.   // Incrementing j by StepAngle moves j to the next point on the circle with
  144.   // no complicated arithmetic (everything has been set up in advance of the
  145.   // loop).  Initializing j with Rotation causes the entire figure to shift
  146.   // clockwise a small amount.
  147.   //
  148.   int i;
  149.   float j;
  150.   for (i = 0, j = Rotation; i < PointCount; i++, j += StepAngle) {
  151.     Points[i].X = cos(j);   // These values will be multiplied by the
  152.     Points[i].Y = sin(j);   // current radius at display time.
  153.   }
  154. }
  155.  
  156. //
  157. //
  158. //
  159. void
  160. TMoveToLineToWindow::Paint(TDC& dc, bool, TRect&)
  161. {
  162.   TRect rect;
  163.   if (Iconized)
  164.     Parent->GetClientRect(rect);
  165.   else
  166.     GetClientRect(rect);
  167.  
  168.   int centerX = rect.right / 2;
  169.   int centerY = rect.bottom / 2;
  170.   int radius = min(centerY, centerX);
  171.  
  172.   // Initiallize the bitmap to all white.
  173.   //
  174.   MemDC->PatBlt(0, 0, radius*2, radius*2, WHITENESS);
  175.  
  176.   // The Ellipse and the loop are all that's really needed to draw.  If you
  177.   // substitute dc for MemDC, the draws will go directly to the screen.
  178.   // (Though the figure would no longer be centered, since the figure is drawn
  179.   // on a MemDC bitmap, and the bitmap is then centered on the dc...)
  180.   // Since this line window is animated, it is frequently updated, which would
  181.   // cause the window to spend most of its time flickering if the dc were
  182.   // used.  Thus, the need for memory DC operations.  If the window were not
  183.   // animated, drawing onto the dc would look just fine.
  184.   //
  185.   MemDC->Ellipse(0, 0, radius*2, radius*2);
  186.   int i,j;
  187.   for (i = 0; i < PointCount; i++) {
  188.     for (j = i + 1; j < PointCount; j++) {
  189.       MemDC->MoveTo(radius + floor(Points[i].X * radius),
  190.                     radius + floor(Points[i].Y * radius));
  191.       MemDC->LineTo(radius + floor(Points[j].X * radius),
  192.                     radius + floor(Points[j].Y * radius));
  193.     }
  194.   }
  195.  
  196.   // Now transfer what was drawn on the (invisible) memory DC onto the visible
  197.   // dc.  This one BitBlt transfer is much faster than the many
  198.   // individual operations that were performed above.
  199.   //
  200.   dc.BitBlt(centerX-radius, centerY-radius, radius*2, radius*2,
  201.             *MemDC, 0, 0, SRCCOPY);
  202.  
  203.   // Restore original bitmap before leaving
  204.   //
  205. //  MemDC->RestoreBitmap();
  206.  
  207.   // Footnotes:
  208.   // Drawing this figure doesn't require a memory DC.  Animating the figure
  209.   // requires a memory DC only to reduce flicker to a tolerable level.
  210.  
  211.   // To make the animation faster still, (but use more memory, too),
  212.   // you could keep that memory DC hanging around between screen paints -
  213.   // constructing a DC takes some effort, and we're constructing one every
  214.   // time we get a timer message.
  215.  
  216.   // You'd get the biggest improvement in animation speed by calculating a
  217.   // sequence of bitmaps, then just displaying them in the proper sequence.
  218.   // This demo reconstructs the points list and redraws the figure for every
  219.   // timer message - a lot of work for the CPU, but it's code is simpler and
  220.   // doesn't use as much memory as more elaborate schemes might.
  221.  
  222.   // A challenge:  Turn the rotating figure into a ball that bounces off the
  223.   // walls of the window.  Don't forget the english (spin) the ball should
  224.   // pick up when bouncing off the wall...
  225. }
  226.