//----------------------------------------------------------------------------
// ObjectWindows
// Copyright (c) 1995, 1995 by Borland International, All Rights Reserved
// notebook.cpp - defines TNotebook class
//
// Special explanation for non-client painting in TNotebook:
//
// normal windows sequence of events for window resize:
// WM_NCCALCSIZE
// WM_NCPAINT
// WM_SIZE
//
// This causes multiple ncpaints since subclassers must hook WM_SIZE and
// show/hide scrollbars based on new client size; these multiple ncpaints
// are especially noticable in TNotebook since the painting of the tabs
// takes a relative long amount of time.
//
// Solution taken to this problem in TNotebook class: created a variable
// called "defer_ncpaint" to turn nc painting on/off. It is used as
// follows:
//
// 1. Constructor: sets defer_ncpaint = 0
// 2. EvNCPaint(): if defer_ncpaint > 0, decrements it and returns
// without painting
// 3. EvNCCalcSize(): if defer_ncpaint >= 0, increments it
// 4. EvSize(): if defer_ncpaint = 0, calls ForceResize(TRUE) to force
// ncpaint
// 5. ForceResize(repaint): if repaint=TRUE, defer_ncpaint=-1,
// resize window, defer_ncpaint=0
//
// Subclassers of TNotebook::Evsize() should:
// 1. set defer_ncpaint=1
// 2. call TNotebook::Evsize(...)
// 3. call SetScrollRange(...) as needed to hide/show scrollbars
// 4. call ForceResize(TRUE) to force ncpaint
//
// If subclassers just ignore "defer_ncpaint", TNotebook should paint
// normally but with multiple nc paints.
//
//----------------------------------------------------------------------------
#include <owlext\pch.h>
#pragma hdrstop
#include <owl/mdichild.h>
#include <owl/dc.h>
#include <owl/uimetric.h>
#include <owlext/notebook.h>
using namespace owl;
using namespace std;
namespace OwlExt {
//----------------------------------------------------------------------------
DEFINE_RESPONSE_TABLE1(TNotebook, TWindow)
EV_WM_GETMINMAXINFO,
EV_WM_SIZE,
EV_WM_NCCALCSIZE,
EV_WM_NCHITTEST,
EV_WM_NCPAINT,
EV_WM_NCCREATE,
EV_WM_NCLBUTTONDOWN,
EV_WM_NCLBUTTONDBLCLK,
EV_WM_LBUTTONUP, // while mouse captured, we get these
EV_WM_MOUSEMOVE, // while mouse captured, we get these
EV_WM_SYSCOLORCHANGE,
EV_MESSAGE(NW_HSCROLL, NWHscroll),
EV_MESSAGE(NW_VSCROLL, NWHscroll),
END_RESPONSE_TABLE;
//----------------------------------------------------------------------------
TNotebook::TNotebook(int TabLoc)
{
tabloc = TabLoc;
tabhorz = ((tabloc == LOC_TOP) || (tabloc == LOC_BOTTOM));
tabcnt = 1;
firsttab = 0;
activetab = 0;
erasetabs = false;
tabhscroll = NULL; // until created
tabvscroll = NULL; // until created
winhscroll = NULL; // until created
winvscroll = NULL; // until created
hscrollon = false;
vscrollon = false;
defer_ncpaint = 0;
///YB nbcheight = 9 + GetSystemMetrics(SM_CYHSCROLL);
nbcheight = 6 + TUIMetric::CyHScroll;
rgncnt = 0;
fillmode = ALTERNATE;
clientprev = TRect(0, 0, 0, 0);
BuildPaintObjects();
}
//----------------------------------------------------------------------------
void TNotebook::BuildPaintObjects()
{
BuildBgBrush();
framebrush = new TBrush(GetSysColor(COLOR_WINDOWFRAME));
hilitebrush = new TBrush(GetSysColor(COLOR_BTNHIGHLIGHT));
shadowbrush = new TBrush(GetSysColor(COLOR_BTNSHADOW));
facebrush = new TBrush(GetSysColor(COLOR_BTNFACE));
trackbrush = new TBrush(GetSysColor(COLOR_SCROLLBAR));
tabbrush = new TBrush(GetSysColor(COLOR_WINDOW));
default_tabbrush = new TBrush(GetSysColor(COLOR_WINDOW));
shadowpen = new TPen(GetSysColor(COLOR_BTNSHADOW));
framepen = new TPen(GetSysColor(COLOR_WINDOWFRAME));
#if 0
if (tabhorz)
tabfont = new TFont(_T("ms sans serif"), 10);
else
tabfont = new TFont(_T("arial"), 10, 0, 2700, 2700);
#else
if (tabhorz)
tabfont = new TFont(_T("ms sans serif"), 8);
else
tabfont = new TFont(_T("arial"), 10, 0, 2700, 2700);
#endif
}
//----------------------------------------------------------------------------
void TNotebook::DeletePaintObjects()
{
delete bgbrush;
delete framebrush;
delete hilitebrush;
delete shadowbrush;
delete facebrush;
delete trackbrush;
delete tabbrush;
delete default_tabbrush;
delete shadowpen;
delete framepen;
delete tabfont;
}
//----------------------------------------------------------------------------
TNotebook::~TNotebook()
{
delete tabhscroll;
delete tabvscroll;
delete winhscroll;
delete winvscroll;
DeletePaintObjects();
}
//----------------------------------------------------------------------------
UINT TNotebook::EvNCHitTest(const TPoint& screenPt)
{
TPoint winpt = screenPt - GetWindowRect().TopLeft(); // win coords
if (nbcrect.Contains(winpt))
return(HTBORDER);
if ((hscrollon) && (hsbrect.Contains(winpt)))
return(HTBORDER);
if ((vscrollon) && (vsbrect.Contains(winpt)))
return(HTBORDER);
return(TWindow::EvNCHitTest(screenPt));
}
//----------------------------------------------------------------------------
void TNotebook::PaintNBC(int paintcontrol)
{
bool goth, gotv;
if ((!GetHandle()) || IsIconic())
return;
TWindowDC mydc(*this);
DrawBackground(mydc, nbcrect, paintcontrol);
DrawTabLines(mydc, nbcrect, TRUE);
DrawTabs(mydc);
if (paintcontrol == NBC_PAINTALL){
if (tabhscroll)
tabhscroll->ForcePaint();
if (tabvscroll)
tabvscroll->ForcePaint();
if (hscrollon)
winhscroll->ForcePaint();
if (vscrollon)
winvscroll->ForcePaint();
}
goth = (hscrollon || tabloc == LOC_BOTTOM);
gotv = (vscrollon || tabloc == LOC_RIGHT);
if (goth && gotv){ // paint corner
int mywidth, myheight;
if(tabloc == LOC_RIGHT)
mywidth = nbcrect.Width();
else
mywidth = GetSystemMetrics(SM_CXVSCROLL);
if(tabloc == LOC_BOTTOM)
myheight = nbcrect.Height() + 1;
else
myheight = GetSystemMetrics(SM_CYHSCROLL);
if((tabloc == LOC_TOP)||(tabloc == LOC_LEFT))
mydc.SelectObject(*trackbrush);
else
mydc.SelectObject(*bgbrush);
mydc.SelectObject(*framepen);
Rectangle(mydc, clientrect.right, clientrect.bottom,
clientrect.right+mywidth, clientrect.bottom+myheight);
}
}
//----------------------------------------------------------------------------
void
TNotebook::EvNCPaint(HRGN rgn)
{
if (defer_ncpaint > 0) {
defer_ncpaint--;
return;
}
TRACE("ncpaint being done");
TWindow::EvNCPaint(rgn); // let windows paint everything else in NC
ComputeSizes(); // we are called before WM_SIZE is sent...
PaintNBC(NBC_PAINTALL);
}
//----------------------------------------------------------------------------
void TNotebook::GetTabName(int tabnum, LPTSTR tabname)
{
if (tabnum < 26){
tabname[0] = (_TCHAR)(_T('A')+tabnum); //Cast to char to avoid 32 bit conv warnings
tabname[1] = 0;
}
else if (tabnum < (702)) {
tabnum -= 26;
tabname[0] = (_TCHAR)(_T('A')+(tabnum/26));
tabname[1] = (_TCHAR)(_T('A')+(tabnum%26));
tabname[2] = 0;
}
else {
tabnum -= 702;
tabname[0] = (_TCHAR)(_T('A')+tabnum/676);
tabnum = tabnum % 676;
tabname[1] = (_TCHAR)(_T('A')+(tabnum/26));
tabname[2] = (_TCHAR)(_T('A')+(tabnum%26));
tabname[3] = 0;
}
}
//----------------------------------------------------------------------------
void TNotebook::DrawDownFrame(TDC &mydc, TRect &myrect)
{
int width = myrect.right - myrect.left;
int height = myrect.bottom - myrect.top;
mydc.SelectObject(*shadowbrush);
FASTHLINE(mydc, myrect.left, myrect.top, width);
FASTVLINE(mydc, myrect.left, myrect.top, height);
mydc.SelectObject(*facebrush);
FASTHLINE(mydc, myrect.left, myrect.bottom-1, width);
FASTVLINE(mydc, myrect.right-1, myrect.top, height);
}
//----------------------------------------------------------------------------
void TNotebook::DrawShadeFrame(TDC &mydc, TRect &myrect)
{
int width = myrect.right - myrect.left;
int height = myrect.bottom - myrect.top;
mydc.SelectObject(*hilitebrush);
FASTHLINE(mydc, myrect.left, myrect.top, width);
FASTVLINE(mydc, myrect.left, myrect.top, height);
mydc.SelectObject(*shadowbrush);
FASTHLINE(mydc, myrect.left, myrect.bottom-1, width);
FASTVLINE(mydc, myrect.right-1, myrect.top, height);
}
//---------------------------------------------------------------------------
int TNotebook::DrawHorzTab(TDC& mydc, int tabnum, int rgnnum, int toff)
{
_TCHAR tabname[MAXTABNAMELEN+1];
SIZE textsize;
int tabsize, bp;
TRect textrect;
POINT *points;
int tabsheight = tabsrect.Height();
int halfheight = tabsheight/2;
int textextra = 10; // extra spacing around text
int taboff = 4;
int ydir, row0, row1, row2, row3;
points = tabpoints[rgnnum];
mydc.SelectObject(*tabfont);
SetBkMode(mydc, TRANSPARENT);
GetTabName(tabnum, tabname);
GetTextExtentPoint(mydc, tabname, static_cast<int>(_tcslen(tabname)),&textsize);
tabsize = textsize.cx + textextra + taboff + taboff;
if (toff+tabsize+2*taboff > tabsrect.right){ // no room for this one
tabsize = 0;
goto exit;
}
if (tabloc == LOC_BOTTOM) {
row0 = tabsrect.top - 5;
row1 = tabsrect.top;
row2 = row1+halfheight;
row3 = row1+tabsheight;
ydir = 1;
textrect = TRect(toff+taboff, row1+2, toff+taboff+textsize.cx+10, row3);
}
else { // LOC_TOP
row0 = tabsrect.bottom + 4;
row1 = tabsrect.bottom - 1;
row2 = row1-halfheight;
row3 = row1-tabsheight;
ydir = -1;
textrect = TRect(toff+taboff, row3+2, toff+taboff+textsize.cx+10, row1);
}
if (erasetabs){ // erase as we draw
mydc.SelectObject(*bgbrush);
FASTRECT(mydc, toff+1, row2, tabsize+1, ydir*(halfheight+3));
}
mydc.SelectObject(*framepen);
mydc.SelectObject(*facebrush);
// draw tab "tabnum"
if ((tabnum == activetab) || (! rgnnum)){
TBrush *endbrush = shadowbrush;
int delta = 0;
int myrow = row1;
if (tabnum == activetab){
mydc.SelectObject(*tabbrush);
endbrush = tabbrush;
delta = 2;
myrow = row0;
}
points[0] = TPoint(toff-taboff-delta, myrow);
points[1] = TPoint(toff+taboff, row3);
points[2] = TPoint(points[1].x+textsize.cx+textextra, row3);
points[3] = TPoint(points[2].x+taboff+taboff+delta, myrow);
points[4] = points[0];
bp = 1;
Polygon(mydc, points, 5);
// draw top shadow line (or erase any such line for active tab)
mydc.SelectObject(*endbrush);
FASTHLINE(mydc, points[0].x, points[0].y, points[3].x-points[0].x-1);
}
else {
points[0] = TPoint(toff+taboff, row1);
points[1] = TPoint(toff, row2);
points[2] = TPoint(toff+taboff, row3);
points[3] = TPoint(points[2].x+textsize.cx+textextra, row3);
points[4] = TPoint(points[3].x+taboff+taboff, row1);
bp = 2;
Polygon(mydc, points, 5);
// draw top shadow line
mydc.SelectObject(*shadowbrush);
FASTHLINE(mydc, points[0].x, points[0].y, points[4].x-points[0].x-1);
// redraw tab shadow for previous tab (Polygon erased part of it)
mydc.SelectObject(*shadowpen);
mydc.MoveTo(toff-taboff+1, row3+ydir);
mydc.LineTo(toff+taboff+1, row1-ydir);
}
// draw tab shadow for this tab
mydc.SelectObject(*shadowpen);
mydc.MoveTo(points[bp].x+1, points[bp].y+ydir);
mydc.LineTo(points[bp+1].x+1, points[bp+1].y+ydir);
mydc.LineTo(points[bp+2].x+1, points[bp+2].y-ydir);
// draw text inside tab
mydc.SelectObject(*framepen);
mydc.DrawText(tabname, -1, textrect, DT_CENTER);
exit:
mydc.RestoreFont();
return(tabsize);
}
//---------------------------------------------------------------------------
int TNotebook::DrawVertTab(TDC &mydc, int tabnum, int rgnnum, int toff)
{
_TCHAR tabname[MAXTABNAMELEN+1];
SIZE textsize;
int tabsize, bp, xval, yval;
TRect textrect;
POINT *points;
int tabswidth = tabsrect.Width();
int halfwidth = tabswidth/2;
int textextra = 10; // extra spacing around text
int taboff = 4;
int xdir, col0, col1, col2, col3;
points = tabpoints[rgnnum];
mydc.SelectObject(*tabfont);
SetBkMode(mydc, TRANSPARENT);
GetTabName(tabnum, tabname);
GetTextExtentPoint(mydc, tabname, static_cast<int>(_tcslen(tabname)), &textsize);
tabsize = textsize.cx + textextra + taboff + taboff;
if (toff+tabsize+2*taboff > tabsrect.bottom){ // no room for this one
tabsize = 0;
goto exit;
}
if (tabloc == LOC_LEFT){
col0 = tabsrect.right + 4;
col1 = col0-5;
col2 = col1-halfwidth;
col3 = col1-tabswidth;
xdir = -1;
textrect = TRect(col3, toff+taboff, col1-2, toff+taboff+textsize.cx+10);
}
else { // LOC_RIGHT
col0 = tabsrect.left - 5;
col1 = col0+5;
col2 = col1+halfwidth;
col3 = col1+tabswidth;
xdir = 1;
textrect = TRect(col1, toff+taboff+2, col3-2, toff+taboff+textsize.cx+10);
}
if (erasetabs){ // erase as we draw
mydc.SelectObject(*bgbrush);
FASTRECT(mydc, col2, toff+1, xdir*(halfwidth+3), tabsize+1);
}
mydc.SelectObject(*framepen);
mydc.SelectObject(*facebrush);
// draw tab "tabnum"
if ((tabnum == activetab) || (! rgnnum)) {
TBrush *endbrush = shadowbrush;
int delta = 0;
int mycol = col1;
if (tabnum == activetab) {
mydc.SelectObject(*tabbrush);
endbrush = tabbrush;
delta = 2;
mycol = col0;
}
points[0] = TPoint(mycol, toff-taboff-delta);
points[1] = TPoint(col3, toff+taboff);
points[2] = TPoint(col3, points[1].y+textsize.cx+textextra);
points[3] = TPoint(mycol, points[2].y+taboff+taboff+delta);
points[4] = points[0];
Polygon(mydc, points, 5);
mydc.SelectObject(*endbrush);
// draw top shadow line (or erase any such line for active tab)
FASTVLINE(mydc, points[0].x, points[0].y, points[3].y-points[0].y);
bp = 1;
}
else {
points[0] = TPoint(col1, toff+taboff);
points[1] = TPoint(col2, toff);
points[2] = TPoint(col3, toff+taboff);
points[3] = TPoint(col3, points[2].y+textsize.cx+textextra);
points[4] = TPoint(col1, points[3].y+taboff+taboff);
bp = 2;
Polygon(mydc, points, 5);
mydc.SelectObject(*shadowbrush);
// draw top shadow line
FASTVLINE(mydc, points[0].x, points[0].y, points[4].y-points[0].y);
// draw part of tab shadow for previous tab
mydc.SelectObject(*shadowpen);
mydc.MoveTo(points[0].x+1, points[0].y);
mydc.LineTo(points[1].x, points[1].y+2);
}
// draw tab shadow for this tab
mydc.SelectObject(*shadowpen);
mydc.MoveTo(points[bp].x+xdir, points[bp].y);
mydc.LineTo(points[bp+1].x+xdir, points[bp+1].y);
mydc.LineTo(points[bp+2].x-xdir, points[bp+2].y);
// draw text
mydc.SelectObject(*framepen);
xval = textrect.right; // vert text is wierd...
yval = textrect.top + (textrect.Height() - textsize.cx)/2;
mydc.TextOut(xval, yval, tabname, static_cast<int>(_tcslen(tabname)));
exit:
mydc.RestoreFont();
return(tabsize);
}
//----------------------------------------------------------------------------
void TNotebook::DrawTabs(TDC& mydc)
{
int tabnum = firsttab;
int tsize, toff;
if (tabhorz)
toff = tabsrect.left + 22;
else
toff = tabsrect.top + 22;
rgncnt = 0;
while (1) {
if (tabhorz)
tsize = DrawHorzTab(mydc, tabnum, rgncnt, toff);
else
tsize = DrawVertTab(mydc, tabnum, rgncnt, toff);
if (! tsize)
break;
toffs[rgncnt++] = toff;
toff += tsize;
if (rgncnt >= MAXTABSSHOWN)
break;
if (++tabnum >= tabcnt)
break;
}
if (erasetabs) { // erase as we draw
if (tabhorz)
EraseLastHorz(mydc, toff);
else
EraseLastVert(mydc, toff);
}
}
//----------------------------------------------------------------------------
void TNotebook::EraseLastVert(TDC &mydc, int toff)
{
int tabswidth = tabsrect.Width();
POINT points[5];
int halfwidth = tabswidth/2;
int col0, col1, col2, col3;
int taboff = 4;
if (tabloc == LOC_RIGHT) {
col0 = tabsrect.left;
col1 = col0 + 1;
col2 = col0 + halfwidth;
col3 = col0 + tabswidth + 2;
}
else {
col0 = tabsrect.right;
col1 = col0 - 1;
col2 = col0 - halfwidth;
col3 = col0 - (tabswidth + 2);
}
mydc.SelectStockObject(NULL_PEN);
mydc.SelectObject(*bgbrush);
toff += 2;
points[0] = TPoint(col1, toff+taboff);
points[1] = TPoint(col2, toff);
points[2] = TPoint(col3, toff);
points[3] = TPoint(col3, tabsrect.bottom+2);
points[4] = TPoint(col1, tabsrect.bottom+2);
Polygon(mydc, points, 5);
erasetabs = FALSE;
}
//----------------------------------------------------------------------------
void TNotebook::EraseLastHorz(TDC &mydc, int toff)
{
int tabsheight = tabsrect.Height();
POINT points[5];
int halfheight = tabsheight/2;
int row0, row1, row2, row3;
int taboff = 4;
if (tabloc == LOC_BOTTOM) {
row0 = tabsrect.top;
row1 = row0 + 1;
row2 = row0 + halfheight;
row3 = row0 + tabsheight + 2;
}
else {
row0 = tabsrect.bottom;
row1 = row0 - 1;
row2 = row0 - halfheight;
row3 = row0 - (tabsheight + 2);
}
mydc.SelectStockObject(NULL_PEN);
mydc.SelectObject(*bgbrush);
toff += 2;
points[0] = TPoint(toff+taboff, row1);
points[1] = TPoint(toff, row2);
points[2] = TPoint(toff, row3);
points[3] = TPoint(tabsrect.right+2, row3);
points[4] = TPoint(tabsrect.right+2, row1);
Polygon(mydc, points, 5);
erasetabs = FALSE;
}
//----------------------------------------------------------------------------
void TNotebook::DrawBackground(TDC &mydc, TRect &myrect, int paintcontrol)
{
if (paintcontrol == NBC_PAINTALL)
mydc.FillRect(myrect, *bgbrush);
else
erasetabs = TRUE;
}
//----------------------------------------------------------------------------
void
TNotebook::DrawTabLines(TDC& mydc, TRect& myrect, bool shadowline)
{
int width = myrect.right - myrect.left;
int height = myrect.bottom - myrect.top;
int tabstart, row, col, dir;
if (tabhorz){
tabstart = tabsrect.left;
if (tabloc == LOC_BOTTOM) {
dir = 1;
row = myrect.top;
}
else {
row = myrect.bottom-1;
dir = -1;
}
mydc.SelectObject(*framebrush);
FASTHLINE(mydc, myrect.left, row, width);
FASTVLINE(mydc, tabstart, row, dir*2);
FASTHLINE(mydc, tabstart, row+dir*2, myrect.right-tabstart);
FASTVLINE(mydc, tabstart+3, row+dir*2, dir*2);
FASTHLINE(mydc, tabstart+3, row+dir*4, myrect.right-tabstart-3);
mydc.SelectObject(*default_tabbrush);
FASTHLINE(mydc, tabstart+1, row+dir*1, myrect.right-tabstart-1);
FASTHLINE(mydc, tabstart+4, row+dir*3, myrect.right-tabstart-4);
if (shadowline) {
mydc.SelectObject(*shadowbrush);
FASTHLINE(mydc, tabstart+5, row+dir*5, myrect.right-tabstart-5);
}
}
else { // left or right
tabstart = tabsrect.top;
if (tabloc == LOC_LEFT){
col = myrect.right-1;
dir = -1;
}
else {
col = myrect.left;
dir = 1;
}
mydc.SelectObject(*framebrush);
FASTVLINE(mydc, col, myrect.top, height);
FASTHLINE(mydc, col, tabstart, dir*2);
FASTVLINE(mydc, col+dir*2, tabstart, myrect.bottom-tabstart);
FASTHLINE(mydc, col+dir*2, tabstart+3, dir*2);
FASTVLINE(mydc, col+dir*4, tabstart+3, myrect.bottom-tabstart-3);
mydc.SelectObject(*default_tabbrush);
FASTVLINE(mydc, col+dir, tabstart+1, myrect.bottom-tabstart-1);
FASTVLINE(mydc, col+dir*3, tabstart+4, myrect.bottom-tabstart-4);
if (shadowline) {
mydc.SelectObject(*shadowbrush);
FASTVLINE(mydc, col+dir*5, tabstart+5, myrect.bottom-tabstart-5);
}
}
}
//----------------------------------------------------------------------------
void
TNotebook::CalcTabRects()
{
int nleft, ntop, nright, nbottom, nwidth, nheight;
int hwidth, hheight, vwidth, vheight, tsblong, tsbshort;
nleft = nbcrect.left;
ntop = nbcrect.top;
nright = nbcrect.right;
nbottom = nbcrect.bottom;
nwidth = nbcrect.right - nbcrect.left;
nheight = nbcrect.bottom - nbcrect.top;
// tab scrollbar's size is fixed to match font (doesn't shrink with window)
if (tabhorz)
tsbshort = 8 + nheight/3;
else
tsbshort = 8 + nwidth/3;
tsblong = 1 + 5*(tsbshort-5);
if(hscrollon){
hwidth = hsbrect.Width();
hheight = hsbrect.Height();
}
else
hheight = hwidth = 0;
if (vscrollon){
vwidth = vsbrect.Width();
vheight = vsbrect.Height();
}
else
vwidth = vheight = 0;
switch (tabloc) {
case LOC_LEFT:
tsbrect = TRect(nleft+2, ntop+2, nleft+2+tsbshort, ntop+2+tsblong);
///YB tabsrect = TRect(nleft+5,tsbrect.bottom-16,nright-5,nbottom-(5+hheight));
tabsrect = TRect(nleft+4,tsbrect.bottom-18,nright-4,nbottom-(4+hheight));
break;
case LOC_RIGHT:
tsbrect = TRect(nleft+3, ntop+3, nleft+3+tsbshort, ntop+3+tsblong);
tabsrect = TRect(nleft+5, tsbrect.bottom-18, nright-5,nbottom-(vheight+5));
break;
case LOC_TOP:
tsbrect = TRect(nleft+2, ntop+1, nleft+2+tsblong, ntop+1+tsbshort);
tabsrect = TRect(tsbrect.right-18, ntop+3, nright-(5+vwidth),nbottom-4);
break;
case LOC_BOTTOM:
///YB tsbrect = TRect(nleft+4, ntop+9, nleft+4+tsblong,ntop+9+tsbshort);
///YB tabsrect = TRect(tsbrect.right-16, ntop+5, nright-(hwidth+5),nbottom-6);
tsbrect = TRect(nleft+2, ntop+6, nleft+2+tsblong,ntop+6+tsbshort);
tabsrect = TRect(tsbrect.right-18, ntop+2, nright-(hwidth+5),nbottom-4);
break;
}
}
//----------------------------------------------------------------------------
void TNotebook::ComputeSizes()
{
int cleft, ctop, cright, cbottom, cwidth, cheight;
int vswidth, hsheight;
if ((!GetHandle()) || (clientrect == clientprev)) // no size change
return;
clientprev = clientrect;
if (vscrollon)
vswidth = GetSystemMetrics(SM_CXVSCROLL);
else
vswidth = 0;
if (hscrollon)
hsheight = GetSystemMetrics(SM_CYHSCROLL);
else
hsheight = 0;
cleft = clientrect.left;
ctop = clientrect.top;
cright = clientrect.right;
cbottom = clientrect.bottom;
cwidth = clientrect.right - clientrect.left;
cheight = clientrect.bottom - clientrect.top;
// calculate rects: nbcrect, hsbrect, vsbrect, tsbrect, tabsrect
// remember: overlap standalone scrollbars with surround win borders
switch (tabloc){
case LOC_LEFT:
nbcrect = TRect(cleft-nbcheight, ctop, cleft, cbottom+hsheight);
if (hscrollon)
hsbrect = TRect(cleft-1, cbottom, cright+1, cbottom+hsheight);
if (vscrollon)
vsbrect = TRect(cright, ctop-1, cright+vswidth, cbottom+1);
CalcTabRects();
break;
case LOC_TOP:
nbcrect = TRect(cleft, ctop-nbcheight, cright+vswidth, ctop);
if (hscrollon)
hsbrect = TRect(cleft-1, cbottom, cright+1, cbottom+hsheight);
if (vscrollon)
vsbrect = TRect(cright, ctop-1, cright+vswidth, cbottom+1);
CalcTabRects();
break;
case LOC_RIGHT:
nbcrect = TRect(cright, ctop, cright+nbcheight, cbottom);
if (hscrollon)
hsbrect = TRect(cleft-1, cbottom, cright+1, cbottom+hsheight);
if (vscrollon)
vsbrect = TRect(cright+3, ctop+3*cheight/4, cright+3+vswidth,cbottom-2);
CalcTabRects();
break;
case LOC_BOTTOM:
///YB nbcrect = TRect(cleft, cbottom, cright, cbottom+nbcheight);
nbcrect = TRect(cleft, cbottom, cright, cbottom+nbcheight);
if (hscrollon)
hsbrect = TRect(cleft+3*cwidth/4, cbottom+7, cright-2,cbottom+7+hsheight);
if (vscrollon)
vsbrect = TRect(cright, ctop-1, cright+vswidth, cbottom+1);
CalcTabRects();
break;
}
if (winhscroll)
winhscroll->ChangeRect(hsbrect, false);
if (winvscroll)
winvscroll->ChangeRect(vsbrect, false);
if (tabhscroll)
tabhscroll->ChangeRect(tsbrect, false);
if (tabvscroll)
tabvscroll->ChangeRect(tsbrect, false);
}
//----------------------------------------------------------------------------
uint TNotebook::EvNCCalcSize(bool calcValidRects,
NCCALCSIZE_PARAMS & calcSize)
{
UINT status;
RECT *rp;
int vswidth, hsheight;
TPoint wtopleft;
// get upperleft corner of window in screen
rp = &calcSize.rgrc[0]; // window rect in screen coords
wtopleft = TPoint(rp->left, rp->top);
status = TWindow::EvNCCalcSize(calcValidRects, calcSize);
rp = &calcSize.rgrc[0]; // client rect in screen coords
if (!IsIconic()){
// change size of client window to allow for our area & scrollbars
// subtrack "1" from scrollbar sizes (overlap last line with win border)
vswidth = GetSystemMetrics(SM_CXVSCROLL) - 1;
hsheight = GetSystemMetrics(SM_CYHSCROLL) - 1;
switch (tabloc) {
case LOC_LEFT:
rp->left += nbcheight;
if (vscrollon)
rp->right -= vswidth;
if (hscrollon)
rp->bottom -= hsheight;
break;
case LOC_TOP:
rp->top += nbcheight;
if (vscrollon)
rp->right -= vswidth;
if (hscrollon)
rp->bottom -= hsheight;
break;
case LOC_RIGHT:
rp->right -= nbcheight;
if (hscrollon)
rp->bottom -= hsheight;
break;
case LOC_BOTTOM:
rp->bottom -= nbcheight;
if (vscrollon)
rp->right -= vswidth;
break;
}
if (rp->bottom < rp->top)
rp->bottom = rp->top;
if (rp->right < rp->left)
rp->right = rp->left;
if (defer_ncpaint >= 0)
defer_ncpaint++; // skip next ncpaint
}
clientrect = TRect(*rp);
clientrect -= wtopleft; // win-relative client rect
return(status);
}
//----------------------------------------------------------------------------
void TNotebook::ActivateTab(int tabnum)
{
TRect myrect;
int oldactive, r;
if (activetab != tabnum){
oldactive = activetab;
activetab = tabnum;
Parent->SendMessage(NB_TABCHANGED, activetab, NULL);
if (IsIconic())
return;
// repaint lines
TWindowDC mydc(*this);
DrawTabLines(mydc, nbcrect, FALSE);
// repaint old tab and tab before it as nonactive
r = oldactive - firsttab - 1;
if ((r >= 0) && (r < rgncnt)) {
if (tabhorz)
DrawHorzTab(mydc, oldactive-1, r, toffs[r]);
else
DrawVertTab(mydc, oldactive-1, r, toffs[r]);
}
if ((r+1 >= 0) && (r+1 < rgncnt)) {
if (tabhorz)
DrawHorzTab(mydc, oldactive, r+1, toffs[r+1]);
else
DrawVertTab(mydc, oldactive, r+1, toffs[r+1]);
}
// paint new active tab
r = activetab - firsttab;
if ((r >= 0) && (r < rgncnt)) {
if (tabhorz)
DrawHorzTab(mydc, activetab, r, toffs[r]);
else
DrawVertTab(mydc, activetab, r, toffs[r]);
}
}
}
//----------------------------------------------------------------------------
void TNotebook::ScrollTabs(int delta)
{
int oldfirst;
oldfirst = firsttab;
firsttab += delta;
if (firsttab < 0)
firsttab = 0;
else if (firsttab > tabcnt-1)
firsttab = tabcnt-1;
if (firsttab != oldfirst) {
if (tabhscroll)
tabhscroll->SetScrollPos(firsttab, TRUE);
if (tabvscroll)
tabvscroll->SetScrollPos(firsttab, TRUE);
PaintNBC(NBC_PAINTTABS);
}
}
//----------------------------------------------------------------------------
bool
TNotebook::MyLButtonDown(uint hitTest, TPoint& screenPt)
{
int i;
bool match;
HRGN myrgn;
TPoint winpt = screenPt - GetWindowRect().TopLeft(); // win coords
if (nbcrect.Contains(winpt)) {
// see if mouse is on tab hscrollbar
if ((tabhscroll) && (tabhscroll->MyLButtonDown(hitTest, winpt)))
return true;
// see if mouse is on tab vscrollbar
if ((tabvscroll) && (tabvscroll->MyLButtonDown(hitTest, winpt)))
return true;
// see if mouse down is in tabs
for (i=rgncnt-1; i >= 0; i--) {
myrgn = CreatePolygonRgn(tabpoints[i], 5, fillmode);
match = PtInRegion(myrgn, winpt.x, winpt.y);
DeleteObject(myrgn);
if (match) {
ActivateTab(firsttab+i);
return true;
}
}
}
// see if mouse is on window hscrollbar
if ((hscrollon) && (winhscroll->MyLButtonDown(hitTest, winpt)))
return true;
// see if mouse is on window vscrollbar
if ((vscrollon) && (winvscroll->MyLButtonDown(hitTest, winpt)))
return true;
return false;
}
//----------------------------------------------------------------------------
void
TNotebook::EvNCLButtonDown(uint hitTest, const TPoint& point)
{
TPoint p(point);
if (MyLButtonDown(hitTest, p))
return;
TWindow::EvNCLButtonDown(hitTest, point);
}
//----------------------------------------------------------------------------
void
TNotebook::EvNCLButtonDblClk(uint hitTest, const TPoint& point)
{
TPoint p(point);
if (MyLButtonDown(hitTest, p))
return;
TWindow::EvNCLButtonDblClk(hitTest, point);
}
//----------------------------------------------------------------------------
void
TNotebook::EvMouseMove(uint hitTest, const TPoint& point)
{
// convert from client to windows coords
TPoint screenpt = MapClientToScreen(point);
TPoint winpt = screenpt - GetWindowRect().TopLeft(); // win coords
// see if mouse has been captured by tab hscrollbar
if ((tabhscroll) && (tabhscroll->MyMouseMove(hitTest, winpt)))
return;
// see if mouse has been captured by tab vscrollbar
if ((tabvscroll) && (tabvscroll->MyMouseMove(hitTest, winpt)))
return;
// see if mouse has been captured by window hscrollbar
if ((hscrollon) && (winhscroll->MyMouseMove(hitTest, winpt)))
return;
// see if mouse has been captured by window vscrollbar
if ((vscrollon) && (winvscroll->MyMouseMove(hitTest, winpt)))
return;
TWindow::EvNCMouseMove(hitTest, point);
}
//----------------------------------------------------------------------------
void
TNotebook::EvLButtonUp(uint hitTest, const TPoint& point)
{
// convert from client to windows coords
TPoint screenpt = MapClientToScreen(point);
TPoint winpt = screenpt - GetWindowRect().TopLeft(); // win coords
// see if mouse has been captured by tab hscrollbar
if ((tabhscroll) && (tabhscroll->MyLButtonUp(hitTest, winpt)))
return;
// see if mouse has been captured by tab vscrollbar
if ((tabvscroll) && (tabvscroll->MyLButtonUp(hitTest, winpt)))
return;
// see if mouse has been captured by window hscrollbar
if ((hscrollon) && (winhscroll->MyLButtonUp(hitTest, winpt)))
return;
// see if mouse has been captured by window vscrollbar
if ((vscrollon) && (winvscroll->MyLButtonUp(hitTest, winpt)))
return;
TWindow::EvNCLButtonUp(hitTest, point);
}
//----------------------------------------------------------------------------
void
TNotebook::EvGetMinMaxInfo(MINMAXINFO & minmaxinfo)
{
TWindow::EvGetMinMaxInfo(minmaxinfo);
minmaxinfo.ptMinTrackSize.x += (nbcheight+2);
minmaxinfo.ptMinTrackSize.y += (nbcheight+2);
}
//----------------------------------------------------------------------------
void
TNotebook::SetTabCnt(int Tabcnt, int Firsttab, int Activetab)
{
tabcnt = Tabcnt;
firsttab = Firsttab;
ActivateTab(Activetab);
if (tabhscroll){
tabhscroll->SetScrollRange(0, tabcnt, false);
tabhscroll->SetScrollPos(activetab, true);
}
if (tabvscroll){
tabvscroll->SetScrollRange(0, tabcnt, false);
tabvscroll->SetScrollPos(activetab, true);
}
PaintNBC(NBC_PAINTTABS);
}
//----------------------------------------------------------------------------
bool
TNotebook::EvNCCreate(CREATESTRUCT & createStruct)
{
long wstyle;
bool status;
// we will draw hscroll and vscroll if needed; tell windows not to bother
wanthscroll = ((createStruct.style & WS_HSCROLL) != 0);
wantvscroll = ((createStruct.style & WS_VSCROLL) != 0);
// reset WS_HSCROLL and WH_VSCROLL in both style locations "just in case..."
createStruct.style &= ~(WS_HSCROLL | WS_VSCROLL);
wstyle = GetWindowLong(GWL_STYLE);
wstyle &= ~(WS_HSCROLL | WS_VSCROLL);
SetWindowLong(GWL_STYLE, wstyle);
status = TWindow::EvNCCreate(createStruct);
CreateScrollBars();
return(status);
}
//----------------------------------------------------------------------------
void
TNotebook::EvSize(uint sizeType, const TSize& newsize)
{
TWindow::EvSize(sizeType, newsize);
ComputeSizes();
if (! defer_ncpaint) {
defer_ncpaint = 1;
ForceResize(TRUE);
}
}
//----------------------------------------------------------------------------
LRESULT TNotebook::NWHscroll(TParam1 wparam, TParam2 lparam)
{
int thumbpos = LOWORD(lparam);
int ctrlid = HIWORD(lparam);
if (ctrlid != ID_TABSB)
return(0);
switch (wparam) {
case SB_LINELEFT:
ScrollTabs(-1);
break;
case SB_LINERIGHT:
ScrollTabs(1);
break;
case SB_PAGELEFT:
if (rgncnt < 2)
ScrollTabs(-1);
else
ScrollTabs(-(rgncnt-1));
break;
case SB_PAGERIGHT:
if (rgncnt < 2)
ScrollTabs(1);
else
ScrollTabs(rgncnt-1);
break;
case SB_THUMBPOSITION:
ScrollTabs(thumbpos-firsttab);
break;
}
return(0);
}
//----------------------------------------------------------------------------
void TNotebook::CreateScrollBars()
{
if (tabhorz){
tabhscroll = new THScroll(this, 0, 0, 1, 1, ID_TABSB, 0, tabcnt-1, 0,
true, false, true);
}
else{
tabvscroll = new TVScroll(this, 0, 0, 1, 1, ID_TABSB, 0, tabcnt-1, 0,
true, false, true);
}
if (wanthscroll) {
winhscroll = new THScroll(this, 0, 0, 1, 1, ID_WINHSB, 0, 100, 0,
false, true, false);
hscrollon = true;
}
if (wantvscroll) {
winvscroll = new TVScroll(this, 0, 0, 1, 1, ID_WINVSB, 0, 100, 0,
false, true, false);
vscrollon = true;
}
}
//----------------------------------------------------------------------------
void
TNotebook::EvSysColorChange()
{
DeletePaintObjects();
BuildPaintObjects();
if (tabhscroll)
tabhscroll->SysColorChange();
if (tabvscroll)
tabvscroll->SysColorChange();
if (winhscroll)
winhscroll->SysColorChange();
if (winvscroll)
winvscroll->SysColorChange();
TWindow::EvSysColorChange();
}
//----------------------------------------------------------------------------
int
TNotebook::GetScrollPos(int bar)
{
if ((bar == SB_HORZ) && (winhscroll))
return(winhscroll->GetScrollPos());
else if ((bar == SB_VERT) && (winvscroll))
return(winvscroll->GetScrollPos());
return(0);
}
//----------------------------------------------------------------------------
void TNotebook::GetScrollRange(int bar, int& low, int& high)
{
if ((bar == SB_HORZ) && (winhscroll))
winhscroll->GetScrollRange(low, high);
else if ((bar == SB_VERT) && (winvscroll))
winvscroll->GetScrollRange(low, high);
}
//----------------------------------------------------------------------------
int TNotebook::SetScrollPos(int bar, int pos, bool redraw)
{
if ((bar == SB_HORZ) && (winhscroll))
return(winhscroll->SetScrollPos(pos, redraw));
else if ((bar == SB_VERT) && (winvscroll))
return(winvscroll->SetScrollPos(pos, redraw));
return 0;
}
//----------------------------------------------------------------------------
void TNotebook::SetScrollRange(int bar, int minPos, int maxPos, bool redraw)
{
bool showit = (minPos != maxPos);
if ((bar == SB_HORZ) && (winhscroll)){
if (hscrollon != showit) {
hscrollon = showit;
winhscroll->ShowScrollBar(showit);
ForceResize(FALSE);
}
winhscroll->SetScrollRange(minPos, maxPos, redraw);
} else if ((bar == SB_VERT) && (winvscroll)) {
if (vscrollon != showit){
vscrollon = showit;
winvscroll->ShowScrollBar(showit);
ForceResize(FALSE);
}
winvscroll->SetScrollRange(minPos, maxPos, redraw);
}
}
//----------------------------------------------------------------------------
void TNotebook::ForceResize(bool repaint)
{
// force a RECALC SIZE and possibly REPAINT of non-client area thru
// following wierd code...
TRect wrect;
int width, height;
wrect = GetWindowRect();
TPoint tl = wrect.TopLeft();
TPoint br = wrect.BottomRight();
Parent->ScreenToClient(tl);
Parent->ScreenToClient(br);
width = br.x - tl.x;
height = br.y - tl.y;
MoveWindow(tl.x, tl.y, width, height+1, TRUE);
if (repaint)
defer_ncpaint = -1; // do ncpaint but don't call myself
MoveWindow(tl.x, tl.y, width, height, TRUE);
if (repaint)
defer_ncpaint = 0;
}
//----------------------------------------------------------------------------
void
TNotebook::BuildBgBrush()
{
struct {
BITMAPINFOHEADER hdr;
RGBQUAD colors[2];
} bmi;
HBITMAP mybitmap;
TWindowDC mydc(*this);
unsigned char bits[8*sizeof(DWORD)];
COLORREF color;
HBRUSH hbrush;
bmi.hdr.biSize = sizeof(BITMAPINFOHEADER);
bmi.hdr.biWidth = 8;
bmi.hdr.biHeight = 8;
bmi.hdr.biPlanes = 1;
bmi.hdr.biBitCount = 1;
bmi.hdr.biSizeImage = 0;
bmi.hdr.biCompression = BI_RGB;
bmi.hdr.biClrUsed = 0;
bmi.hdr.biClrImportant = 0;
memset(bits, 0, sizeof(bits));
bits[0 * sizeof(DWORD)] = 0xAA;
bits[2 * sizeof(DWORD)] = 0xAA;
bits[4 * sizeof(DWORD)] = 0xAA;
bits[6 * sizeof(DWORD)] = 0xAA;
bits[1 * sizeof(DWORD)] = 0x55;
bits[3 * sizeof(DWORD)] = 0x55;
bits[5 * sizeof(DWORD)] = 0x55;
bits[7 * sizeof(DWORD)] = 0x55;
color = GetSysColor(COLOR_BTNFACE);
bmi.colors[0].rgbRed = GetRValue(color);
bmi.colors[0].rgbGreen = GetGValue(color);
bmi.colors[0].rgbBlue = GetBValue(color);
bmi.colors[0].rgbReserved = 0;
color = GetSysColor(COLOR_BTNHIGHLIGHT);
bmi.colors[1].rgbRed = GetRValue(color);
bmi.colors[1].rgbGreen = GetGValue(color);
bmi.colors[1].rgbBlue = GetBValue(color);
bmi.colors[1].rgbReserved = 0;
mybitmap = ::CreateDIBitmap(mydc, &bmi.hdr, CBM_INIT, bits,
(LPBITMAPINFO)&bmi, DIB_RGB_COLORS);
hbrush = ::CreatePatternBrush(mybitmap);
bgbrush = new TBrush(hbrush);
::DeleteObject(mybitmap);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
TCustomScroll::TCustomScroll(TWindow* parent, int, int, int, int,
int /*idnum*/, bool Frame3d, bool Arrowline, bool Thumbmove, int Repeatdelay)
{
Parent = parent;
frame3d = Frame3d;
arrowline = Arrowline;
thumbmove = Thumbmove;
repeatdelay = Repeatdelay;
showit = true;
if (arrowline)
barsize = 1;
else
barsize = 2;
BuildBrushes();
}
//----------------------------------------------------------------------------
TCustomScroll::~TCustomScroll()
{
DeleteBrushes();
}
//----------------------------------------------------------------------------
void
TCustomScroll::DeleteBrushes()
{
delete framebrush;
delete trackbrush;
delete hilitebrush;
delete shadowbrush;
delete facebrush;
}
//----------------------------------------------------------------------------
void
TCustomScroll::BuildBrushes()
{
framebrush = new TBrush(GetSysColor(COLOR_WINDOWFRAME));
trackbrush = new TBrush(GetSysColor(COLOR_SCROLLBAR));
hilitebrush = new TBrush(GetSysColor(COLOR_BTNHIGHLIGHT));
shadowbrush = new TBrush(GetSysColor(COLOR_BTNSHADOW));
facebrush = new TBrush(GetSysColor(COLOR_BTNFACE));
}
//----------------------------------------------------------------------------
void
TCustomScroll::ShowScrollBar(bool show)
{
showit = show;
}
//----------------------------------------------------------------------------
void
TCustomScroll::SysColorChange()
{
DeleteBrushes();
BuildBrushes();
}
//----------------------------------------------------------------------------
int
TCustomScroll::GetScrollPos()
{
return curval;
}
//----------------------------------------------------------------------------
void
TCustomScroll::GetScrollRange(int& low, int& high)
{
low = lowval;
high = highval;
}
//----------------------------------------------------------------------------
void
TCustomScroll::AutoScrollMouse()
{
MSG loopMsg;
DWORD delayticks;
loopMsg.message = 0;
Parent->SetCapture();
delayticks = repeatdelay + GetTickCount();
while (loopMsg.message != WM_LBUTTONUP &&
(loopMsg.message != WM_MOUSEMOVE ||(loopMsg.wParam&MK_LBUTTON))) {
if (::PeekMessage(&loopMsg, 0, 0, 0, PM_REMOVE)) {
::TranslateMessage(&loopMsg);
::DispatchMessage(&loopMsg);
}
if (GetTickCount() > delayticks)
AutoScrollAction();
}
Parent->ReleaseCapture();
}
//----------------------------------------------------------------------------
void
TCustomScroll::ForcePaint()
{
MyPaint(CSB_FORCEALL);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
THScroll::THScroll(TWindow* Parent, int x, int y, int width, int height,
int idnum, int Lowval, int Highval, int initval, bool Frame3d,
bool Arrowline, bool Thumbmove, int Repeatdelay)
:
TCustomScroll(Parent, x, y, width, height,idnum,Frame3d, Arrowline,
Thumbmove, Repeatdelay)
{
SetScrollRange(Lowval, Highval, false);
SetScrollPos(initval, false);
mousedown = CSB_NOTDOWN;
displaystate = CSB_NOTDOWN;
mylongid = MkUint32(0, (uint16)idnum);
if (!idnum)
scrollmsg = WM_HSCROLL;
else
scrollmsg = NW_HSCROLL;
ChangeRect(TRect(x, y, x+width, y+height), false);
}
//----------------------------------------------------------------------------
THScroll::~THScroll()
{
}
//----------------------------------------------------------------------------
void
THScroll::ChangeRect(const TRect& newrect, bool repaint)
{
int height = newrect.Height();
int width = newrect.Width();
// set minimum sizes
if (height < 4)
height = 4;
if (width < 14)
width = 14;
framerect = TRect(newrect.left, newrect.top, newrect.left+width,
newrect.top+height);
if (frame3d) // will add 3d frame on outside
sbrect = framerect.InflatedBy(-1, -1);
else
sbrect = framerect;
// compute a few measurements here to make our life easier
sbheight = sbrect.bottom - sbrect.top;
sbwidth = sbrect.right - sbrect.left;
sqsize = sbheight - 2;
trackwidth = sbwidth - 2*(sqsize + barsize); // overlaps arrow lines
trange = trackwidth - (sqsize+2);
trackxoff = sbrect.left + sqsize + barsize; // start on outer left arrow bar
SetScrollPos(curval, SV_NOREPAINT);
if (repaint)
MyPaint(CSB_FORCEALL);
}
//----------------------------------------------------------------------------
void
THScroll::DrawFrames(TDC& mydc)
{
if (frame3d) // outer 3d frame
DrawShadeFrame(mydc, framerect, false);
// draw inner frame (avoid flicker by not painting interrior)
mydc.FrameRect(sbrect, *framebrush);
// draw double black lines for left and right buttons
mydc.SelectObject(*framebrush);
FASTRECT(mydc, sbrect.left+sqsize+1, sbrect.top, barsize, sbheight);
FASTRECT(mydc, sbrect.right-(sqsize+1+barsize), sbrect.top, barsize,
sbheight);
}
//----------------------------------------------------------------------------
void
THScroll::DrawLeftArrow(TDC& mydc, bool isdown)
{
TRect myrect(sbrect.left+1, sbrect.top+1, sbrect.left+sqsize+1,
sbrect.bottom-1);
DrawArrowButton(mydc, myrect, isdown, true);
}
//----------------------------------------------------------------------------
void
THScroll::DrawRightArrow(TDC& mydc, bool isdown)
{
TRect myrect(sbrect.right-(sqsize+1), sbrect.top+1, sbrect.right-1,
sbrect.bottom-1);
DrawArrowButton(mydc, myrect, isdown, false);
}
//----------------------------------------------------------------------------
void
THScroll::DrawLeftTrack(TDC& mydc, bool isdown)
{
if (isdown)
mydc.SelectObject(*shadowbrush);
else
mydc.SelectObject(*trackbrush);
FASTRECT(mydc, trackxoff, sbrect.top+barsize, thumbxoff-trackxoff,
sbheight-2);
}
//----------------------------------------------------------------------------
void
THScroll::DrawRightTrack(TDC& mydc, bool isdown)
{
int xoff = thumbxoff+sqsize+2;
int lastx = trackxoff + trackwidth - 1;
if (isdown)
mydc.SelectObject(*shadowbrush);
else
mydc.SelectObject(*trackbrush);
FASTRECT(mydc, xoff, sbrect.top+1, lastx-xoff+1, sbheight-2);
}
//----------------------------------------------------------------------------
void
THScroll::DrawThumb(TDC& mydc, bool drawfocus, bool erasefocus)
{
if ((erasefocus) && (lastfocusxoff >= 0)){
mydc.DrawFocusRect(lastfocusxoff, sbrect.top, lastfocusxoff+sqsize+2,
sbrect.top+sbheight);
}
if (drawfocus){
mydc.DrawFocusRect(thumbxoff, sbrect.top, thumbxoff+sqsize+2,
sbrect.top+sbheight);
lastfocusxoff = thumbxoff;
return;
}
// draw thumb track (but don't cover two outside black lines)
mydc.SelectObject(*trackbrush);
FASTRECT(mydc, trackxoff+1, sbrect.top+1, trackwidth-2, sbheight-2);
// draw black lines on each side of solid thumb
mydc.SelectObject(*framebrush);
FASTVLINE(mydc, thumbxoff, sbrect.top, sbheight);
FASTVLINE(mydc, thumbxoff+sqsize+1, sbrect.top, sbheight);
// draw solid thumb
mydc.SelectObject(*facebrush);
FASTRECT(mydc, thumbxoff+1, sbrect.top+1, sqsize, sqsize);
// draw shaded frame and extra "_|" design for solid thumb
TRect myrect(thumbxoff+1, sbrect.top+1, thumbxoff+sqsize+1,
sbrect.bottom-1);
DrawShadeFrame(mydc, myrect, true);
lastfocusxoff = -1;
}
//----------------------------------------------------------------------------
void
THScroll::DrawDownFrame(TDC& mydc, TRect& myrect)
{
// always a single width shadow line
mydc.SelectObject(*shadowbrush);
FASTHLINE(mydc, myrect.left, myrect.top, myrect.right-myrect.left);
FASTVLINE(mydc, myrect.left, myrect.top, myrect.bottom-myrect.top);
}
//----------------------------------------------------------------------------
void
THScroll::DrawShadeFrame(TDC& mydc, TRect& myrect, bool forthumb)
{
int width = myrect.right - myrect.left;
int height = myrect.bottom - myrect.top;
mydc.SelectObject(*hilitebrush);
FASTHLINE(mydc, myrect.left, myrect.top, width);
FASTVLINE(mydc, myrect.left, myrect.top, height);
if (sqsize > 15) { // double highlight
FASTHLINE(mydc, myrect.left, myrect.top+1, width);
FASTVLINE(mydc, myrect.left+1, myrect.top, height);
}
mydc.SelectObject(*shadowbrush);
FASTHLINE(mydc, myrect.left, myrect.bottom-1, width);
FASTVLINE(mydc, myrect.right-1, myrect.top, height);
if ((forthumb) || (sqsize >= 15)) { // double shadow
FASTHLINE(mydc, myrect.left+1, myrect.bottom-2, width-1);
FASTVLINE(mydc, myrect.right-2, myrect.top+1, height-1);
}
}
//---------------------------------------------------------------------------
void
THScroll::DrawArrowButton(TDC& mydc, TRect& brect, bool isdown, bool left)
{
int xoff, yoff, width, height, downoff, aheight, awidth;
int lheight, lwidth, mywidth, delta;
// draw button background
mydc.FillRect(brect, *facebrush);
// draw frame around button
if (isdown)
DrawDownFrame(mydc, brect);
else
DrawShadeFrame(mydc, brect, FALSE);
// calculations for drawing arrow line and head
width = brect.right - brect.left;
height = brect.bottom - brect.top;
if (isdown)
downoff = 1;
else
downoff = 0;
mydc.SelectObject(*framebrush); // for drawing arrows
aheight = 2 + (height+1)/3;
if (! (aheight%2)) // need an odd numbered arrow height
aheight--;
awidth = (aheight+1)/2;
if (arrowline)
lwidth = awidth-1;
else
lwidth = 0;
mywidth = awidth + lwidth;
delta = width - mywidth;
xoff = brect.left + delta/2; // where whole object should start
if (delta%2) // odd number - put extra space on left
xoff++;
if (arrowline) { // draw arrow line
if (left)
xoff += awidth; // xoff is now where line starts
lheight = (aheight+2)/3;
yoff = brect.top + (height/2 - lheight/2);
FASTRECT(mydc, xoff+downoff, yoff+downoff, lwidth, lheight);
if (left)
xoff--;
else
xoff += lwidth;
}else if (left)
xoff += (awidth-1);
// xoff is now where back line of arrow should be drawn
yoff = brect.top + (height/2 - aheight/2);
// draw arrow head
while (aheight > 0) {
FASTVLINE(mydc, xoff+downoff, yoff+downoff, aheight);
aheight -= 2;
if (left)
xoff--;
else
xoff++;
yoff++;
}
}
//---------------------------------------------------------------------------
void
THScroll::MyPaint(int newstate)
{
if ((!Parent->GetHandle())||(Parent->IsIconic())||(!showit))
return;
bool forceall = (newstate == CSB_FORCEALL);
if ((! forceall) && (newstate == displaystate) &&
(newstate <= CSB_RIGHTTHUMB))
return; // already drawn
bool doleft = (displaystate==CSB_LEFTARROW) || (newstate==CSB_LEFTARROW);
bool doright = (displaystate==CSB_RIGHTARROW) || (newstate==CSB_RIGHTARROW);
bool dothumb = (displaystate>=CSB_LEFTTHUMB) || (newstate>=CSB_LEFTTHUMB);
if (newstate <= CSB_RIGHTTHUMB)
displaystate = newstate;
TWindowDC mydc(*Parent);
if (forceall)
DrawFrames(mydc);
if ((forceall) || (doleft))
DrawLeftArrow(mydc, (displaystate==CSB_LEFTARROW));
if ((forceall) || (doright))
DrawRightArrow(mydc, (displaystate==CSB_RIGHTARROW));
if ((forceall) || (dothumb)) {
DrawThumb(mydc, (displaystate==CSB_THUMBFOCUS),
(displaystate==CSB_THUMBFOCUS));
if (displaystate == CSB_LEFTTHUMB) // gray to left of thumb
DrawLeftTrack(mydc, TRUE);
else if (displaystate == CSB_RIGHTTHUMB) // gray to right of thumb
DrawRightTrack(mydc, TRUE);
}
}
//----------------------------------------------------------------------------
int
THScroll::SetScrollPos(int newval, int repaint)
{
int oldval = curval;
curval = std::min(std::max(newval, lowval), highval);
// reposition thumb to match new value
thumbxoff = (int)(trackxoff + ((LONG)trange*(curval-lowval))/vrange);
if (repaint == SV_REPAINT)
MyPaint(CSB_THUMB);
else if (repaint == SV_THUMBTRACK)
MyPaint(thumbmove ? CSB_THUMB : CSB_THUMBFOCUS);
return(oldval);
}
//----------------------------------------------------------------------------
void
THScroll::SetScrollRange(int low, int hi, bool redraw)
{
lowval = low;
highval = hi;
if (highval <= lowval)
highval = lowval + 1;
vrange = highval - lowval;
if (redraw)
MyPaint(CSB_FORCEALL);
}
//----------------------------------------------------------------------------
int
THScroll::GetMouseLoc(TPoint& winpt)
{
if ((Parent->IsIconic()) || (! sbrect.Contains(winpt)) || (! showit))
return CSB_NOTDOWN;
int myx = winpt.x;
int left = sbrect.left;
if (myx < left+sqsize+2)
return CSB_LEFTARROW;
if (myx > (left+sqsize+2+trackwidth))
return CSB_RIGHTARROW;
if (myx < thumbxoff)
return CSB_LEFTTHUMB;
if (myx > thumbxoff+sqsize+2)
return CSB_RIGHTTHUMB;
return CSB_THUMB;
}
//----------------------------------------------------------------------------
bool
THScroll::MyLButtonDown(uint /*hitTest*/, TPoint& winpt)
{
mousedown = GetMouseLoc(winpt);
if (mousedown == CSB_NOTDOWN) // mousedown not in scrollbar
return false;
origval = curval;
newloc = mousedown;
switch (mousedown) {
case CSB_LEFTARROW:
case CSB_RIGHTARROW:
MyPaint(mousedown);
break;
case CSB_LEFTTHUMB:
MyPaint(mousedown);
Parent->SendMessage(scrollmsg, SB_PAGELEFT, mylongid);
break;
case CSB_RIGHTTHUMB:
MyPaint(mousedown);
Parent->SendMessage(scrollmsg, SB_PAGERIGHT, mylongid);
break;
case CSB_THUMB:
thumbgrabxoff = winpt.x - thumbxoff;
SetScrollPos(curval, SV_THUMBTRACK);
}
AutoScrollMouse();
return true;
}
//----------------------------------------------------------------------------
bool
THScroll::MyMouseMove(uint /*hitTest*/, TPoint& winpt)
{
if (mousedown == CSB_NOTDOWN) // mousedown was not in our scrollbar
return false;
newloc = GetMouseLoc(winpt);
switch (mousedown) {
case CSB_LEFTARROW:
case CSB_RIGHTARROW:
case CSB_LEFTTHUMB:
case CSB_RIGHTTHUMB:
if (newloc == mousedown)
MyPaint(mousedown);
else
MyPaint(CSB_NOTDOWN);
break;
case CSB_THUMB:
if (newloc != CSB_NOTDOWN){ // anywhere inside sb
int newpos = (winpt.x - thumbgrabxoff) - trackxoff;
if (newpos < 0)
newpos = 0;
else if (newpos > trange)
newpos = trange;
int newval = (int)(lowval + ((LONG)vrange*newpos)/trange);
SetScrollPos(newval, SV_THUMBTRACK);
Parent->SendMessage(scrollmsg, SB_THUMBTRACK,
mylongid | newval);
} else {
SetScrollPos(origval, SV_THUMBTRACK);
Parent->SendMessage(scrollmsg, SB_THUMBTRACK,
mylongid | origval);
}
break;
}
return true;
}
//----------------------------------------------------------------------------
bool
THScroll::MyLButtonUp(uint /*hitTest*/, TPoint& winpt)
{
int sendval;
if (mousedown == CSB_NOTDOWN) // mousedown was not in our scrollbar
return false;
newloc = GetMouseLoc(winpt);
switch (mousedown){
case CSB_LEFTARROW:
MyPaint(CSB_NOTDOWN);
if (newloc == mousedown)
Parent->SendMessage(scrollmsg, SB_LINELEFT, mylongid);
break;
case CSB_RIGHTARROW:
MyPaint(CSB_NOTDOWN);
if (newloc == mousedown)
Parent->SendMessage(scrollmsg, SB_LINERIGHT, mylongid);
break;
case CSB_THUMB:
sendval = curval; // save off before overwritting
SetScrollPos(origval, SV_REPAINT);
Parent->SendMessage(scrollmsg, SB_THUMBPOSITION,
mylongid | sendval);
break;
default:
MyPaint(CSB_NOTDOWN);
break;
}
Parent->SendMessage(scrollmsg, SB_ENDSCROLL, mylongid);
mousedown = CSB_NOTDOWN;
return true;
}
//----------------------------------------------------------------------------
void
THScroll::AutoScrollAction()
{
if (newloc != mousedown)
return;
switch (mousedown) {
case CSB_LEFTARROW:
Parent->SendMessage(scrollmsg, SB_LINELEFT, mylongid);
break;
case CSB_RIGHTARROW:
Parent->SendMessage(scrollmsg, SB_LINERIGHT, mylongid);
break;
case CSB_LEFTTHUMB:
Parent->SendMessage(scrollmsg, SB_PAGELEFT, mylongid);
break;
case CSB_RIGHTTHUMB:
Parent->SendMessage(scrollmsg, SB_PAGERIGHT, mylongid);
break;
}
}
////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
TVScroll::TVScroll(TWindow* Parent, int x, int y, int width, int height,
int idnum, int Lowval, int Highval, int initval, bool Frame3d,
bool Arrowline, bool Thumbmove, int Repeatdelay)
:
TCustomScroll(Parent, x, y, width, height,idnum,Frame3d, Arrowline,
Thumbmove, Repeatdelay)
{
SetScrollRange(Lowval, Highval, false);
SetScrollPos(initval, false);
mousedown = CSB_NOTDOWN;
displaystate = CSB_NOTDOWN;
mylongid = MAKELONG(0, idnum);
if (!idnum)
scrollmsg = WM_VSCROLL;
else
scrollmsg = NW_VSCROLL;
ChangeRect(TRect(x, y, x+width, y+height), FALSE);
}
//----------------------------------------------------------------------------
TVScroll::~TVScroll()
{
}
//----------------------------------------------------------------------------
void
TVScroll::ChangeRect(const TRect& newrect, bool repaint)
{
int width = newrect.Width();
int height = newrect.Height();
// set minimum sizes
if (height < 14)
height = 14;
if (width < 4)
width = 4;
framerect = TRect(newrect.left, newrect.top, newrect.left+width,
newrect.top+height);
if (frame3d) // will add 3d frame on outside
sbrect = framerect.InflatedBy(-1, -1);
else
sbrect = framerect;
// compute a few measurements here to make our life easier
sbheight = sbrect.bottom - sbrect.top;
sbwidth = sbrect.right - sbrect.left;
sqsize = sbwidth - 2;
trackheight = sbheight - 2*(sqsize+barsize); // overlaps arrow lines
trange = trackheight - (sqsize+2);
trackyoff = sbrect.top + sqsize + barsize; // start on 2nd left arrow bar
SetScrollPos(curval, SV_NOREPAINT);
if (repaint)
MyPaint(CSB_FORCEALL);
}
//----------------------------------------------------------------------------
void
TVScroll::DrawFrames(TDC& mydc)
{
if (frame3d) // outer 3d frame
DrawShadeFrame(mydc, framerect, FALSE);
// draw inner frame (avoid flicker by not painting interrior)
mydc.FrameRect(sbrect, *framebrush);
// draw single/double black lines for top and bottom buttons
mydc.SelectObject(*framebrush);
FASTRECT(mydc, sbrect.left, sbrect.top+sqsize+1, sbwidth, barsize);
FASTRECT(mydc, sbrect.left, sbrect.bottom-(sqsize+barsize+1), sbwidth,
barsize);
}
//----------------------------------------------------------------------------
void
TVScroll::DrawTopArrow(TDC& mydc, bool isdown)
{
TRect myrect(sbrect.left+1, sbrect.top+1, sbrect.left+sqsize+1,
sbrect.top+sqsize+1);
DrawArrowButton(mydc, myrect, isdown, TRUE);
}
//----------------------------------------------------------------------------
void
TVScroll::DrawBottomArrow(TDC& mydc, bool isdown)
{
TRect myrect(sbrect.left+1, sbrect.bottom-(sqsize+1),
sbrect.left+sqsize+1, sbrect.bottom-1);
DrawArrowButton(mydc, myrect, isdown, FALSE);
}
//----------------------------------------------------------------------------
void
TVScroll::DrawTopTrack(TDC &mydc, bool isdown)
{
if (isdown)
mydc.SelectObject(*shadowbrush);
else
mydc.SelectObject(*trackbrush);
FASTRECT(mydc, sbrect.left+1, trackyoff, sbwidth-2, thumbyoff-trackyoff);
}
//----------------------------------------------------------------------------
void
TVScroll::DrawBottomTrack(TDC& mydc, bool isdown)
{
int yoff = thumbyoff+sqsize+2;
int lasty = trackyoff + trackheight - 1;
if (isdown)
mydc.SelectObject(*shadowbrush);
else
mydc.SelectObject(*trackbrush);
FASTRECT(mydc, sbrect.left+1, yoff, sbwidth-2, lasty-yoff+1);
}
//----------------------------------------------------------------------------
void
TVScroll::DrawThumb(TDC& mydc, bool drawfocus, bool erasefocus)
{
if ((erasefocus) && (lastfocusyoff >= 0)) {
mydc.DrawFocusRect(sbrect.left, lastfocusyoff, sbrect.right,
lastfocusyoff+sqsize+2);
}
if (drawfocus) {
mydc.DrawFocusRect(sbrect.left, thumbyoff, sbrect.left+sbwidth,
thumbyoff+sqsize+2);
lastfocusyoff = thumbyoff;
return;
}
// draw thumb track (but don't cover two outside black lines)
mydc.SelectObject(*trackbrush);
FASTRECT(mydc, sbrect.left+1, trackyoff+1, sbwidth-2, trackheight-2);
// draw black lines on each side of solid thumb
mydc.SelectObject(*framebrush);
FASTHLINE(mydc, sbrect.left, thumbyoff, sbwidth);
FASTHLINE(mydc, sbrect.left, thumbyoff+sqsize+1, sbwidth);
// draw solid thumb
mydc.SelectObject(*facebrush);
FASTRECT(mydc, sbrect.left+1, thumbyoff+1, sqsize-2, sqsize-2);
// draw shaded frame and extra "_|" design for solid thumb
TRect myrect(sbrect.left+1, thumbyoff+1, sbrect.right-1,
thumbyoff+sqsize+1);
DrawShadeFrame(mydc, myrect, TRUE);
lastfocusyoff = -1;
}
//----------------------------------------------------------------------------
void
TVScroll::DrawDownFrame(TDC& mydc, TRect& myrect)
{
// always a single width shadow line
mydc.SelectObject(*shadowbrush);
FASTHLINE(mydc, myrect.left, myrect.top, myrect.right-myrect.left);
FASTVLINE(mydc, myrect.left, myrect.top, myrect.bottom-myrect.top);
}
//----------------------------------------------------------------------------
void
TVScroll::DrawShadeFrame(TDC& mydc, TRect& myrect, bool forthumb)
{
int width = myrect.right - myrect.left;
int height = myrect.bottom - myrect.top;
mydc.SelectObject(*hilitebrush);
FASTHLINE(mydc, myrect.left, myrect.top, width);
FASTVLINE(mydc, myrect.left, myrect.top, height);
if (sqsize > 15) { // double highlight
FASTHLINE(mydc, myrect.left, myrect.top+1, width);
FASTVLINE(mydc, myrect.left+1, myrect.top, height);
}
mydc.SelectObject(*shadowbrush);
FASTHLINE(mydc, myrect.left, myrect.bottom-1, width);
FASTVLINE(mydc, myrect.right-1, myrect.top, height);
if ((forthumb) || (sqsize >= 15)) { // double shadow
FASTHLINE(mydc, myrect.left+1, myrect.bottom-2, width-1);
FASTVLINE(mydc, myrect.right-2, myrect.top+1, height-1);
}
}
//---------------------------------------------------------------------------
void TVScroll::DrawArrowButton(TDC &mydc, TRect& brect, bool isdown, bool top)
{
int xoff, yoff, width, height, downoff, aheight, awidth;
int lheight, lwidth, myheight, delta;
// draw button background
mydc.FillRect(brect, *facebrush);
// draw frame around button
if (isdown)
DrawDownFrame(mydc, brect);
else
DrawShadeFrame(mydc, brect, FALSE);
// calculations for drawing arrow line and head
width = brect.right - brect.left;
height = brect.bottom - brect.top;
if (isdown)
downoff = 1;
else
downoff = 0;
mydc.SelectObject(*framebrush); // for drawing arrows
awidth = 2 + (width+1)/3;
if (! (awidth%2)) // need an odd numbered arrow width
awidth--;
aheight = (awidth+1)/2;
if (arrowline)
lheight = aheight-1;
else
lheight = 0;
myheight = aheight + lheight;
delta = height - myheight;
yoff = brect.top + delta/2; // where whole object should start
if (delta%2) // odd number - put extra space on left
yoff++;
if (arrowline) { // draw arrow line
if (top)
yoff += aheight; // yoff is now where line starts
lwidth = (awidth+2)/3;
xoff = brect.left + (width/2 - lwidth/2);
FASTRECT(mydc, xoff+downoff, yoff+downoff, lwidth, lheight);
if (top)
yoff--;
else
yoff += lheight;
} else if (top)
yoff += (aheight-1);
// yoff is now where back line of arrow should be drawn
xoff = brect.left + (width/2 - awidth/2);
// draw arrow head
while (awidth > 0) {
FASTHLINE(mydc, xoff+downoff, yoff+downoff, awidth);
awidth -= 2;
if (top)
yoff--;
else
yoff++;
xoff++;
}
}
//---------------------------------------------------------------------------
void
TVScroll::MyPaint(int newstate)
{
if ((! Parent->GetHandle()) || (Parent->IsIconic()) || (! showit))
return;
bool forceall = (newstate == CSB_FORCEALL);
if ((! forceall) && (newstate == displaystate) &&
(newstate <= CSB_BOTTOMTHUMB))
return; // already drawn
bool dotop = (displaystate==CSB_TOPARROW) || (newstate==CSB_TOPARROW);
bool dobottom = (displaystate==CSB_BOTTOMARROW) ||
(newstate==CSB_BOTTOMARROW);
bool dothumb = (displaystate>=CSB_TOPTHUMB) || (newstate>=CSB_TOPTHUMB);
if (newstate <= CSB_BOTTOMTHUMB)
displaystate = newstate;
TWindowDC mydc(*Parent);
if (forceall)
DrawFrames(mydc);
if ((forceall) || (dotop))
DrawTopArrow(mydc, (displaystate==CSB_TOPARROW));
if ((forceall) || (dobottom))
DrawBottomArrow(mydc, (displaystate==CSB_BOTTOMARROW));
if ((forceall) || (dothumb)) {
DrawThumb(mydc, (displaystate==CSB_THUMBFOCUS),
(displaystate==CSB_THUMBFOCUS));
if (displaystate == CSB_TOPTHUMB) // gray to top of thumb
DrawTopTrack(mydc, TRUE);
else if (displaystate == CSB_BOTTOMTHUMB) // gray to right of thumb
DrawBottomTrack(mydc, TRUE);
}
}
//----------------------------------------------------------------------------
int
TVScroll::SetScrollPos(int newval, int repaint)
{
int oldval = curval;
curval = std::min(std::max(newval, lowval), highval);
// reposition thumb to match new value
thumbyoff = (int)(trackyoff + ((LONG)trange*(curval-lowval))/vrange);
if (repaint == SV_REPAINT)
MyPaint(CSB_THUMB);
else if (repaint == SV_THUMBTRACK)
MyPaint(thumbmove ? CSB_THUMB : CSB_THUMBFOCUS);
return(oldval);
}
//----------------------------------------------------------------------------
void
TVScroll::SetScrollRange(int Lowval, int Highval, bool redraw)
{
lowval = Lowval;
highval = Highval;
if (highval <= lowval)
highval = lowval + 1;
vrange = highval - lowval;
if (redraw)
MyPaint(CSB_FORCEALL);
}
//----------------------------------------------------------------------------
int
TVScroll::GetMouseLoc(TPoint& winpt)
{
if ((Parent->IsIconic()) || (! sbrect.Contains(winpt)) || (! showit))
return CSB_NOTDOWN;
int myy = winpt.y;
int top = sbrect.top;
if (myy < top+sqsize+2)
return CSB_TOPARROW;
if (myy > (top+sqsize+2+trackheight))
return CSB_BOTTOMARROW;
if (myy < thumbyoff)
return CSB_TOPTHUMB;
if (myy > thumbyoff+sqsize+2)
return CSB_BOTTOMTHUMB;
return CSB_THUMB;
}
//----------------------------------------------------------------------------
bool
TVScroll::MyLButtonDown(uint /*hitTest*/, TPoint& winpt)
{
mousedown = GetMouseLoc(winpt);
if (mousedown == CSB_NOTDOWN) // mousedown not in scrollbar
return false;
origval = curval;
newloc = mousedown;
switch (mousedown) {
case CSB_TOPARROW:
case CSB_BOTTOMARROW:
MyPaint(mousedown);
break;
case CSB_TOPTHUMB:
MyPaint(mousedown);
Parent->SendMessage(scrollmsg, SB_PAGEUP, mylongid);
break;
case CSB_BOTTOMTHUMB:
MyPaint(mousedown);
Parent->SendMessage(scrollmsg, SB_PAGEDOWN, mylongid);
break;
case CSB_THUMB:
thumbgrabyoff = winpt.y - thumbyoff;
SetScrollPos(curval, SV_THUMBTRACK);
}
AutoScrollMouse();
return true;
}
//----------------------------------------------------------------------------
bool
TVScroll::MyMouseMove(uint /*hitTest*/, TPoint& winpt)
{
if (mousedown == CSB_NOTDOWN) // mousedown was not in our scrollbar
return false;
newloc = GetMouseLoc(winpt);
switch (mousedown){
case CSB_TOPARROW:
case CSB_BOTTOMARROW:
case CSB_TOPTHUMB:
case CSB_BOTTOMTHUMB:
if (newloc == mousedown)
MyPaint(mousedown);
else
MyPaint(CSB_NOTDOWN);
break;
case CSB_THUMB:
if (newloc != CSB_NOTDOWN){ // anywhere inside sb
int newpos = (winpt.y - thumbgrabyoff) - trackyoff;
if (newpos < 0)
newpos = 0;
else if (newpos > trange)
newpos = trange;
int newval = (int)(lowval + ((LONG)vrange*newpos)/trange);
SetScrollPos(newval, SV_THUMBTRACK);
Parent->SendMessage(scrollmsg, SB_THUMBTRACK,
mylongid | newval);
} else {
SetScrollPos(origval, SV_THUMBTRACK);
Parent->SendMessage(scrollmsg, SB_THUMBTRACK,
mylongid | origval);
}
break;
}
return true;
}
//----------------------------------------------------------------------------
bool
TVScroll::MyLButtonUp(uint /*hitTest*/, TPoint& winpt)
{
int sendval;
if (mousedown == CSB_NOTDOWN) // mousedown was not in our scrollbar
return false;
newloc = GetMouseLoc(winpt);
switch (mousedown) {
case CSB_TOPARROW:
MyPaint(CSB_NOTDOWN);
if (newloc == mousedown)
Parent->SendMessage(scrollmsg, SB_LINEUP, mylongid);
break;
case CSB_BOTTOMARROW:
MyPaint(CSB_NOTDOWN);
if (newloc == mousedown)
Parent->SendMessage(scrollmsg, SB_LINEDOWN, mylongid);
break;
case CSB_THUMB:
sendval = curval; // save off before overwritting
SetScrollPos(origval, SV_REPAINT);
Parent->SendMessage(scrollmsg, SB_THUMBPOSITION,
mylongid | sendval);
break;
default:
MyPaint(CSB_NOTDOWN);
break;
}
Parent->SendMessage(scrollmsg, SB_ENDSCROLL, mylongid);
mousedown = CSB_NOTDOWN;
return true;
}
//----------------------------------------------------------------------------
void
TVScroll::AutoScrollAction()
{
if (newloc != mousedown)
return;
switch (mousedown){
case CSB_TOPARROW:
Parent->SendMessage(scrollmsg, SB_LINEUP, mylongid);
break;
case CSB_BOTTOMARROW:
Parent->SendMessage(scrollmsg, SB_LINEDOWN, mylongid);
break;
case CSB_TOPTHUMB:
Parent->SendMessage(scrollmsg, SB_PAGEUP, mylongid);
break;
case CSB_BOTTOMTHUMB:
Parent->SendMessage(scrollmsg, SB_PAGEDOWN, mylongid);
break;
}
}
} // OwlExt namespace
//------------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
//\\\\\\\\\\\//\\\\\\\\\\\\\\\\\\\\\\\\//\\\\\\\\\\\\\\\\\\//\\\\\\\\\\\\\\\\\//
////////////////////////////////////////////////////////////////////////////////
↑ V688 The 'textextra' local variable possesses the same name as one of the class members, which can result in a confusion.
↑ V688 The 'textextra' local variable possesses the same name as one of the class members, which can result in a confusion.
↑ V730 It is possible that not all members of a class are initialized inside the constructor. Consider inspecting: tabpoints, textextra, toffs, wanthscroll, wantvscroll.
↑ V525 The code contains the collection of similar blocks. Check items 'hsbrect', 'vsbrect', 'tsbrect', 'tsbrect' in lines 788, 790, 792, 794.
↑ V601 The 'true' value is implicitly cast to the integer type. Inspect the second argument.
↑ V601 The 'true' value is implicitly cast to the integer type. Inspect the second argument.
↑ V601 The 'false' value is implicitly cast to the integer type. Inspect the second argument.
↑ V601 The 'false' value is implicitly cast to the integer type. Inspect the second argument.
↑ V730 It is possible that not all members of a class are initialized inside the constructor. Consider inspecting: trange, vrange, mousedown, newloc, displaystate, lowval, ...
↑ V832 It's better to use '= default;' syntax instead of empty destructor body.
↑ V832 It's better to use '= default;' syntax instead of empty destructor body.