home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 May / Pcwk5b98.iso / Borland / Cplus45 / BC45 / OWL1.PAK / SCROLLER.CPP < prev    next >
Text File  |  1995-08-29  |  9KB  |  327 lines

  1. // ObjectWindows - (C) Copyright 1992 by Borland International
  2.  
  3. /* --------------------------------------------------------
  4.   SCROLLER.CPP
  5.   Defines type TScroller.
  6.   -------------------------------------------------------- */
  7.  
  8. #include "applicat.h"
  9. #include "window.h"
  10.  
  11. #define max(a,b)(((a) >(b)) ?(a) :(b))
  12. #define min(a,b)(((a) <(b)) ?(a) :(b))
  13. #define abs(a)  (((a) >= 0)  ?(a) :-(a))
  14.  
  15. hashValueType TScroller::ClassHashValue = 0;
  16.  
  17. /* Constructs a TScroller object, initializing its data fields to
  18.    default values. */
  19. TScroller::TScroller(PTWindow TheWindow,int TheXUnit, int TheYUnit, long TheXRange, long TheYRange)
  20. {
  21.   Window = TheWindow;
  22.   XPos = YPos = 0;
  23.   XUnit = TheXUnit;
  24.   YUnit = TheYUnit;
  25.   XRange = TheXRange;
  26.   YRange = TheYRange;
  27.   XLine = 1;  YLine = 1;
  28.   XPage = 1;  YPage = 1;
  29.   AutoMode = TRUE;
  30.   TrackMode = TRUE;
  31.   AutoOrg = TRUE;
  32.   HasHScrollBar = (Window &&
  33.           ((Window->Attr.Style & WS_HSCROLL) == WS_HSCROLL));
  34.   HasVScrollBar = (Window &&
  35.           ((Window->Attr.Style & WS_VSCROLL) == WS_VSCROLL));
  36.   InstanceHashValue = ClassHashValue++;
  37. }
  38.  
  39. /* Destructs a TScroller object. Sets Window's Scroller member to NULL */
  40. TScroller::~TScroller()
  41. {
  42.   if ( Window && Window->Scroller )
  43.     Window->Scroller = NULL;
  44. }
  45.  
  46. /* Sets the number of units per page (amount by which to scroll on
  47.    a page scroll request) according to the current size of the
  48.    Window's client area. */
  49. void TScroller::SetPageSize()
  50. {
  51.   RECT ClientRect;
  52.   int Width, Height;
  53.  
  54.   if ( Window )
  55.   {
  56.     GetClientRect(Window->HWindow, &ClientRect);
  57.     Width = ClientRect.right - ClientRect.left;
  58.     Height = ClientRect.bottom - ClientRect.top;
  59.     if ( (Width != 0) && (XUnit > 0) )
  60.       XPage = max(1, ((Width+1)/XUnit) -1);
  61.     if ( (Height != 0) && (YUnit > 0) )
  62.       YPage = max(1, ((Height+1)/YUnit) -1);
  63.   }
  64. }
  65.  
  66. /* Sets the range of the TScroller and also sets the range of
  67.    its Window's scrollbars. */
  68. void TScroller::SetRange(long TheXRange, long TheYRange)
  69. {
  70.   XRange = TheXRange;
  71.   YRange = TheYRange;
  72.   SetSBarRange();
  73.   ScrollTo(XPos, YPos);
  74. }
  75.  
  76. /* Resets the X and Y scroll unit size (in device units) to the passed
  77.   parameters.  Calls SetPageSize to update the X and Y page size, which
  78.   are specified in scroll units. */
  79. void TScroller::SetUnits(int TheXUnit, int TheYUnit)
  80. {
  81.   XUnit = TheXUnit;
  82.   YUnit = TheYUnit;
  83.   SetPageSize();
  84. }
  85.  
  86. /* Sets the range of the Window's scrollbars. */
  87. void TScroller::SetSBarRange()
  88. {
  89.   if ( Window )
  90.   {
  91.     if ( HasHScrollBar )
  92.         SetScrollRange(Window->HWindow, SB_HORZ, 0,
  93.                        max(0, (int)min(XRange, MaxInt)), FALSE);
  94.     if ( HasVScrollBar )
  95.         SetScrollRange(Window->HWindow, SB_VERT, 0,
  96.                        max(0, (int)min(YRange, MaxInt)), FALSE);
  97.   }
  98. }
  99.  
  100. /* Sets the origin for the paint display context according to
  101.    XPos, YPos. */
  102.  
  103. inline void TScroller::__BeginView(HDC PaintDC, PAINTSTRUCT&)
  104. {
  105.   long XOrg, YOrg;
  106.  
  107.   XOrg = XPos * XUnit;
  108.   YOrg = YPos * YUnit;
  109.   if ( AutoOrg && (XOrg <= MaxInt) && (YOrg <= MaxInt) )
  110.     SetViewportOrg(PaintDC, (int)-XOrg, (int)-YOrg);
  111. }
  112.  
  113. #if  defined(WIN31)
  114. void TScroller::BeginView(HDC PaintDC, PAINTSTRUCT&)
  115. {
  116.   PAINTSTRUCT ps_tmp;
  117.   __BeginView(PaintDC, ps_tmp);
  118. }
  119. #endif
  120. #if  defined(WIN30)
  121. void TScroller::BeginView(HDC_30 PaintDC, PAINTSTRUCT&)
  122. {
  123.   PAINTSTRUCT ps_tmp;    
  124.   __BeginView( HDC( PaintDC ), ps_tmp);
  125. }
  126. #endif
  127.  
  128. /* Updates the position of the Window's scrollbar(s). */
  129. void TScroller::EndView()
  130. {
  131.   int TempPos;
  132.  
  133.   if ( Window )
  134.   {
  135.     if ( HasHScrollBar )
  136.     {
  137.       if ( XRange > MaxInt )
  138.         TempPos = XScrollValue(XPos);
  139.       else
  140.         TempPos = (int)XPos;
  141.       if ( GetScrollPos(Window->HWindow, SB_HORZ) != TempPos )
  142.         SetScrollPos(Window->HWindow, SB_HORZ, TempPos, TRUE);
  143.     }
  144.     if ( HasVScrollBar )
  145.     {
  146.       if ( YRange > MaxInt )
  147.         TempPos = YScrollValue(YPos);
  148.       else
  149.         TempPos = (int)YPos;
  150.       if ( GetScrollPos(Window->HWindow, SB_VERT) != TempPos )
  151.         SetScrollPos(Window->HWindow, SB_VERT, TempPos, TRUE);
  152.     }
  153.   }
  154. }
  155.  
  156. /* Scrolls vertically according to scroll action and thumb position. */
  157. void TScroller::VScroll(WORD ScrollEvent, int ThumbPos)
  158. {
  159.   switch (ScrollEvent) {
  160.     case SB_LINEDOWN : ScrollBy(0, YLine);
  161.                        break;
  162.     case SB_LINEUP   : ScrollBy(0, -YLine);
  163.                        break;
  164.     case SB_PAGEDOWN : ScrollBy(0, YPage);
  165.                        break;
  166.     case SB_PAGEUP   : ScrollBy(0, -YPage);
  167.                        break;
  168.     case SB_TOP      : ScrollTo(XPos, 0);
  169.                        break;
  170.     case SB_BOTTOM   : ScrollTo(XPos, YRange);
  171.                        break;
  172.  
  173.     case SB_THUMBPOSITION :
  174.       if ( YRange > MaxInt )
  175.         ScrollTo(XPos, YRangeValue(ThumbPos));
  176.       else
  177.         ScrollTo(XPos, ThumbPos);
  178.       break;
  179.     case SB_THUMBTRACK :
  180.       if ( TrackMode )
  181.         if ( YRange > MaxInt )
  182.           ScrollTo(XPos, YRangeValue(ThumbPos));
  183.         else
  184.           ScrollTo(XPos, ThumbPos);
  185.       if ( Window && HasVScrollBar )
  186.         SetScrollPos(Window->HWindow, SB_VERT, ThumbPos, TRUE);
  187.       break;
  188.   }  // switch
  189. }
  190.  
  191. /* Scrolls horizontally according to scroll action and thumb
  192.    position. */
  193. void TScroller::HScroll(WORD ScrollEvent, int ThumbPos)
  194. {
  195.   switch (ScrollEvent) {
  196.     case SB_LINEDOWN : ScrollBy(XLine, 0);
  197.                        break;
  198.     case SB_LINEUP : ScrollBy(-XLine, 0);
  199.                      break;
  200.     case SB_PAGEDOWN : ScrollBy(XPage, 0);
  201.                        break;
  202.     case SB_PAGEUP : ScrollBy(-XPage, 0);
  203.                      break;
  204.  
  205.     case SB_TOP      : ScrollTo(0, YPos);
  206.                        break;
  207.     case SB_BOTTOM   : ScrollTo(XRange, YPos);
  208.                        break;
  209.  
  210.     case SB_THUMBPOSITION :
  211.       if ( XRange > MaxInt )
  212.         ScrollTo(XRangeValue(ThumbPos), YPos);
  213.       else
  214.         ScrollTo(ThumbPos, YPos);
  215.       break;
  216.     case SB_THUMBTRACK :
  217.         if ( TrackMode )
  218.           if ( XRange > MaxInt )
  219.             ScrollTo(XRangeValue(ThumbPos), YPos);
  220.           else
  221.             ScrollTo(ThumbPos, YPos);
  222.         if ( (Window) && HasHScrollBar )
  223.           SetScrollPos(Window->HWindow, SB_HORZ, ThumbPos, TRUE);
  224.         break;
  225.   }  // switch
  226. }
  227.  
  228. /* Scrolls to an (X,Y) position, after checking boundary conditions.
  229.    Causes a WMPaint message to be sent.  First scrolls the contents
  230.    of the client area, if a portion of the client area will
  231.    remain visible. */
  232. void TScroller::ScrollTo(long X, long Y)
  233. {
  234.   long NewXPos , NewYPos;
  235.  
  236.   if ( Window )
  237.   {
  238.     NewXPos = max(0, min(X, XRange));
  239.     NewYPos = max(0, min(Y, YRange));
  240.     if ( (NewXPos != XPos) || (NewYPos != YPos) )
  241.     {
  242.     /* Scaling is not needed here. If condition is met, ScrollWindow()
  243.        will succeed since XPage and YPage are ints. If condition is not
  244.        met, ScrollWindow() is called in EndScroll() as a result of calling
  245.        UpdateWindow(). EndScroll() performs the necessary scaling.
  246.     */
  247.       if ( AutoOrg || (abs(YPos - NewYPos) < YPage) &&
  248.                       (abs(XPos - NewXPos) < XPage) )
  249.         ScrollWindow(Window->HWindow, (int)((XPos-NewXPos)*XUnit),
  250.                           (int)((YPos-NewYPos)*YUnit), NULL, NULL);
  251.       else
  252.         InvalidateRect(Window->HWindow, NULL, TRUE);
  253.       XPos = NewXPos;
  254.       YPos = NewYPos;
  255.       UpdateWindow(Window->HWindow);
  256.     }
  257.   }
  258. }
  259.  
  260. /* Performs "auto-scrolling".  (Dragging the mouse from within the
  261.    client area of the Window to without results in auto-scrolling
  262.    when the AutoMode data member of the Scroller is TRUE). */
  263. void TScroller::AutoScroll()
  264. {
  265.   POINT CursorPos;
  266.   RECT ClientRect;
  267.   long Dx , Dy;
  268.  
  269.   if ( AutoMode && Window )
  270.   {
  271.     GetCursorPos(&CursorPos);
  272.     ScreenToClient(Window->HWindow, &CursorPos);
  273.     GetClientRect(Window->HWindow, &ClientRect);
  274.     Dx = 0; Dy = 0;
  275.     if ( CursorPos.y < 0 )
  276.       Dy = min(-YLine, max(-YPage, (CursorPos.y/10) * YLine));
  277.     else
  278.       if ( CursorPos.y > ClientRect.bottom )
  279.         Dy = max(YLine, min(YPage,
  280.                      ((CursorPos.y - ClientRect.bottom)/10) * YLine));
  281.     if ( CursorPos.x < 0 )
  282.       Dx = min(-XLine, max(-XPage, (CursorPos.x/10) * XLine));
  283.     else
  284.       if ( CursorPos.x > ClientRect.right )
  285.         Dx = max(XLine, min(XPage, ((CursorPos.x - ClientRect.right)/10) * XLine));
  286.     ScrollBy(Dx, Dy);
  287.   }
  288. }
  289.  
  290. /* Reads an instance of TScroller from the passed ipstream. */
  291. void *TScroller::read(ipstream& is)
  292. {
  293.   is >> XPos >> YPos
  294.      >> XUnit >> YUnit
  295.      >> XRange >> YRange
  296.      >> XLine >> YLine
  297.      >> XPage >> YPage
  298.      >> AutoMode >> TrackMode
  299.      >> AutoOrg
  300.      >> HasHScrollBar >> HasVScrollBar;
  301.   Window = NULL;
  302.   InstanceHashValue = ClassHashValue++;
  303.   return this;
  304. }
  305.  
  306. /* Writes the TScroller to the passed opstream. */
  307. void TScroller::write(opstream& os)
  308. {
  309.   os << XPos << YPos
  310.      << XUnit << YUnit
  311.      << XRange << YRange
  312.      << XLine << YLine
  313.      << XPage << YPage
  314.      << AutoMode << TrackMode
  315.      << AutoOrg
  316.      << HasHScrollBar << HasVScrollBar;
  317. }
  318.  
  319. TStreamable *TScroller::build()
  320. {
  321.   return new TScroller(streamableInit);
  322. }
  323.  
  324. TStreamableClass RegScroller("TScroller", TScroller::build,
  325.                  __DELTA(TScroller));
  326.  
  327.