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 >
Wrap
C/C++ Source or Header
|
1996-06-13
|
10KB
|
451 lines
//----------------------------------------------------------------------------
// ObjectWindows - (C) Copyright 1993 by Borland International
// source\owl\slider.cpp
//----------------------------------------------------------------------------
#pragma hdrignore SECTION
#include <owl\owlpch.h>
#include <owl\slider.h>
#include <owl\dc.h>
#if !defined(SECTION) || SECTION == 1
DEFINE_RESPONSE_TABLE1(TSlider, TScrollBar)
EV_WM_SIZE,
EV_WM_GETDLGCODE,
EV_WM_ERASEBKGND,
EV_WM_PAINT,
EV_WM_LBUTTONDOWN,
EV_WM_MOUSEMOVE,
EV_WM_LBUTTONUP,
EV_WM_LBUTTONDBLCLK,
EV_WM_KEYDOWN,
EV_WM_SETFOCUS,
EV_WM_KILLFOCUS,
END_RESPONSE_TABLE;
TSize TSlider::MouseOffset;
TDC* TSlider::SlideDC = 0;
//
// Constructor for a TSlider object
//
TSlider::TSlider(TWindow* parent,
int id,
int x, int y, int w, int h,
TResId thumbResId,
TModule* module)
: TScrollBar(parent, id, x, y, w, h, TRUE, module),
ThumbResId(thumbResId),
ThumbRect(0, 0, 9, 20),
CaretRect(3, 3, 3+3, 3+13)
{
SetRange(0, 100);
Pos = 0;
ThumbRgn = 0;
TicGap = Range/10;
SlotThick = 17;
Snap = TRUE;
Sliding = FALSE;
// get slot size from Attr.H set by TScrollBar ?
Attr.W = w;
Attr.H = h;
}
//
//
//
TSlider::~TSlider()
{
delete ThumbRgn;
}
//
// Setup slider window
//
void
TSlider::SetupWindow()
{
TScrollBar::SetupWindow();
SetupThumbRgn();
}
//
// Check & set the slider range
//
void
TSlider::SetRange(int min, int max)
{
Min = min;
Max = max;
if (Max > Min)
Range = Max - Min;
else if (Min > Max)
Range = Min - Max;
else
Range = 1;
}
//
// Set the position of the thumb
//
void
TSlider::SetPosition(int pos)
{
//
// constrain pos to be in the range "Min .. Max" & snap to tics if enabled
//
pos = SnapPos(pos);
//
// Slide thumb to new position, converting pos to pixels
//
if (pos != Pos) {
if (HWindow) {
TDC* dc = SlideDC ? SlideDC : new TClientDC(HWindow);
SlideThumb(*dc, pos);
if (!SlideDC)
delete dc;
}
Pos = pos;
}
}
//
// setup region that defines the thumb shape for this slider class.
// default region is a simple bounding rect, but could be any shape.
//
void
TSlider::SetupThumbRgn()
{
if (!ThumbRgn)
ThumbRgn = new TRegion(ThumbRect);
}
//
// Slide the thumb & perform necessary blitting & painting.
// Assumes that Pos, Min & Max are up to date.
//
void
TSlider::SlideThumb(TDC& dc, int pos)
{
TPoint point = PosToPoint(pos);
HideCaret();
GetBkColor(dc);
if (ThumbRgn) {
TRegion oldRgn(ThumbRect);
TRect newThumbRect(point, ThumbRect.Size());
*ThumbRgn += point-ThumbRect.TopLeft();
dc.SelectClipRgn(*ThumbRgn);
dc.BitBlt(newThumbRect, dc, ThumbRect.TopLeft());
ThumbRect = newThumbRect;
oldRgn -= *ThumbRgn;
dc.SelectClipRgn(oldRgn);
PaintSlot(dc);
} else {
ThumbRect = TRect(point, ThumbRect.Size());
PaintSlot(dc);
PaintThumb(dc);
}
SetCaretPos(ThumbRect.left+CaretRect.left, ThumbRect.top+CaretRect.top);
ShowCaret();
}
//
// Paint the thumb itself using a resource DIB translated to the current system
// button colors. Overlaps the slot.
//
void
TSlider::PaintThumb(TDC& dc)
{
TDib thumbDib(*GetModule(), ThumbResId);
thumbDib.MapUIColors(
TDib::MapFace|TDib::MapText|TDib::MapShadow|TDib::MapHighlight,
&dc.GetBkColor()
);
int dibX = (Sliding || !IsWindowEnabled()) ? thumbDib.Width()/2 : 0;
dc.SetDIBitsToDevice(ThumbRect, TPoint(dibX, 0), thumbDib);
}
//
// Constrain pos to be in the range "Min .. Max" &
// perform 'Snap'ing if enabled by rounding pos to nearest TicGap
//
int
TSlider::SnapPos(int pos)
{
if (pos > Max)
pos = Max;
else if (pos < Min)
pos = Min;
return Snap ? (((pos-Min)+TicGap/2)/TicGap)*TicGap + Min : pos;
}
//
// Get & release a brush obtained from our parent window for use in painting
// background areas in this control.
//
void
TSlider::GetBkColor(TDC& /*dc*/)
{
#if 0
Parent->HandleMessage(WM_CTLCOLOR,
(WPARAM)(HDC)dc,
MAKELPARAM(HWindow, CTLCOLOR_STATIC));
BkColor = dc.GetBkColor();
#endif
BkColor = BkgndColor;
}
//
//
//
void
TSlider::EvSize(UINT sizeType, TSize& size)
{
TScrollBar::EvSize(sizeType, size);
}
//
// Make sure we get cursor movement keys to move the thumb
//
UINT
TSlider::EvGetDlgCode(MSG far*)
{
return DLGC_WANTARROWS;
}
//
// Paint the whole slider: ruler, slot & thumb
//
void
TSlider::EvPaint()
{
HideCaret();
if (ThumbRgn) { // use thumb region if avalable
TRegion updateRgn;
GetUpdateRgn(updateRgn);
TPaintDC dc(*this);
GetBkColor(dc);
TRegion thumbClip = *ThumbRgn; // set clip to intersect of update & thumb
thumbClip &= updateRgn;
dc.SelectClipRgn(thumbClip);
PaintThumb(dc);
updateRgn -= thumbClip;
dc.SelectClipRgn(updateRgn); // set clip to update minus thumb
ValidateRgn(*ThumbRgn);
PaintSlot(dc);
PaintRuler(dc);
} else { // no region, thumb will flicker a little
TPaintDC dc(*this);
GetBkColor(dc);
PaintSlot(dc);
PaintRuler(dc);
PaintThumb(dc);
}
ShowCaret();
}
//
// We'll always erase as we paint to avoid flicker
//
BOOL
TSlider::EvEraseBkgnd(HDC)
{
return TRUE;
}
//
// If a button down on the thumb, then enter sliding state.
// If in the slot, pg up or down. If on the ruler, jump there.
//
void
TSlider::EvLButtonDown(UINT /*modKeys*/, TPoint& point)
{
if (GetFocus() != HWindow)
SetFocus();
int scrollCode = HitTest(point);
switch (scrollCode) {
case SB_THUMBPOSITION:
NotifyParent(scrollCode, SnapPos(PointToPos(point)));
break;
case SB_LINEUP:
case SB_LINEDOWN:
case SB_PAGEUP:
case SB_PAGEDOWN:
NotifyParent(scrollCode);
break;
case SB_THUMBTRACK: {
Sliding = TRUE;
SetCapture();
HideCaret();
SlideDC = new TClientDC(HWindow); // keep this dc around while sliding
GetBkColor(*SlideDC); // repaint thumb in pressed state
PaintThumb(*SlideDC);
MouseOffset = point-ThumbRect.TopLeft();
point -= MouseOffset;
int pos = SnapPos(PointToPos(point));// keep thumb on track & on pos units
NotifyParent(9, pos); // undocumented 'begin track' code
NotifyParent(SB_THUMBTRACK, pos);
}
}
}
//
// If sliding then either slide thumb, or detect a lost button up & simulate
// it.
//
void
TSlider::EvMouseMove(UINT modKeys, TPoint& point)
{
if (Sliding && SlideDC) {
if (!(modKeys&MK_LBUTTON)) {
EvLButtonUp(modKeys, point); // we missed a lbutton up somehow...
return;
}
// keep thumb on track & on pos units
NotifyParent(SB_THUMBTRACK, SnapPos(PointToPos(point - MouseOffset)));
}
}
//
// Handle button messages if we are sliding by releasing capture & ending
// sliding state
//
void
TSlider::EvLButtonUp(UINT /*modKeys*/, TPoint& point)
{
int pos = SnapPos(PointToPos(point - MouseOffset));
if (Sliding) {
Sliding = FALSE;
NotifyParent(SB_THUMBPOSITION, pos);
GetBkColor(*SlideDC); // repaint thumb in released state
if (ThumbRgn)
SlideDC->SelectClipRgn(*ThumbRgn);
PaintThumb(*SlideDC);
ReleaseCapture();
delete SlideDC;
SlideDC = 0;
ShowCaret();
}
NotifyParent(SB_ENDSCROLL, pos);
}
//
// Catch double clicks and eat them
//
void
TSlider::EvLButtonDblClk(UINT /*modKeys*/, TPoint&)
{
}
//
// Translate key messages to scroll events w/ repeat.
//
void
TSlider::EvKeyDown(UINT key, UINT repeatCount, UINT /*flags*/)
{
static int KeyToCode[] = {
SB_PAGEUP, // VK_PRIOR
SB_PAGEDOWN, // VK_NEXT
SB_BOTTOM, // VK_END
SB_TOP, // VK_HOME
SB_LINEUP, // VK_LEFT(same as SB_LINELEFT)
SB_LINEUP, // VK_UP
SB_LINEDOWN, // VK_RIGHT(same as SB_LINERIGHT)
SB_LINEDOWN // VK_DOWN
};
if (key >= VK_PRIOR && key <= VK_DOWN) {
for (int i = 0; i < repeatCount; i++)
NotifyParent(KeyToCode[key-VK_PRIOR], Pos);
NotifyParent(SB_ENDSCROLL, Pos);
}
}
//
// Create, position & show a caret when we have focus. Remove it when we lose
// focus
//
void
TSlider::EvSetFocus(HWND /*hWndLostFocus*/)
{
CreateCaret(TRUE, CaretRect.Width(), CaretRect.Height());
SetCaretPos(ThumbRect.left+CaretRect.left, ThumbRect.top+CaretRect.top);
ShowCaret();
// TScrollBar::EvSetFocus(hWndLostFocus); // Can't let SCROLLBAR see this
}
void
TSlider::EvKillFocus(HWND hWndGetFocus)
{
HideCaret();
DestroyCaret();
TScrollBar::EvKillFocus(hWndGetFocus); // need to let TWindow do focus save
}
#endif
#if !defined(SECTION) || SECTION == 2
IMPLEMENT_ABSTRACT_STREAMABLE1(TSlider, TScrollBar);
void*
TSlider::Streamer::Read(ipstream& is, uint32 /*version*/) const
{
TSlider* o = GetObject();
ReadBaseObject((TScrollBar*)o, is);
is >> o->Min
>> o->Max
>> o->Pos
>> o->ThumbResId
>> o->ThumbRect
>> o->TicGap
>> o->CaretRect
>> o->Snap;
o->SetRange(o->Min, o->Max); // let it calculate Range
return o;
}
void
TSlider::Streamer::Write(opstream& os) const
{
TSlider* o = GetObject();
WriteBaseObject((TScrollBar*)o, os);
os << o->Min
<< o->Max
<< o->Pos
<< o->ThumbResId
<< o->ThumbRect
<< o->CaretRect
<< o->TicGap
<< o->Snap;
}
#endif