home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c083 / 13.ddi / NOTEBOOK.PAK / VSCROLL.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-02  |  16.4 KB  |  556 lines

  1. //----------------------------------------------------------------------------
  2. //    vscroll.cpp - class for vscroll bar gadget (non-window based) 
  3. //----------------------------------------------------------------------------
  4. //    Copyright (c) 1993 Borland International
  5. //----------------------------------------------------------------------------
  6. #include <owl\owlpch.h>
  7. #include <owl\dc.h>
  8.  
  9. #include "utils.h"        // for debugging support
  10. #include "vscroll.h"
  11. //---------------------------------------------------------------------------- 
  12. TVScroll::TVScroll(TWindow *Parent, int x, int y, int width, int height, 
  13.     int idnum, int Lowval, int Highval, int initval, BOOL Frame3d, 
  14.     BOOL Arrowline, BOOL Thumbmove, int Repeatdelay)
  15. {
  16.   parent = Parent;
  17.   frame3d = Frame3d;
  18.   lastfocusyoff = -1;
  19.   arrowline = Arrowline;
  20.   thumbmove = Thumbmove;
  21.   repeatdelay = Repeatdelay;
  22.   showit = TRUE;
  23.   if (arrowline)
  24.     barsize = 1;
  25.   else
  26.     barsize = 2;
  27.  
  28.   BuildBrushes();
  29.   SetScrollRange(Lowval, Highval, FALSE);
  30.   SetScrollPos(initval, FALSE);
  31.  
  32.   mousedown = VSB_NOTDOWN;
  33.   displaystate = VSB_NOTDOWN;
  34.   mylongid = MAKELONG(0, idnum);
  35.   if (! idnum)
  36.     scrollmsg = WM_VSCROLL;
  37.   else
  38.     scrollmsg = NW_VSCROLL;
  39.  
  40.   ChangeRect(TRect(x, y, x+width, y+height), FALSE);
  41. }
  42. //----------------------------------------------------------------------------
  43. TVScroll::~TVScroll()
  44. {
  45.   DeleteBrushes();
  46. }
  47. //----------------------------------------------------------------------------
  48. void TVScroll::ShowScrollBar(BOOL show)
  49. {
  50.   showit = show;
  51. }
  52. //----------------------------------------------------------------------------
  53. void TVScroll::DeleteBrushes()
  54. {
  55.   delete framebrush;
  56.   delete trackbrush;
  57.   delete hilitebrush;
  58.   delete shadowbrush;
  59.   delete facebrush;
  60. }
  61. //----------------------------------------------------------------------------
  62. void TVScroll::BuildBrushes()
  63. {
  64.   framebrush = new TBrush(GetSysColor(COLOR_WINDOWFRAME));
  65.   trackbrush = new TBrush(GetSysColor(COLOR_SCROLLBAR));
  66.   hilitebrush = new TBrush(GetSysColor(COLOR_BTNHIGHLIGHT));
  67.   shadowbrush = new TBrush(GetSysColor(COLOR_BTNSHADOW));
  68.   facebrush = new TBrush(GetSysColor(COLOR_BTNFACE));
  69. }
  70. //----------------------------------------------------------------------------
  71. void TVScroll::SysColorChange()
  72. {
  73.   DeleteBrushes();
  74.   BuildBrushes();
  75. }
  76. //----------------------------------------------------------------------------
  77. void TVScroll::ChangeRect(TRect &newrect, BOOL repaint)
  78. {
  79.   int width = newrect.Width();
  80.   int height = newrect.Height();
  81.  
  82.   // set minimum sizes
  83.   if (height < 14)
  84.     height = 14;
  85.   if (width < 4)
  86.     width = 4;
  87.   framerect = TRect(newrect.left, newrect.top, newrect.left+width,
  88.     newrect.top+height);
  89.  
  90.   if (frame3d)        // will add 3d frame on outside
  91.     sbrect = framerect.InflatedBy(-1, -1);
  92.   else
  93.     sbrect = framerect;
  94.  
  95.   // compute a few measurements here to make our life easier 
  96.   sbheight = sbrect.bottom - sbrect.top;
  97.   sbwidth = sbrect.right - sbrect.left;
  98.   sqsize = sbwidth - 2;
  99.   trackheight = sbheight - 2*(sqsize+barsize);    // overlaps arrow lines
  100.   trange = trackheight - (sqsize+2);
  101.   trackyoff = sbrect.top + sqsize + barsize;    // start on 2nd left arrow bar
  102.  
  103.   SetScrollPos(curval, SV_NOREPAINT);
  104.  
  105.   if (repaint)
  106.     MyPaint(VSB_FORCEALL);
  107. }
  108. //----------------------------------------------------------------------------
  109. void TVScroll::ForcePaint()
  110. {
  111.   MyPaint(VSB_FORCEALL);
  112. }
  113. //----------------------------------------------------------------------------
  114. void TVScroll::DrawFrames(TDC &mydc)
  115. {
  116.   if (frame3d)            // outer 3d frame
  117.       DrawShadeFrame(mydc, framerect, FALSE);
  118.  
  119.   // draw inner frame (avoid flicker by not painting interrior)
  120.   mydc.FrameRect(sbrect, *framebrush);
  121.  
  122.   // draw single/double black lines for top and bottom buttons
  123.   mydc.SelectObject(*framebrush);
  124.   FASTRECT(mydc, sbrect.left, sbrect.top+sqsize+1, sbwidth, barsize);
  125.   FASTRECT(mydc, sbrect.left, sbrect.bottom-(sqsize+barsize+1), sbwidth, 
  126.     barsize);
  127. }
  128. //----------------------------------------------------------------------------
  129. void TVScroll::DrawTopArrow(TDC &mydc, BOOL isdown)
  130. {
  131.   TRect myrect(sbrect.left+1, sbrect.top+1, sbrect.left+sqsize+1,
  132.     sbrect.top+sqsize+1);
  133.   DrawArrowButton(mydc, myrect, isdown, TRUE);
  134. }
  135. //----------------------------------------------------------------------------
  136. void TVScroll::DrawBottomArrow(TDC &mydc, BOOL isdown)
  137. {
  138.   TRect myrect(sbrect.left+1, sbrect.bottom-(sqsize+1), 
  139.     sbrect.left+sqsize+1, sbrect.bottom-1);
  140.   DrawArrowButton(mydc, myrect, isdown, FALSE);
  141. }
  142. //----------------------------------------------------------------------------
  143. void TVScroll::DrawTopTrack(TDC &mydc, BOOL isdown)
  144. {
  145.   if (isdown)
  146.     mydc.SelectObject(*shadowbrush);
  147.   else
  148.     mydc.SelectObject(*trackbrush);
  149.   FASTRECT(mydc, sbrect.left+1, trackyoff, sbwidth-2, thumbyoff-trackyoff);
  150. }
  151. //----------------------------------------------------------------------------
  152. void TVScroll::DrawBottomTrack(TDC &mydc, BOOL isdown)
  153. {
  154.   int yoff = thumbyoff+sqsize+2;
  155.   int lasty = trackyoff + trackheight - 1;
  156.  
  157.   if (isdown)
  158.     mydc.SelectObject(*shadowbrush);
  159.   else
  160.     mydc.SelectObject(*trackbrush);
  161.   FASTRECT(mydc, sbrect.left+1, yoff, sbwidth-2, lasty-yoff+1);
  162. }
  163. //----------------------------------------------------------------------------
  164. void TVScroll::DrawThumb(TDC &mydc, BOOL drawfocus, BOOL erasefocus)
  165. {
  166.   if ((erasefocus) && (lastfocusyoff >= 0)) {
  167.     mydc.DrawFocusRect(sbrect.left, lastfocusyoff, sbrect.right,
  168.       lastfocusyoff+sqsize+2);
  169.   }
  170.  
  171.   if (drawfocus) {
  172.     mydc.DrawFocusRect(sbrect.left, thumbyoff, sbrect.left+sbwidth,
  173.         thumbyoff+sqsize+2);
  174.     lastfocusyoff = thumbyoff;
  175.     return;
  176.   }
  177.  
  178.   // draw thumb track (but don't cover two outside black lines)
  179.   mydc.SelectObject(*trackbrush);
  180.   FASTRECT(mydc, sbrect.left+1, trackyoff+1, sbwidth-2, trackheight-2);
  181.  
  182.   // draw black lines on each side of solid thumb
  183.   mydc.SelectObject(*framebrush);
  184.   FASTHLINE(mydc, sbrect.left, thumbyoff, sbwidth);
  185.   FASTHLINE(mydc, sbrect.left, thumbyoff+sqsize+1, sbwidth);
  186.  
  187.   // draw solid thumb
  188.   mydc.SelectObject(*facebrush);
  189.   FASTRECT(mydc, sbrect.left+1, thumbyoff+1, sqsize-2, sqsize-2);
  190.  
  191.   // draw shaded frame and extra "_|" design for solid thumb
  192.   TRect myrect(sbrect.left+1, thumbyoff+1, sbrect.right-1, 
  193.     thumbyoff+sqsize+1);
  194.   DrawShadeFrame(mydc, myrect, TRUE);
  195.  
  196.   lastfocusyoff = -1;
  197. }
  198. //----------------------------------------------------------------------------
  199. void TVScroll::DrawDownFrame(TDC &mydc, TRect &myrect)
  200. {
  201.   // always a single width shadow line
  202.   mydc.SelectObject(*shadowbrush);
  203.   FASTHLINE(mydc, myrect.left, myrect.top, myrect.right-myrect.left);
  204.   FASTVLINE(mydc, myrect.left, myrect.top, myrect.bottom-myrect.top);
  205. }
  206. //----------------------------------------------------------------------------
  207. void TVScroll::DrawShadeFrame(TDC &mydc, TRect &myrect, BOOL forthumb)
  208. {
  209.   int width = myrect.right - myrect.left;
  210.   int height = myrect.bottom - myrect.top;
  211.  
  212.   mydc.SelectObject(*hilitebrush);
  213.   FASTHLINE(mydc, myrect.left, myrect.top, width);
  214.   FASTVLINE(mydc, myrect.left, myrect.top, height);
  215.   if (sqsize > 15) {        // double highlight
  216.     FASTHLINE(mydc, myrect.left, myrect.top+1, width);
  217.     FASTVLINE(mydc, myrect.left+1, myrect.top, height);
  218.   }
  219.  
  220.   mydc.SelectObject(*shadowbrush);
  221.   FASTHLINE(mydc, myrect.left, myrect.bottom-1, width);
  222.   FASTVLINE(mydc, myrect.right-1, myrect.top, height);
  223.   if ((forthumb) || (sqsize >= 15)) {        // double shadow 
  224.     FASTHLINE(mydc, myrect.left+1, myrect.bottom-2, width-1);
  225.     FASTVLINE(mydc, myrect.right-2, myrect.top+1, height-1);
  226.   }
  227. }
  228. //---------------------------------------------------------------------------
  229. void TVScroll::DrawArrowButton(TDC &mydc, TRect brect, BOOL isdown, BOOL top)
  230. {
  231.   int xoff, yoff, width, height, downoff, aheight, awidth;
  232.   int lheight, lwidth, myheight, delta;
  233.  
  234.   // draw button background 
  235.   mydc.FillRect(brect, *facebrush);
  236.  
  237.   // draw frame around button
  238.   if (isdown)
  239.     DrawDownFrame(mydc, brect);
  240.   else
  241.     DrawShadeFrame(mydc, brect, FALSE);
  242.  
  243.   // calculations for drawing arrow line and head
  244.   width = brect.right - brect.left;
  245.   height = brect.bottom - brect.top;
  246.  
  247.   if (isdown)
  248.     downoff = 1;
  249.   else
  250.     downoff = 0;
  251.  
  252.   mydc.SelectObject(*framebrush);    // for drawing arrows
  253.  
  254.   awidth = 2 + (width+1)/3;
  255.   if (! (awidth%2))        // need an odd numbered arrow width
  256.     awidth--;
  257.   aheight = (awidth+1)/2;
  258.   if (arrowline)
  259.     lheight = aheight-1;
  260.   else
  261.     lheight = 0;
  262.  
  263.   myheight = aheight + lheight;
  264.   delta = height - myheight;
  265.   yoff = brect.top + delta/2;        // where whole object should start
  266.   if (delta%2)    // odd number - put extra space on left
  267.     yoff++;
  268.  
  269.   if (arrowline) {        // draw arrow line
  270.     if (top)
  271.         yoff += aheight;        // yoff is now where line starts
  272.     lwidth = (awidth+2)/3;
  273.     xoff = brect.left + (width/2 - lwidth/2);
  274.     FASTRECT(mydc, xoff+downoff, yoff+downoff, lwidth, lheight);
  275.     if (top)
  276.         yoff--;
  277.     else
  278.         yoff += lheight;
  279.     } else if (top)
  280.       yoff += (aheight-1);
  281.  
  282.   // yoff is now where back line of arrow should be drawn
  283.   xoff = brect.left + (width/2 - awidth/2);
  284.  
  285.   // draw arrow head
  286.   while (awidth > 0) {
  287.     FASTHLINE(mydc, xoff+downoff, yoff+downoff, awidth);
  288.     awidth -= 2;
  289.     if (top)
  290.         yoff--;
  291.     else
  292.         yoff++;
  293.     xoff++;
  294.     }
  295. }
  296. //---------------------------------------------------------------------------
  297. void TVScroll::MyPaint(int newstate)
  298. {
  299.   if ((! parent->HWindow) || (parent->IsIconic()) || (! showit))
  300.     return;
  301.  
  302.   BOOL forceall = (newstate == VSB_FORCEALL);
  303.  
  304.   if ((! forceall) && (newstate == displaystate) && 
  305.     (newstate <= VSB_BOTTOMTHUMB))
  306.     return;            // already drawn
  307.  
  308.   BOOL dotop = (displaystate==VSB_TOPARROW) || (newstate==VSB_TOPARROW);
  309.   BOOL dobottom = (displaystate==VSB_BOTTOMARROW) || 
  310.     (newstate==VSB_BOTTOMARROW);
  311.   BOOL dothumb = (displaystate>=VSB_TOPTHUMB) || (newstate>=VSB_TOPTHUMB);
  312.  
  313.   if (newstate <= VSB_BOTTOMTHUMB)
  314.     displaystate = newstate;
  315.  
  316.   TWindowDC mydc(*parent);
  317.  
  318.   if (forceall)
  319.     DrawFrames(mydc);
  320.  
  321.   if ((forceall) || (dotop))
  322.     DrawTopArrow(mydc, (displaystate==VSB_TOPARROW));
  323.   
  324.   if ((forceall) || (dobottom))
  325.     DrawBottomArrow(mydc, (displaystate==VSB_BOTTOMARROW));
  326.   
  327.   if ((forceall) || (dothumb)) {
  328.     DrawThumb(mydc, (displaystate==VSB_THUMBFOCUS), 
  329.         (displaystate==VSB_THUMBFOCUS));
  330.     if (displaystate == VSB_TOPTHUMB)        // gray to top of thumb
  331.         DrawTopTrack(mydc, TRUE);
  332.     else if (displaystate == VSB_BOTTOMTHUMB)    // gray to right of thumb
  333.         DrawBottomTrack(mydc, TRUE);
  334.   }
  335. }
  336. //----------------------------------------------------------------------------
  337. int TVScroll::GetScrollPos()
  338. {
  339.   return(curval);
  340. }
  341. //----------------------------------------------------------------------------
  342. void TVScroll::GetScrollRange(int &low, int &high)
  343. {
  344.   low = lowval;
  345.   high = highval;
  346. }
  347. //----------------------------------------------------------------------------
  348. int TVScroll::SetScrollPos(int newval, int repaint)
  349. {
  350.   int oldval = curval;
  351.   curval = min(max(newval, lowval), highval);
  352.  
  353.   // reposition thumb to match new value
  354.   thumbyoff = (int)(trackyoff + ((LONG)trange*(curval-lowval))/vrange);
  355.  
  356.   if (repaint == SV_REPAINT)
  357.     MyPaint(VSB_THUMB);
  358.   else if (repaint == SV_THUMBTRACK)
  359.     MyPaint(thumbmove ? VSB_THUMB : VSB_THUMBFOCUS);
  360.  
  361.   return(oldval);
  362. }
  363. //----------------------------------------------------------------------------
  364. void TVScroll::SetScrollRange(int Lowval, int Highval, BOOL redraw)
  365. {
  366.   lowval = Lowval;
  367.   highval = Highval;
  368.   if (highval <= lowval)
  369.     highval = lowval + 1;
  370.   vrange = highval - lowval;
  371.  
  372.   if (redraw)
  373.     MyPaint(VSB_FORCEALL);
  374. }
  375. //----------------------------------------------------------------------------
  376. int TVScroll::GetMouseLoc(TPoint &winpt)
  377. {
  378.   if ((parent->IsIconic()) || (! sbrect.Contains(winpt)) || (! showit)) 
  379.     return(VSB_NOTDOWN);
  380.  
  381.   int myy = winpt.y;
  382.   int top = sbrect.top;
  383.  
  384.   if (myy < top+sqsize+2)
  385.     return(VSB_TOPARROW);
  386.   if (myy > (top+sqsize+2+trackheight))
  387.     return(VSB_BOTTOMARROW);
  388.   if (myy < thumbyoff)
  389.     return(VSB_TOPTHUMB);
  390.   if (myy > thumbyoff+sqsize+2)
  391.     return(VSB_BOTTOMTHUMB);
  392.   return(VSB_THUMB);
  393. }
  394. //----------------------------------------------------------------------------
  395. BOOL TVScroll::MyLButtonDown(UINT /*hitTest*/, TPoint& winpt)
  396. {
  397.   mousedown = GetMouseLoc(winpt);
  398.   if (mousedown == VSB_NOTDOWN)    // mousedown not in scrollbar
  399.     return(FALSE);
  400.  
  401.   origval = curval;
  402.   newloc = mousedown;
  403.  
  404.   switch (mousedown) {
  405.     case VSB_TOPARROW:
  406.     case VSB_BOTTOMARROW:
  407.         MyPaint(mousedown);
  408.         break;
  409.  
  410.     case VSB_TOPTHUMB:
  411.          MyPaint(mousedown);
  412.         parent->SendMessage(scrollmsg, SB_PAGEUP, mylongid);
  413.         break;
  414.  
  415.     case VSB_BOTTOMTHUMB:
  416.         MyPaint(mousedown);
  417.         parent->SendMessage(scrollmsg, SB_PAGEDOWN, mylongid);
  418.         break;
  419.  
  420.     case VSB_THUMB:
  421.         thumbgrabyoff = winpt.y - thumbyoff;
  422.         SetScrollPos(curval, SV_THUMBTRACK);
  423.   }
  424.  
  425.   AutoScrollMouse();
  426.  
  427.   return(TRUE);
  428. }
  429. //----------------------------------------------------------------------------
  430. BOOL TVScroll::MyMouseMove(UINT /*hitTest*/, TPoint& winpt)
  431. {
  432.   if (mousedown == VSB_NOTDOWN)    // mousedown was not in our scrollbar
  433.     return(FALSE);
  434.  
  435.   newloc = GetMouseLoc(winpt);
  436.  
  437.   switch (mousedown){
  438.     case VSB_TOPARROW:
  439.     case VSB_BOTTOMARROW:
  440.     case VSB_TOPTHUMB:
  441.     case VSB_BOTTOMTHUMB:
  442.         if (newloc == mousedown)
  443.           MyPaint(mousedown);
  444.         else
  445.           MyPaint(VSB_NOTDOWN);
  446.         break;
  447.  
  448.     case VSB_THUMB:
  449.         if (newloc != VSB_NOTDOWN){        // anywhere inside sb
  450.           int newpos = (winpt.y - thumbgrabyoff) - trackyoff;
  451.           if (newpos < 0)
  452.               newpos = 0;
  453.           else if (newpos > trange)
  454.               newpos = trange;
  455.           int newval = (int)(lowval + ((LONG)vrange*newpos)/trange);
  456.           SetScrollPos(newval, SV_THUMBTRACK);
  457.           parent->SendMessage(scrollmsg, SB_THUMBTRACK, 
  458.               mylongid | newval);
  459.         } else {
  460.           SetScrollPos(origval, SV_THUMBTRACK);
  461.           parent->SendMessage(scrollmsg, SB_THUMBTRACK, 
  462.               mylongid | origval);
  463.         }
  464.         break;
  465.   }
  466.   return(TRUE);
  467. }
  468. //----------------------------------------------------------------------------
  469. BOOL TVScroll::MyLButtonUp(UINT /*hitTest*/, TPoint& winpt)
  470. {
  471.   int sendval;
  472.  
  473.   if (mousedown == VSB_NOTDOWN)    // mousedown was not in our scrollbar
  474.     return(FALSE);
  475.  
  476.   newloc = GetMouseLoc(winpt);
  477.  
  478.   switch (mousedown) {
  479.     case VSB_TOPARROW:
  480.         MyPaint(VSB_NOTDOWN);
  481.         if (newloc == mousedown)
  482.           parent->SendMessage(scrollmsg, SB_LINEUP, mylongid);
  483.         break;
  484.  
  485.     case VSB_BOTTOMARROW:
  486.         MyPaint(VSB_NOTDOWN);
  487.         if (newloc == mousedown)
  488.           parent->SendMessage(scrollmsg, SB_LINEDOWN, mylongid);
  489.         break;
  490.  
  491.     case VSB_THUMB:
  492.         sendval = curval;        // save off before overwritting
  493.         SetScrollPos(origval, SV_REPAINT);
  494.         parent->SendMessage(scrollmsg, SB_THUMBPOSITION, 
  495.           mylongid | sendval);
  496.         break;
  497.     
  498.     default:
  499.         MyPaint(VSB_NOTDOWN);
  500.         break;
  501.   }
  502.  
  503.   parent->SendMessage(scrollmsg, SB_ENDSCROLL, mylongid);
  504.   mousedown = VSB_NOTDOWN;
  505.   return(TRUE);
  506. }
  507. //----------------------------------------------------------------------------
  508. void TVScroll::AutoScrollMouse()
  509. {
  510.   MSG  loopMsg;
  511.   DWORD delayticks;
  512.  
  513.   loopMsg.message = 0;
  514.   parent->SetCapture();
  515.   
  516.   delayticks = repeatdelay + GetTickCount();    
  517.  
  518.   while (loopMsg.message != WM_LBUTTONUP && 
  519.     (loopMsg.message != WM_MOUSEMOVE ||(loopMsg.wParam&MK_LBUTTON))) {
  520.     if (::PeekMessage(&loopMsg, 0, 0, 0, PM_REMOVE)) {
  521.       ::TranslateMessage(&loopMsg);
  522.       ::DispatchMessage(&loopMsg);
  523.     }
  524.     if (GetTickCount() > delayticks)
  525.         AutoScrollAction();
  526.   }
  527.  
  528.   parent->ReleaseCapture();
  529. }
  530. //----------------------------------------------------------------------------
  531. void TVScroll::AutoScrollAction()
  532. {
  533.   if (newloc != mousedown)
  534.       return;
  535.  
  536.   switch (mousedown){
  537.       case VSB_TOPARROW:
  538.         parent->SendMessage(scrollmsg, SB_LINEUP, mylongid);
  539.         break;
  540.  
  541.       case VSB_BOTTOMARROW:
  542.         parent->SendMessage(scrollmsg, SB_LINEDOWN, mylongid);
  543.         break;
  544.  
  545.       case VSB_TOPTHUMB:
  546.         parent->SendMessage(scrollmsg, SB_PAGEUP, mylongid);
  547.         break;
  548.  
  549.       case VSB_BOTTOMTHUMB:
  550.         parent->SendMessage(scrollmsg, SB_PAGEDOWN, mylongid);
  551.         break;
  552.   }
  553. }
  554. //----------------------------------------------------------------------------
  555.  
  556.