home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1998 May
/
Pcwk5b98.iso
/
Borland
/
Cplus45
/
BC45
/
OWL1.PAK
/
SCROLLER.CPP
< prev
next >
Wrap
Text File
|
1995-08-29
|
9KB
|
327 lines
// ObjectWindows - (C) Copyright 1992 by Borland International
/* --------------------------------------------------------
SCROLLER.CPP
Defines type TScroller.
-------------------------------------------------------- */
#include "applicat.h"
#include "window.h"
#define max(a,b)(((a) >(b)) ?(a) :(b))
#define min(a,b)(((a) <(b)) ?(a) :(b))
#define abs(a) (((a) >= 0) ?(a) :-(a))
hashValueType TScroller::ClassHashValue = 0;
/* Constructs a TScroller object, initializing its data fields to
default values. */
TScroller::TScroller(PTWindow TheWindow,int TheXUnit, int TheYUnit, long TheXRange, long TheYRange)
{
Window = TheWindow;
XPos = YPos = 0;
XUnit = TheXUnit;
YUnit = TheYUnit;
XRange = TheXRange;
YRange = TheYRange;
XLine = 1; YLine = 1;
XPage = 1; YPage = 1;
AutoMode = TRUE;
TrackMode = TRUE;
AutoOrg = TRUE;
HasHScrollBar = (Window &&
((Window->Attr.Style & WS_HSCROLL) == WS_HSCROLL));
HasVScrollBar = (Window &&
((Window->Attr.Style & WS_VSCROLL) == WS_VSCROLL));
InstanceHashValue = ClassHashValue++;
}
/* Destructs a TScroller object. Sets Window's Scroller member to NULL */
TScroller::~TScroller()
{
if ( Window && Window->Scroller )
Window->Scroller = NULL;
}
/* Sets the number of units per page (amount by which to scroll on
a page scroll request) according to the current size of the
Window's client area. */
void TScroller::SetPageSize()
{
RECT ClientRect;
int Width, Height;
if ( Window )
{
GetClientRect(Window->HWindow, &ClientRect);
Width = ClientRect.right - ClientRect.left;
Height = ClientRect.bottom - ClientRect.top;
if ( (Width != 0) && (XUnit > 0) )
XPage = max(1, ((Width+1)/XUnit) -1);
if ( (Height != 0) && (YUnit > 0) )
YPage = max(1, ((Height+1)/YUnit) -1);
}
}
/* Sets the range of the TScroller and also sets the range of
its Window's scrollbars. */
void TScroller::SetRange(long TheXRange, long TheYRange)
{
XRange = TheXRange;
YRange = TheYRange;
SetSBarRange();
ScrollTo(XPos, YPos);
}
/* Resets the X and Y scroll unit size (in device units) to the passed
parameters. Calls SetPageSize to update the X and Y page size, which
are specified in scroll units. */
void TScroller::SetUnits(int TheXUnit, int TheYUnit)
{
XUnit = TheXUnit;
YUnit = TheYUnit;
SetPageSize();
}
/* Sets the range of the Window's scrollbars. */
void TScroller::SetSBarRange()
{
if ( Window )
{
if ( HasHScrollBar )
SetScrollRange(Window->HWindow, SB_HORZ, 0,
max(0, (int)min(XRange, MaxInt)), FALSE);
if ( HasVScrollBar )
SetScrollRange(Window->HWindow, SB_VERT, 0,
max(0, (int)min(YRange, MaxInt)), FALSE);
}
}
/* Sets the origin for the paint display context according to
XPos, YPos. */
inline void TScroller::__BeginView(HDC PaintDC, PAINTSTRUCT&)
{
long XOrg, YOrg;
XOrg = XPos * XUnit;
YOrg = YPos * YUnit;
if ( AutoOrg && (XOrg <= MaxInt) && (YOrg <= MaxInt) )
SetViewportOrg(PaintDC, (int)-XOrg, (int)-YOrg);
}
#if defined(WIN31)
void TScroller::BeginView(HDC PaintDC, PAINTSTRUCT&)
{
PAINTSTRUCT ps_tmp;
__BeginView(PaintDC, ps_tmp);
}
#endif
#if defined(WIN30)
void TScroller::BeginView(HDC_30 PaintDC, PAINTSTRUCT&)
{
PAINTSTRUCT ps_tmp;
__BeginView( HDC( PaintDC ), ps_tmp);
}
#endif
/* Updates the position of the Window's scrollbar(s). */
void TScroller::EndView()
{
int TempPos;
if ( Window )
{
if ( HasHScrollBar )
{
if ( XRange > MaxInt )
TempPos = XScrollValue(XPos);
else
TempPos = (int)XPos;
if ( GetScrollPos(Window->HWindow, SB_HORZ) != TempPos )
SetScrollPos(Window->HWindow, SB_HORZ, TempPos, TRUE);
}
if ( HasVScrollBar )
{
if ( YRange > MaxInt )
TempPos = YScrollValue(YPos);
else
TempPos = (int)YPos;
if ( GetScrollPos(Window->HWindow, SB_VERT) != TempPos )
SetScrollPos(Window->HWindow, SB_VERT, TempPos, TRUE);
}
}
}
/* Scrolls vertically according to scroll action and thumb position. */
void TScroller::VScroll(WORD ScrollEvent, int ThumbPos)
{
switch (ScrollEvent) {
case SB_LINEDOWN : ScrollBy(0, YLine);
break;
case SB_LINEUP : ScrollBy(0, -YLine);
break;
case SB_PAGEDOWN : ScrollBy(0, YPage);
break;
case SB_PAGEUP : ScrollBy(0, -YPage);
break;
case SB_TOP : ScrollTo(XPos, 0);
break;
case SB_BOTTOM : ScrollTo(XPos, YRange);
break;
case SB_THUMBPOSITION :
if ( YRange > MaxInt )
ScrollTo(XPos, YRangeValue(ThumbPos));
else
ScrollTo(XPos, ThumbPos);
break;
case SB_THUMBTRACK :
if ( TrackMode )
if ( YRange > MaxInt )
ScrollTo(XPos, YRangeValue(ThumbPos));
else
ScrollTo(XPos, ThumbPos);
if ( Window && HasVScrollBar )
SetScrollPos(Window->HWindow, SB_VERT, ThumbPos, TRUE);
break;
} // switch
}
/* Scrolls horizontally according to scroll action and thumb
position. */
void TScroller::HScroll(WORD ScrollEvent, int ThumbPos)
{
switch (ScrollEvent) {
case SB_LINEDOWN : ScrollBy(XLine, 0);
break;
case SB_LINEUP : ScrollBy(-XLine, 0);
break;
case SB_PAGEDOWN : ScrollBy(XPage, 0);
break;
case SB_PAGEUP : ScrollBy(-XPage, 0);
break;
case SB_TOP : ScrollTo(0, YPos);
break;
case SB_BOTTOM : ScrollTo(XRange, YPos);
break;
case SB_THUMBPOSITION :
if ( XRange > MaxInt )
ScrollTo(XRangeValue(ThumbPos), YPos);
else
ScrollTo(ThumbPos, YPos);
break;
case SB_THUMBTRACK :
if ( TrackMode )
if ( XRange > MaxInt )
ScrollTo(XRangeValue(ThumbPos), YPos);
else
ScrollTo(ThumbPos, YPos);
if ( (Window) && HasHScrollBar )
SetScrollPos(Window->HWindow, SB_HORZ, ThumbPos, TRUE);
break;
} // switch
}
/* Scrolls to an (X,Y) position, after checking boundary conditions.
Causes a WMPaint message to be sent. First scrolls the contents
of the client area, if a portion of the client area will
remain visible. */
void TScroller::ScrollTo(long X, long Y)
{
long NewXPos , NewYPos;
if ( Window )
{
NewXPos = max(0, min(X, XRange));
NewYPos = max(0, min(Y, YRange));
if ( (NewXPos != XPos) || (NewYPos != YPos) )
{
/* Scaling is not needed here. If condition is met, ScrollWindow()
will succeed since XPage and YPage are ints. If condition is not
met, ScrollWindow() is called in EndScroll() as a result of calling
UpdateWindow(). EndScroll() performs the necessary scaling.
*/
if ( AutoOrg || (abs(YPos - NewYPos) < YPage) &&
(abs(XPos - NewXPos) < XPage) )
ScrollWindow(Window->HWindow, (int)((XPos-NewXPos)*XUnit),
(int)((YPos-NewYPos)*YUnit), NULL, NULL);
else
InvalidateRect(Window->HWindow, NULL, TRUE);
XPos = NewXPos;
YPos = NewYPos;
UpdateWindow(Window->HWindow);
}
}
}
/* Performs "auto-scrolling". (Dragging the mouse from within the
client area of the Window to without results in auto-scrolling
when the AutoMode data member of the Scroller is TRUE). */
void TScroller::AutoScroll()
{
POINT CursorPos;
RECT ClientRect;
long Dx , Dy;
if ( AutoMode && Window )
{
GetCursorPos(&CursorPos);
ScreenToClient(Window->HWindow, &CursorPos);
GetClientRect(Window->HWindow, &ClientRect);
Dx = 0; Dy = 0;
if ( CursorPos.y < 0 )
Dy = min(-YLine, max(-YPage, (CursorPos.y/10) * YLine));
else
if ( CursorPos.y > ClientRect.bottom )
Dy = max(YLine, min(YPage,
((CursorPos.y - ClientRect.bottom)/10) * YLine));
if ( CursorPos.x < 0 )
Dx = min(-XLine, max(-XPage, (CursorPos.x/10) * XLine));
else
if ( CursorPos.x > ClientRect.right )
Dx = max(XLine, min(XPage, ((CursorPos.x - ClientRect.right)/10) * XLine));
ScrollBy(Dx, Dy);
}
}
/* Reads an instance of TScroller from the passed ipstream. */
void *TScroller::read(ipstream& is)
{
is >> XPos >> YPos
>> XUnit >> YUnit
>> XRange >> YRange
>> XLine >> YLine
>> XPage >> YPage
>> AutoMode >> TrackMode
>> AutoOrg
>> HasHScrollBar >> HasVScrollBar;
Window = NULL;
InstanceHashValue = ClassHashValue++;
return this;
}
/* Writes the TScroller to the passed opstream. */
void TScroller::write(opstream& os)
{
os << XPos << YPos
<< XUnit << YUnit
<< XRange << YRange
<< XLine << YLine
<< XPage << YPage
<< AutoMode << TrackMode
<< AutoOrg
<< HasHScrollBar << HasVScrollBar;
}
TStreamable *TScroller::build()
{
return new TScroller(streamableInit);
}
TStreamableClass RegScroller("TScroller", TScroller::build,
__DELTA(TScroller));