home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 1997 March / VPR9703A.ISO / VPR_DATA / DOGA / SOURCES / PASM.LZH / SLIDER.CPP < prev    next >
C/C++ Source or Header  |  1996-06-13  |  10KB  |  451 lines

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