home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 May / Pcwk5b98.iso / Borland / Cplus45 / BC45 / GDIDEMO.PAK / ARTY.CPP next >
C/C++ Source or Header  |  1995-08-29  |  10KB  |  356 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1991, 1993 by Borland International
  3. //   Arty demo window object
  4. //----------------------------------------------------------------------------
  5. #include <owl\owlpch.h>
  6. #include <owl\dc.h>
  7. #include <owl\static.h>
  8. #include <stdlib.h>
  9. #include "arty.h"           // class definition for TArtyWindow
  10. #include "artypriv.h"       // internal component classes of TArtyWindow
  11.  
  12.  
  13. //---------- TList ----------------------------------------------
  14.  
  15. // The low-level line draw routine
  16. //
  17. static void
  18. LineDraw(TDC& dc, int x1, int y1, int x2, int y2)
  19. {
  20.   dc.MoveTo(x1, y1);
  21.   dc.LineTo(x2, y2);
  22. }
  23.  
  24. // Initialize the list-of-lines object 
  25. //
  26. TList::TList(int _max)
  27. {
  28.   MaxLines = min(_max, MaxLineCount);
  29.   CurrentLine = 1;
  30.   Xmax = 0;
  31.   Ymax = 0;
  32.   ColorDuration = MaxColorDuration;
  33.   IncrementCount = 0;
  34.   MaxDelta = 10;
  35.   PenColor = TColor(random(256), random(256), random(256));
  36. }
  37.  
  38. // Keep X within range, and reverse Delta if necessary to do so
  39. //
  40. void
  41. TList::AdjustX(int& x, int& deltaX)
  42. {
  43.   int testX = x + deltaX;
  44.   if (testX < 1 || testX > Xmax) {
  45.     testX = x;
  46.     deltaX = -deltaX;
  47.   }
  48.   x = testX;
  49. }
  50.  
  51. // Keep Y within range, and reverse Delta if necessary to do so
  52. //
  53. void
  54. TList::AdjustY(int& y, int& deltaY)
  55. {
  56.   int testY = y + deltaY;
  57.   if (testY < 1 || testY > Ymax) {
  58.     testY = y;
  59.     deltaY = -deltaY;
  60.   }
  61.   y = testY;
  62. }
  63.  
  64. // Clear the array of lines
  65. //
  66. void
  67. TList::ResetLines() 
  68. {
  69.   int startX = Xmax / 2;
  70.   int startY = Ymax / 2;
  71.   for (int i = 0; i < MaxLines; i++) {
  72.     Line[i].LX1 = startX;
  73.     Line[i].LX2 = startX;
  74.     Line[i].LY1 = startY;
  75.     Line[i].LY2 = startY;
  76.     Line[i].Color = 0;
  77.   }
  78.   X1 = startX;
  79.   X2 = startX;
  80.   Y1 = startY;
  81.   Y2 = startY;
  82. }
  83.  
  84. // Scale the old line coordinates to the new Xmax and Ymax coordinates.
  85. //  The new Xmax and new Ymax are passed in as parameters so we can
  86. //  calculate the scaling ratios.
  87. //
  88. void
  89. TList::ScaleTo(int newXmax, int newYmax)
  90. {
  91.   if (!Xmax || !Ymax) {    // at startup, Xmax and Ymax are zero
  92.     Xmax = newXmax;
  93.     Ymax = newYmax;
  94.     ResetLines();
  95.  
  96.   } else {
  97.     X1 = int(long(X1)*newXmax / Xmax);
  98.     Y1 = int(long(Y1)*newYmax / Ymax);
  99.     X2 = int(long(X2)*newXmax / Xmax);
  100.     Y2 = int(long(Y2)*newYmax / Ymax);
  101.     for (int i = 0; i < MaxLines; i++) {
  102.       Line[i].LX1 = int(long(Line[i].LX1)*newXmax / Xmax);
  103.       Line[i].LX2 = int(long(Line[i].LX2)*newXmax / Xmax);
  104.       Line[i].LY1 = int(long(Line[i].LY1)*newYmax / Ymax);
  105.       Line[i].LY2 = int(long(Line[i].LY2)*newYmax / Ymax);
  106.     }
  107.   }
  108.   Xmax = newXmax;
  109.   Ymax = newYmax;
  110. }
  111.  
  112. // The high-level Draw method of the object.
  113. //
  114. void
  115. TList::DrawLine(TDC& dc, int index)
  116. {
  117.   TPen pen(Line[index].Color);
  118.   dc.SelectObject(pen);
  119.   LineDraw(dc, Line[index].LX1, Line[index].LY1, 
  120.                Line[index].LX2, Line[index].LY2);
  121.   dc.RestorePen();
  122. }
  123.  
  124. // The high-level draw which erases a line.
  125. //
  126. void TList::EraseLine(TDC& dc, int index)
  127. {
  128.   dc.SelectStockObject(BLACK_PEN);
  129.   LineDraw(dc, Line[index].LX1, Line[index].LY1,
  130.                Line[index].LX2, Line[index].LY2);
  131. }
  132.  
  133. // Redraw all the lines in the array.
  134. //
  135. void
  136. TList::Redraw(TDC& dc)
  137. {
  138.   for (int i = 0; i < MaxLines; i++)
  139.     DrawLine(dc, i);
  140. }
  141.  
  142. // Reset the color counter and pick a random color.
  143. //
  144. void
  145. TList::SelectNewColor()
  146. {
  147.   ColorDuration = MaxColorDuration;
  148.   PenColor = TColor(random(256), random(256), random(256));
  149. }
  150.  
  151. // Pick random directional deltas and reset the delta counter.
  152. //
  153. void
  154. TList::SelectNewDeltaValues()
  155. {
  156.   DeltaX1 = random(MaxDelta) - MaxDelta/2;
  157.   DeltaX2 = random(MaxDelta) - MaxDelta/2;
  158.   DeltaY1 = random(MaxDelta) - MaxDelta/2;
  159.   DeltaY2 = random(MaxDelta) - MaxDelta/2;
  160.   IncrementCount = 2 * (1 + random(10));
  161. }
  162.  
  163. // Process the movement of one line.
  164. //
  165. void
  166. TList::LineTick(TDC& dc)
  167. {
  168.   EraseLine(dc, CurrentLine);
  169.   if (ColorDuration < 0)
  170.     SelectNewColor();
  171.   if (!IncrementCount)
  172.     SelectNewDeltaValues();
  173.   AdjustX(X1, DeltaX1);
  174.   AdjustX(X2, DeltaX2);
  175.   AdjustY(Y1, DeltaY1);
  176.   AdjustY(Y2, DeltaY2);
  177.  
  178.   Line[CurrentLine].LX1 = X1;
  179.   Line[CurrentLine].LX2 = X2;
  180.   Line[CurrentLine].LY1 = Y1;
  181.   Line[CurrentLine].LY2 = Y2;
  182.   Line[CurrentLine].Color = PenColor;
  183.  
  184.   DrawLine(dc, CurrentLine);
  185.   CurrentLine++;
  186.   if (CurrentLine >= MaxLines)
  187.     CurrentLine = 1;
  188.   ColorDuration--;
  189.   IncrementCount--;
  190. }
  191.  
  192.  
  193. //------------ TQuadList ----------------------------------------
  194.  
  195. // Draw the line and 3 reflections of it.
  196. //
  197. void
  198. TQuadList::DrawLine(TDC& dc, int index)
  199. {
  200.   TPen pen(Line[index].Color);
  201.   dc.SelectObject(pen);
  202.   LineDraw(dc, Line[index].LX1, Line[index].LY1,
  203.                Line[index].LX2, Line[index].LY2);
  204.   LineDraw(dc, Xmax - Line[index].LX1, Line[index].LY1,
  205.                Xmax - Line[index].LX2, Line[index].LY2);
  206.   LineDraw(dc, Line[index].LX1, Ymax - Line[index].LY1,
  207.                Line[index].LX2, Ymax - Line[index].LY2);
  208.   LineDraw(dc, Xmax - Line[index].LX1, Ymax - Line[index].LY1,
  209.                Xmax - Line[index].LX2, Ymax - Line[index].LY2);
  210.   dc.RestorePen();
  211. }
  212.  
  213. // Erase the line and 3 reflections of it.
  214. //
  215. void
  216. TQuadList::EraseLine(TDC& dc, int index)
  217. {
  218.   dc.SelectStockObject(BLACK_PEN);
  219.   LineDraw(dc, Line[index].LX1, Line[index].LY1,
  220.                Line[index].LX2, Line[index].LY2);
  221.   LineDraw(dc, Xmax - Line[index].LX1, Line[index].LY1,
  222.                Xmax - Line[index].LX2, Line[index].LY2);
  223.   LineDraw(dc, Line[index].LX1, Ymax - Line[index].LY1,
  224.                Line[index].LX2, Ymax - Line[index].LY2);
  225.   LineDraw(dc, Xmax - Line[index].LX1, Ymax - Line[index].LY1,
  226.                Xmax - Line[index].LX2, Ymax - Line[index].LY2);
  227. }
  228.  
  229. //----------- TArtyWindow ------------------------------------------
  230.  
  231. DEFINE_RESPONSE_TABLE1(TArtyWindow, TBaseDemoWindow)
  232.   EV_WM_LBUTTONDOWN,
  233.   EV_WM_RBUTTONDOWN,
  234.   EV_WM_SIZE,
  235. END_RESPONSE_TABLE;
  236.  
  237. IMPLEMENT_CASTABLE1(TArtyWindow, TBaseDemoWindow);
  238.  
  239. TArtyWindow::TArtyWindow() : TBaseDemoWindow()
  240. {
  241.   StaticControl = new TStatic(this, 100,
  242.     "Press Left Button to pause, Right Button to Clear",10,10,10,10,0);
  243.   Iconized = FALSE;
  244.   TextHeight = 20;
  245.   Paused = FALSE;
  246.  
  247.   // Initialize two line list objects:
  248.   //    BigLineList is the 4-reflection artwork that is displayed in
  249.   //    a full sized window.  Mouse clicks will pause or clear
  250.   //    the display, and the line list will be scaled to the
  251.   //    new window coordinates when the window is resized.
  252.   //
  253.   //    IconicLineList is a smaller list implementing a single-line
  254.   //    quark to display in the iconized window region.  Since
  255.   //    mouse clicks are not sent to iconized windows, the icon
  256.   //    cannot be paused or cleared, and since there is only one
  257.   //    icon window size, scaling the lines to new coordinates
  258.   //    has no visual effect.
  259.   //
  260.   //  The List pointer will be toggled between the two line list
  261.   //  objects: when the window is iconized, List will point to the
  262.   //  IconicLineList object.  When the window is restored to full
  263.   //  size, List will be made to point to the BigLineList object.
  264.   //  This is so the window routines don't have to know which kind
  265.   //  of list they're dealing with.  Keyword: polymorphism.
  266.  
  267.   BigLineList = new TQuadList(MaxLineCount);
  268.   IconicLineList = new TList(MaxIconicLineCount);
  269.   List = BigLineList;
  270.  
  271.   SetBkgndColor(TColor::Black);
  272. }
  273.  
  274. // Dispose of the objects that this window object created.  There's
  275. //  no need to dispose the List pointer, since it will only point to
  276. //  one of these two objects which are being disposed by their
  277. //  primary pointers
  278. //
  279. TArtyWindow::~TArtyWindow()
  280. {
  281.   delete BigLineList;
  282.   delete IconicLineList;
  283. }
  284.  
  285. // When the window is resized, scale the line list to fit the new
  286. //  window extent, or switch between full size and iconized window
  287. //  states.
  288. //
  289. void
  290. TArtyWindow::EvSize(UINT sizeType, TSize& size)
  291. {
  292.   TBaseDemoWindow::EvSize(sizeType, size);
  293.  
  294.   // Force Windows to repaint the entire window region
  295.   Invalidate(TRUE);
  296.  
  297.   int newXmax = size.cx;
  298.   int newYmax = size.cy;
  299.   if (sizeType == SIZE_MINIMIZED) {
  300.     if (!Iconized) {
  301.       Iconized = TRUE;
  302.       List = IconicLineList;
  303.     }
  304.  
  305.   } else {
  306.     if (Iconized) {
  307.       Iconized = FALSE;
  308.       List = BigLineList;
  309.     }
  310.     newYmax -= TextHeight;  // allow room for the text at the bottom
  311.   }
  312.  
  313.   List->ScaleTo(newXmax, newYmax);  // scale the lines in the list
  314.   if (StaticControl)
  315.     StaticControl->MoveWindow(0, newYmax, newXmax, TextHeight, TRUE);
  316. }
  317.  
  318. // Toggle the window's Paused status.  Since the window will
  319. //  not receive mouse clicks when iconized, this will not pause the
  320. //  iconized lines display.
  321. //
  322. void
  323. TArtyWindow::EvLButtonDown(UINT, TPoint&)
  324. {
  325.   Paused = !Paused;
  326. }
  327.  
  328. // Clear the line list when the user presses the right mouse
  329. //  button.  Same comments as above on iconized windows.
  330. //
  331. void
  332. TArtyWindow::EvRButtonDown(UINT, TPoint&)
  333. {
  334.   Invalidate(TRUE);
  335.   List->ResetLines();
  336. }
  337.  
  338. // When the window is resized, or some other window blots out part
  339. // of our client area, redraw the entire line list.
  340. //
  341. void
  342. TArtyWindow::Paint(TDC& dc, BOOL, TRect&)
  343. {
  344.   List->Redraw(dc);
  345. }
  346.  
  347. // Fetch a device context, pass it to the line list object, then
  348. // release the device context back to Windows.
  349. //
  350. void
  351. TArtyWindow::TimerTick()
  352. {
  353.   if (!Paused)
  354.     List->LineTick(TClientDC(Iconized ? Parent->HWindow : HWindow));
  355. }
  356.