home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / owlsrc.pak / SLIDER.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-24  |  9.9 KB  |  457 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // (C) Copyright 1993, 1994 by Borland International, All Rights Reserved
  4. //
  5. //   Implementation of TSlider, slider UI widget abstract base class.
  6. //----------------------------------------------------------------------------
  7. #pragma hdrignore SECTION
  8. #include <owl/owlpch.h>
  9. #include <owl/slider.h>
  10. #include <owl/dc.h>
  11.  
  12. #if !defined(SECTION) || SECTION == 1
  13.  
  14. DEFINE_RESPONSE_TABLE1(TSlider, TScrollBar)
  15.   EV_WM_SIZE,
  16.   EV_WM_GETDLGCODE,
  17.   EV_WM_ERASEBKGND,
  18.   EV_WM_PAINT,
  19.   EV_WM_LBUTTONDOWN,
  20.   EV_WM_MOUSEMOVE,
  21.   EV_WM_LBUTTONUP,
  22.   EV_WM_LBUTTONDBLCLK,
  23.   EV_WM_KEYDOWN,
  24.   EV_WM_SETFOCUS,
  25.   EV_WM_KILLFOCUS,
  26. END_RESPONSE_TABLE;
  27.  
  28. TSize  TSlider::MouseOffset;
  29. TDC*   TSlider::SlideDC = 0;
  30.  
  31. //
  32. // Constructor for a TSlider object
  33. //
  34. TSlider::TSlider(TWindow*        parent,
  35.                  int             id,
  36.                  int x, int y, int w, int h,
  37.                  TResId          thumbResId,
  38.                  TModule*        module)
  39. :
  40.   TScrollBar(parent, id, x, y, w, h, true, module),
  41.   ThumbResId(thumbResId),
  42.   ThumbRect(0, 0, 9, 20),
  43.   CaretRect(3, 3, 3+3, 3+13)
  44. {
  45.   SetRange(0, 100);
  46.   Pos = 0;
  47.   ThumbRgn = 0;
  48.   TicGap = Range/10;
  49.   SlotThick = 17;
  50.   Snap = true;
  51.  
  52.   Sliding = false;
  53.   
  54.   // get slot size from Attr.H set by TScrollBar ?
  55.  
  56.   Attr.W = w;
  57.   Attr.H = h;
  58. }
  59.  
  60. //
  61. //
  62. //
  63. TSlider::~TSlider()
  64. {
  65.   delete ThumbRgn;
  66. }
  67.  
  68. //
  69. // Setup slider window
  70. //
  71. void
  72. TSlider::SetupWindow()
  73. {
  74.   TScrollBar::SetupWindow();
  75.   SetupThumbRgn();
  76. }
  77.  
  78. //
  79. // Check & set the slider range
  80. //
  81. void
  82. TSlider::SetRange(int min, int max) 
  83. {
  84.   Min = min;
  85.   Max = max;
  86.   if (Max > Min)
  87.     Range = Max - Min;
  88.   else if (Min > Max)
  89.     Range = Min - Max;
  90.   else
  91.     Range = 1;
  92. }
  93.  
  94. //
  95. // Set the position of the thumb
  96. //
  97. void
  98. TSlider::SetPosition(int pos)
  99. {
  100.   //
  101.   // constrain pos to be in the range "Min .. Max" & snap to tics if enabled
  102.   //
  103.   pos = SnapPos(pos);
  104.  
  105.   //
  106.   // Slide thumb to new position, converting pos to pixels
  107.   //
  108.   if (pos != Pos) {
  109.     if (HWindow) {
  110.       TDC* dc = SlideDC ? SlideDC : new TClientDC(HWindow);
  111.       SlideThumb(*dc, pos);
  112.       if (!SlideDC)
  113.         delete dc;
  114.     }
  115.     Pos = pos;
  116.   }
  117. }
  118.  
  119. //
  120. // setup region that defines the thumb shape for this slider class.
  121. // default region is a simple bounding rect, but could be any shape.
  122. //
  123. void
  124. TSlider::SetupThumbRgn()
  125. {
  126.   if (!ThumbRgn)
  127.     ThumbRgn = new TRegion(ThumbRect);
  128. }
  129.  
  130. //
  131. // Slide the thumb & perform necessary blitting & painting.
  132. // Assumes that Pos, Min & Max are up to date.
  133. //
  134. void
  135. TSlider::SlideThumb(TDC& dc, int pos)
  136. {
  137.   TPoint point = PosToPoint(pos);
  138.  
  139.   HideCaret();
  140.   GetBkColor(dc);
  141.   if (ThumbRgn) {
  142.     TRegion  oldRgn(ThumbRect);
  143.     TRect    newThumbRect(point, ThumbRect.Size());
  144.  
  145.     *ThumbRgn += point-ThumbRect.TopLeft();
  146.   
  147.     dc.SelectClipRgn(*ThumbRgn);
  148.     dc.BitBlt(newThumbRect, dc, ThumbRect.TopLeft());
  149.  
  150.     ThumbRect = newThumbRect;
  151.  
  152.     oldRgn -= *ThumbRgn;
  153.     dc.SelectClipRgn(oldRgn);
  154.     PaintSlot(dc);
  155.   }
  156.   else {
  157.     ThumbRect = TRect(point, ThumbRect.Size());
  158.     PaintSlot(dc);
  159.     PaintThumb(dc);
  160.   }
  161.   SetCaretPos(ThumbRect.left+CaretRect.left, ThumbRect.top+CaretRect.top);
  162.   ShowCaret();
  163. }
  164.  
  165. //
  166. // Paint the thumb itself using a resource DIB translated to the current system
  167. // button colors. Overlaps the slot.
  168. //
  169. void
  170. TSlider::PaintThumb(TDC& dc)
  171. {
  172.   TDib  thumbDib(*GetModule(), ThumbResId);
  173.   thumbDib.MapUIColors(
  174.     TDib::MapFace|TDib::MapText|TDib::MapShadow|TDib::MapHighlight,
  175.     &dc.GetBkColor()
  176.   );
  177.   int  dibX = (Sliding || !IsWindowEnabled()) ? thumbDib.Width()/2 : 0;
  178.   dc.SetDIBitsToDevice(ThumbRect, TPoint(dibX, 0), thumbDib);
  179. }
  180.  
  181. //
  182. // Constrain pos to be in the range "Min .. Max" &
  183. // perform 'Snap'ing if enabled by rounding pos to nearest TicGap
  184. //
  185. int
  186. TSlider::SnapPos(int pos)
  187. {
  188.   if (pos > Max)
  189.     pos = Max;
  190.  
  191.   else if (pos < Min)
  192.     pos = Min;
  193.  
  194.   return Snap ? (((pos-Min)+TicGap/2)/TicGap)*TicGap + Min : pos;
  195. }
  196.  
  197. //
  198. // Get & release a brush obtained from our parent window for use in painting 
  199. // background areas in this control.
  200. //
  201. void
  202. TSlider::GetBkColor(TDC& dc)
  203. {
  204. #if defined(BI_PLAT_WIN32)
  205.   Parent->HandleMessage(WM_CTLCOLORSTATIC,
  206.                         (WPARAM)(HDC)dc,
  207.                         LPARAM(HWindow));
  208. #else
  209.   Parent->HandleMessage(WM_CTLCOLOR, 
  210.                         (WPARAM)(HDC)dc,
  211.                         MAKELPARAM(HWindow, CTLCOLOR_STATIC));
  212. #endif  
  213.   BkColor = dc.GetBkColor();
  214. }
  215.  
  216. //
  217. // 
  218. //
  219. void
  220. TSlider::EvSize(uint sizeType, TSize& size)
  221. {
  222.   TScrollBar::EvSize(sizeType, size);
  223. }
  224.  
  225. //
  226. // Make sure we get cursor movement keys to move the thumb
  227. //
  228. uint
  229. TSlider::EvGetDlgCode(MSG far*)
  230. {
  231.   return DLGC_WANTARROWS;
  232. }
  233.  
  234. //
  235. // Paint the whole slider: ruler, slot & thumb
  236. //
  237. void
  238. TSlider::EvPaint()
  239. {
  240.   HideCaret();
  241.   if (ThumbRgn) {                   // use thumb region if avalable
  242.     TRegion updateRgn;
  243.     GetUpdateRgn(updateRgn);
  244.  
  245.     TPaintDC  dc(*this);
  246.  
  247.     GetBkColor(dc);
  248.  
  249.     TRegion thumbClip = *ThumbRgn;  // set clip to intersect of update & thumb
  250.     thumbClip &= updateRgn;
  251.     dc.SelectClipRgn(thumbClip);
  252.     PaintThumb(dc);
  253.  
  254.     updateRgn -= thumbClip;
  255.     dc.SelectClipRgn(updateRgn);    // set clip to update minus thumb
  256.     ValidateRgn(*ThumbRgn);
  257.     PaintSlot(dc);
  258.     PaintRuler(dc);
  259.   }
  260.   else {                          // no region, thumb will flicker a little
  261.     TPaintDC  dc(*this);
  262.  
  263.     GetBkColor(dc);
  264.     PaintSlot(dc);
  265.     PaintRuler(dc);
  266.     PaintThumb(dc);
  267.   }
  268.   ShowCaret();
  269. }
  270.  
  271. //
  272. // We'll always erase as we paint to avoid flicker
  273. //
  274. bool
  275. TSlider::EvEraseBkgnd(HDC)
  276. {
  277.   return true;
  278. }
  279.  
  280. //
  281. // If a button down on the thumb, then enter sliding state.
  282. // If in the slot, pg up or down. If on the ruler, jump there.
  283. //
  284. void
  285. TSlider::EvLButtonDown(uint /*modKeys*/, TPoint& point)
  286. {
  287.   if (GetFocus() != HWindow)
  288.     SetFocus();
  289.  
  290.   int scrollCode = HitTest(point);
  291.   switch (scrollCode) {
  292.     case SB_THUMBPOSITION:
  293.       NotifyParent(scrollCode, SnapPos(PointToPos(point)));
  294.       break;
  295.       
  296.     case SB_LINEUP:
  297.     case SB_LINEDOWN:
  298.     case SB_PAGEUP:
  299.     case SB_PAGEDOWN:
  300.       NotifyParent(scrollCode);
  301.       break;
  302.  
  303.     case SB_THUMBTRACK: {
  304.       Sliding = true;
  305.       SetCapture();
  306.       HideCaret();
  307.       SlideDC = new TClientDC(HWindow);  // keep this dc around while sliding
  308.  
  309.       GetBkColor(*SlideDC);  // repaint thumb in pressed state
  310.       PaintThumb(*SlideDC);
  311.  
  312.       MouseOffset = point-ThumbRect.TopLeft();
  313.       point -= MouseOffset;
  314.       int pos = SnapPos(PointToPos(point));// keep thumb on track & on pos units
  315.       NotifyParent(9, pos);     // undocumented 'begin track' code
  316.       NotifyParent(SB_THUMBTRACK, pos);
  317.     }
  318.   }
  319. }
  320.  
  321. //
  322. // If sliding then either slide thumb, or detect a lost button up & simulate
  323. // it.
  324. //
  325. void
  326. TSlider::EvMouseMove(uint modKeys, TPoint& point)
  327. {
  328.   if (Sliding && SlideDC) {
  329.     if (!(modKeys&MK_LBUTTON)) {
  330.       EvLButtonUp(modKeys, point);    // we missed a lbutton up somehow...
  331.       return;
  332.     }
  333.     // keep thumb on track & on pos units
  334.     NotifyParent(SB_THUMBTRACK, SnapPos(PointToPos(point - MouseOffset)));
  335.   }
  336. }
  337.  
  338. //
  339. // Handle button messages if we are sliding by releasing capture & ending
  340. // sliding state
  341. //
  342. void
  343. TSlider::EvLButtonUp(uint /*modKeys*/, TPoint& point)
  344. {
  345.   int pos = SnapPos(PointToPos(point - MouseOffset));
  346.   if (Sliding) {
  347.     Sliding = false;
  348.     NotifyParent(SB_THUMBPOSITION, pos);
  349.  
  350.     GetBkColor(*SlideDC);   // repaint thumb in released state
  351.     if (ThumbRgn)
  352.       SlideDC->SelectClipRgn(*ThumbRgn);
  353.     PaintThumb(*SlideDC);
  354.  
  355.     ReleaseCapture();
  356.     delete SlideDC;
  357.     SlideDC = 0;
  358.  
  359.     ShowCaret();
  360.   }
  361.   NotifyParent(SB_ENDSCROLL, pos);
  362. }
  363.  
  364. //
  365. // Catch double clicks and eat them
  366. //
  367. void
  368. TSlider::EvLButtonDblClk(uint /*modKeys*/, TPoint&)
  369. {
  370. }
  371.  
  372. //
  373. // Translate key messages to scroll events w/ repeat.
  374. //
  375. void
  376. TSlider::EvKeyDown(uint key, uint repeatCount, uint /*flags*/)
  377. {
  378.   static int KeyToCode[] = {
  379.     SB_PAGEUP,    // VK_PRIOR
  380.     SB_PAGEDOWN,  // VK_NEXT 
  381.     SB_BOTTOM,    // VK_END
  382.     SB_TOP,       // VK_HOME
  383.     SB_LINEUP,    // VK_LEFT(same as SB_LINELEFT)
  384.     SB_LINEUP,    // VK_UP
  385.     SB_LINEDOWN,  // VK_RIGHT(same as SB_LINERIGHT)
  386.     SB_LINEDOWN   // VK_DOWN
  387.   };
  388.  
  389.   if (key >= VK_PRIOR && key <= VK_DOWN) {
  390.     for (int i = 0; i < repeatCount; i++)
  391.       NotifyParent(KeyToCode[key-VK_PRIOR], Pos);
  392.     NotifyParent(SB_ENDSCROLL, Pos);
  393.   }
  394. }
  395.  
  396. //
  397. // Create, position & show a caret when we have focus. Remove it when we lose
  398. // focus
  399. //
  400. void
  401. TSlider::EvSetFocus(HWND /*hWndLostFocus*/)
  402. {
  403.   CreateCaret(true, CaretRect.Width(), CaretRect.Height());
  404.   SetCaretPos(ThumbRect.left+CaretRect.left, ThumbRect.top+CaretRect.top);
  405.   ShowCaret();
  406.  
  407. //  TScrollBar::EvSetFocus(hWndLostFocus);  // Can't let SCROLLBAR see this
  408. }
  409.  
  410. void
  411. TSlider::EvKillFocus(HWND hWndGetFocus)
  412. {
  413.   HideCaret();
  414.   DestroyCaret();
  415.  
  416.   TScrollBar::EvKillFocus(hWndGetFocus); // need to let TWindow do focus save
  417. }
  418.  
  419. #endif
  420. #if !defined(SECTION) || SECTION == 2
  421.  
  422. IMPLEMENT_ABSTRACT_STREAMABLE1(TSlider, TScrollBar);
  423.  
  424. void*
  425. TSlider::Streamer::Read(ipstream& is, uint32 /*version*/) const
  426. {
  427.   TSlider* o = GetObject();
  428.   ReadBaseObject((TScrollBar*)o, is);
  429.   is >> o->Min
  430.      >> o->Max
  431.      >> o->Pos
  432.      >> o->ThumbResId
  433.      >> o->ThumbRect
  434.      >> o->TicGap
  435.      >> o->CaretRect
  436.      >> o->Snap;
  437.   o->SetRange(o->Min, o->Max);  // let it calculate Range
  438.   return o;
  439. }
  440.  
  441. void
  442. TSlider::Streamer::Write(opstream& os) const
  443. {
  444.   TSlider* o = GetObject();
  445.   WriteBaseObject((TScrollBar*)o, os);
  446.   os << o->Min
  447.      << o->Max
  448.      << o->Pos
  449.      << o->ThumbResId
  450.      << o->ThumbRect
  451.      << o->CaretRect
  452.      << o->TicGap
  453.      << o->Snap;
  454. }
  455.  
  456. #endif
  457.