home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / NOTEBOOK.PAK / NOTEBOOK.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  39.1 KB  |  1,271 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // Copyright (c) 1995, 1995 by Borland International, All Rights Reserved
  4. //    notebook.cpp - defines TNotebook class
  5. //
  6. //   Special explanation for non-client painting in TNotebook:
  7. //
  8. //   normal windows sequence of events for window resize:
  9. //        WM_NCCALCSIZE
  10. //        WM_NCPAINT
  11. //        WM_SIZE
  12. //
  13. //   This causes multiple ncpaints since subclassers must hook WM_SIZE and
  14. //   show/hide scrollbars based on new client size; these multiple ncpaints
  15. //   are especially noticable in TNotebook since the painting of the tabs
  16. //   takes a relative long amount of time.
  17. //
  18. //   Solution taken to this problem in TNotebook class: created a variable
  19. //   called "defer_ncpaint" to turn nc painting on/off.  It is used as
  20. //   follows:
  21. //
  22. //      1. Constructor: sets defer_ncpaint = 0
  23. //      2. EvNCPaint(): if defer_ncpaint > 0, decrements it and returns
  24. //         without painting
  25. //      3. EvNCCalcSize(): if defer_ncpaint >= 0, increments it
  26. //      4. EvSize(): if defer_ncpaint = 0, calls ForceResize(TRUE) to force
  27. //         ncpaint
  28. //      5. ForceResize(repaint): if repaint=TRUE, defer_ncpaint=-1,
  29. //         resize window, defer_ncpaint=0
  30. //
  31. //   Subclassers of TNotebook::Evsize() should:
  32. //      1. set defer_ncpaint=1
  33. //      2. call TNotebook::Evsize(...)
  34. //      3. call SetScrollRange(...) as needed to hide/show scrollbars
  35. //      4. call ForceResize(TRUE) to force ncpaint
  36. //
  37. //   If subclassers just ignore "defer_ncpaint", TNotebook should paint
  38. //   normally but with multiple nc paints.
  39. //
  40. //----------------------------------------------------------------------------
  41. #include <owl/pch.h>
  42. #include <owl/mdichild.h>
  43. #include <owl/dc.h>
  44.  
  45. #include "utils.h"              // for debugging support
  46. #include "notebook.h"
  47. //----------------------------------------------------------------------------
  48. DEFINE_RESPONSE_TABLE1(TNotebook, TWindow)
  49.   EV_WM_GETMINMAXINFO,
  50.   EV_WM_SIZE,
  51.   EV_WM_NCCALCSIZE,
  52.   EV_WM_NCHITTEST,
  53.   EV_WM_NCPAINT,
  54.   EV_WM_NCCREATE,
  55.   EV_WM_NCLBUTTONDOWN,
  56.   EV_WM_NCLBUTTONDBLCLK,
  57.   EV_WM_LBUTTONDOWN,                    // while mouse captured, we get these
  58.   EV_WM_LBUTTONUP,                      // while mouse captured, we get these
  59.   EV_WM_MOUSEMOVE,                      // while mouse captured, we get these
  60.   EV_WM_SYSCOLORCHANGE,
  61.   EV_MESSAGE(NW_HSCROLL, NWHscroll),
  62.   EV_MESSAGE(NW_VSCROLL, NWHscroll),
  63. END_RESPONSE_TABLE;
  64. //----------------------------------------------------------------------------
  65. TNotebook::TNotebook(int TabLoc)
  66. {
  67.   tabloc = TabLoc;
  68.   tabhorz = ((tabloc == LOC_TOP) || (tabloc == LOC_BOTTOM));
  69.   tabcnt = 1;
  70.   firsttab = 0;
  71.   activetab = 0;
  72.   erasetabs = FALSE;
  73.   tabhscroll = NULL;            // until created
  74.   tabvscroll = NULL;            // until created
  75.   winhscroll = NULL;            // until created
  76.   winvscroll = NULL;            // until created
  77.   hscrollon = FALSE;
  78.   vscrollon = FALSE;
  79.   defer_ncpaint = 0;
  80.  
  81.   nbcheight = 9 + GetSystemMetrics(SM_CYHSCROLL);
  82.  
  83.   rgncnt = 0;
  84.   fillmode = ALTERNATE;
  85.   clientprev = TRect(0, 0, 0, 0);
  86.  
  87.   BuildPaintObjects();
  88. }
  89. //----------------------------------------------------------------------------
  90. void TNotebook::BuildPaintObjects()
  91. {
  92.   BuildBgBrush();
  93.  
  94.   framebrush = new TBrush(GetSysColor(COLOR_WINDOWFRAME));
  95.   hilitebrush = new TBrush(GetSysColor(COLOR_BTNHIGHLIGHT));
  96.   shadowbrush = new TBrush(GetSysColor(COLOR_BTNSHADOW));
  97.   facebrush = new TBrush(GetSysColor(COLOR_BTNFACE));
  98.   trackbrush = new TBrush(GetSysColor(COLOR_SCROLLBAR));
  99.   tabbrush = new TBrush(GetSysColor(COLOR_WINDOW));
  100.   default_tabbrush = new TBrush(GetSysColor(COLOR_WINDOW));
  101.  
  102.   shadowpen = new TPen(GetSysColor(COLOR_BTNSHADOW));
  103.   framepen = new TPen(GetSysColor(COLOR_WINDOWFRAME));
  104.   if (tabhorz)
  105.     tabfont = new TFont("ms sans serif", 10);
  106.   else
  107.     tabfont = new TFont("arial", 10, 0, 2700, 2700);
  108. }
  109. //----------------------------------------------------------------------------
  110. void TNotebook::DeletePaintObjects()
  111. {
  112.   delete bgbrush;
  113.   delete framebrush;
  114.   delete hilitebrush;
  115.   delete shadowbrush;
  116.   delete facebrush;
  117.   delete trackbrush;
  118.   delete tabbrush;
  119.   delete default_tabbrush;
  120.  
  121.   delete shadowpen;
  122.   delete framepen;
  123.   delete tabfont;
  124. }
  125. //----------------------------------------------------------------------------
  126. TNotebook::~TNotebook()
  127. {
  128.   if (tabhscroll)
  129.     delete tabhscroll;
  130.   if (tabvscroll)
  131.     delete tabvscroll;
  132.   if (winhscroll)
  133.     delete winhscroll;
  134.   if (winvscroll)
  135.     delete winvscroll;
  136.  
  137.   DeletePaintObjects();
  138. }
  139. //----------------------------------------------------------------------------
  140. UINT TNotebook::EvNCHitTest(TPoint& screenPt)
  141. {
  142.   TPoint winpt = screenPt - GetWindowRect().TopLeft();  // win coords
  143.  
  144.   if (nbcrect.Contains(winpt))
  145.     return(HTBORDER);
  146.   if ((hscrollon) && (hsbrect.Contains(winpt)))
  147.     return(HTBORDER);
  148.   if ((vscrollon) && (vsbrect.Contains(winpt)))
  149.     return(HTBORDER);
  150.   return(TWindow::EvNCHitTest(screenPt));
  151. }
  152. //----------------------------------------------------------------------------
  153. void TNotebook::PaintNBC(int paintcontrol)
  154. {
  155.   BOOL goth, gotv;
  156.  
  157.   if ((! HWindow) || IsIconic())
  158.     return;
  159.  
  160.   TWindowDC mydc(*this);
  161.  
  162.   DrawBackground(mydc, nbcrect, paintcontrol);
  163.   DrawTabLines(mydc, nbcrect, TRUE);
  164.   DrawTabs(mydc);
  165.  
  166.   if (paintcontrol == NBC_PAINTALL){
  167.     if (tabhscroll)
  168.       tabhscroll->ForcePaint();
  169.     if (tabvscroll)
  170.       tabvscroll->ForcePaint();
  171.     if (hscrollon)
  172.             winhscroll->ForcePaint();
  173.     if (vscrollon)
  174.             winvscroll->ForcePaint();
  175.   }
  176.  
  177.   goth = ((hscrollon) || (tabloc == LOC_BOTTOM));
  178.   gotv = ((vscrollon) || (tabloc == LOC_RIGHT));
  179.  
  180.   if ((goth) && (gotv)){                        // paint corner
  181.     int mywidth, myheight;
  182.     if (tabloc == LOC_RIGHT)
  183.             mywidth = nbcrect.Width();
  184.     else
  185.             mywidth = GetSystemMetrics(SM_CXVSCROLL);
  186.     if (tabloc == LOC_BOTTOM)
  187.             myheight = nbcrect.Height() + 1;
  188.     else
  189.       myheight = GetSystemMetrics(SM_CYHSCROLL);
  190.  
  191.     if ((tabloc == LOC_TOP) || (tabloc == LOC_LEFT))
  192.       mydc.SelectObject(*trackbrush);
  193.     else
  194.       mydc.SelectObject(*bgbrush);
  195.  
  196.     mydc.SelectObject(*framepen);
  197.     Rectangle(mydc, clientrect.right, clientrect.bottom,
  198.             clientrect.right+mywidth, clientrect.bottom+myheight);
  199.   }
  200. }
  201. //----------------------------------------------------------------------------
  202. #if defined(BI_PLAT_WIN32)
  203. void TNotebook::EvNCPaint(HRGN region)
  204. #else
  205. void TNotebook::EvNCPaint()
  206. #endif
  207. {
  208.   if (defer_ncpaint > 0) {
  209.     defer_ncpaint--;
  210.     return;
  211.   }
  212.  
  213.   log("ncpaint being done");
  214.  
  215. // let windows paint everything else in NC
  216. #if defined(BI_PLAT_WIN32)
  217.   TWindow::EvNCPaint(region);
  218. #else
  219.   TWindow::EvNCPaint(); 
  220. #endif
  221.  
  222.   ComputeSizes();               // we are called before WM_SIZE is sent...
  223.   PaintNBC(NBC_PAINTALL);
  224. }
  225. //----------------------------------------------------------------------------
  226. void TNotebook::GetTabName(int tabnum, char *tabname)
  227. {
  228.  
  229.   if (tabnum < 26){
  230.           tabname[0] = (char)('A'+tabnum); //Cast to char to avoid 32 bit conv warnings
  231.           tabname[1] = 0;
  232.   }else if (tabnum < (702)) {
  233.           tabnum -= 26;
  234.           tabname[0] = (char)('A'+(tabnum/26));
  235.           tabname[1] = (char)('A'+(tabnum%26));
  236.           tabname[2] = 0;
  237.   }else {
  238.           tabnum -= 702;
  239.           tabname[0] = (char)('A'+tabnum/676);
  240.           tabnum = tabnum % 676;
  241.           tabname[1] = (char)('A'+(tabnum/26));
  242.           tabname[2] = (char)('A'+(tabnum%26));
  243.           tabname[3] = 0;
  244.   }
  245. }
  246. //----------------------------------------------------------------------------
  247. void TNotebook::DrawDownFrame(TDC &mydc, TRect &myrect)
  248. {
  249.   int width = myrect.right - myrect.left;
  250.   int height = myrect.bottom - myrect.top;
  251.  
  252.   mydc.SelectObject(*shadowbrush);
  253.   FASTHLINE(mydc, myrect.left, myrect.top, width);
  254.   FASTVLINE(mydc, myrect.left, myrect.top, height);
  255.  
  256.   mydc.SelectObject(*facebrush);
  257.   FASTHLINE(mydc, myrect.left, myrect.bottom-1, width);
  258.   FASTVLINE(mydc, myrect.right-1, myrect.top, height);
  259. }
  260. //----------------------------------------------------------------------------
  261. void TNotebook::DrawShadeFrame(TDC &mydc, TRect &myrect)
  262. {
  263.   int width = myrect.right - myrect.left;
  264.   int height = myrect.bottom - myrect.top;
  265.  
  266.   mydc.SelectObject(*hilitebrush);
  267.   FASTHLINE(mydc, myrect.left, myrect.top, width);
  268.   FASTVLINE(mydc, myrect.left, myrect.top, height);
  269.  
  270.   mydc.SelectObject(*shadowbrush);
  271.   FASTHLINE(mydc, myrect.left, myrect.bottom-1, width);
  272.   FASTVLINE(mydc, myrect.right-1, myrect.top, height);
  273. }
  274. //---------------------------------------------------------------------------
  275. int TNotebook::DrawHorzTab(TDC &mydc, int tabnum, int rgnnum, int toff)
  276. {
  277.   char tabname[MAXTABNAMELEN+1];
  278.   SIZE textsize;
  279.   int tabsize, bp;
  280.   TRect textrect;
  281.   POINT *points;
  282.   int tabsheight = tabsrect.Height();
  283.   int halfheight = tabsheight/2;
  284.   int textextra = 10;           // extra spacing around text
  285.   int taboff = 4;
  286.   int ydir, row0, row1, row2, row3;
  287.  
  288.   points = tabpoints[rgnnum];
  289.   mydc.SelectObject(*tabfont);
  290.   SetBkMode(mydc, TRANSPARENT);
  291.  
  292.   GetTabName(tabnum, tabname);
  293.   GetTextExtentPoint(mydc, tabname, strlen(tabname),&textsize);
  294.   tabsize = textsize.cx + textextra + taboff + taboff;
  295.   if (toff+tabsize+2*taboff > tabsrect.right){     // no room for this one
  296.     tabsize = 0;
  297.     goto exit;
  298.   }
  299.  
  300.   if (tabloc == LOC_BOTTOM) {
  301.     row0 = tabsrect.top - 5;
  302.     row1 = tabsrect.top;
  303.     row2 = row1+halfheight;
  304.     row3 = row1+tabsheight;
  305.     ydir = 1;
  306.     textrect = TRect(toff+taboff, row1+2, toff+taboff+textsize.cx+10, row3);
  307.   } else {              // LOC_TOP
  308.     row0 = tabsrect.bottom + 4;
  309.     row1 = tabsrect.bottom - 1;
  310.     row2 = row1-halfheight;
  311.     row3 = row1-tabsheight;
  312.     ydir = -1;
  313.     textrect = TRect(toff+taboff, row3+2, toff+taboff+textsize.cx+10, row1);
  314.   }
  315.  
  316.   if (erasetabs){               // erase as we draw
  317.   mydc.SelectObject(*bgbrush);
  318.   FASTRECT(mydc, toff+1, row2, tabsize+1, ydir*(halfheight+3));
  319.   }
  320.  
  321.   mydc.SelectObject(*framepen);
  322.   mydc.SelectObject(*facebrush);
  323.  
  324.   // draw tab "tabnum"
  325.   if ((tabnum == activetab) || (! rgnnum)){
  326.     TBrush *endbrush = shadowbrush;
  327.     int delta = 0;
  328.     int myrow = row1;
  329.     if (tabnum == activetab){
  330.       mydc.SelectObject(*tabbrush);
  331.           endbrush = tabbrush;
  332.           delta = 2;
  333.           myrow = row0;
  334.     }
  335.     points[0] = TPoint(toff-taboff-delta, myrow);
  336.     points[1] = TPoint(toff+taboff, row3);
  337.     points[2] = TPoint(points[1].x+textsize.cx+textextra, row3);
  338.     points[3] = TPoint(points[2].x+taboff+taboff+delta, myrow);
  339.     points[4] = points[0];
  340.     bp = 1;
  341.     Polygon(mydc, points, 5);
  342.     // draw top shadow line (or erase any such line for active tab)
  343.           mydc.SelectObject(*endbrush);
  344.     FASTHLINE(mydc, points[0].x, points[0].y, points[3].x-points[0].x-1);
  345.   } else {
  346.     points[0] = TPoint(toff+taboff, row1);
  347.     points[1] = TPoint(toff, row2);
  348.     points[2] = TPoint(toff+taboff, row3);
  349.     points[3] = TPoint(points[2].x+textsize.cx+textextra, row3);
  350.     points[4] = TPoint(points[3].x+taboff+taboff, row1);
  351.     bp = 2;
  352.     Polygon(mydc, points, 5);
  353.     // draw top shadow line
  354.     mydc.SelectObject(*shadowbrush);
  355.     FASTHLINE(mydc, points[0].x, points[0].y, points[4].x-points[0].x-1);
  356.  
  357.     // redraw tab shadow for previous tab (Polygon erased part of it)
  358.     mydc.SelectObject(*shadowpen);
  359.     mydc.MoveTo(toff-taboff+1, row3+ydir);
  360.     mydc.LineTo(toff+taboff+1, row1-ydir);
  361.   }
  362.  
  363.   // draw tab shadow for this tab
  364.   mydc.SelectObject(*shadowpen);
  365.   mydc.MoveTo(points[bp].x+1, points[bp].y+ydir);
  366.   mydc.LineTo(points[bp+1].x+1, points[bp+1].y+ydir);
  367.   mydc.LineTo(points[bp+2].x+1, points[bp+2].y-ydir);
  368.  
  369.   // draw text inside tab
  370.   mydc.SelectObject(*framepen);
  371.   mydc.DrawText(tabname, -1, textrect, DT_CENTER);
  372.  
  373. exit:
  374.   mydc.RestoreFont();
  375.   return(tabsize);
  376. }
  377. //---------------------------------------------------------------------------
  378. int TNotebook::DrawVertTab(TDC &mydc, int tabnum, int rgnnum, int toff)
  379. {
  380.   char tabname[MAXTABNAMELEN+1];
  381.   SIZE textsize;
  382.   int tabsize, bp, xval, yval;
  383.   TRect textrect;
  384.   POINT *points;
  385.   int tabswidth = tabsrect.Width();
  386.   int halfwidth = tabswidth/2;
  387.   int textextra = 10;           // extra spacing around text
  388.   int taboff = 4;
  389.   int xdir, col0, col1, col2, col3;
  390.  
  391.   points = tabpoints[rgnnum];
  392.   mydc.SelectObject(*tabfont);
  393.   SetBkMode(mydc, TRANSPARENT);
  394.  
  395.   GetTabName(tabnum, tabname);
  396.   GetTextExtentPoint(mydc, tabname, strlen(tabname),&textsize);
  397.   tabsize = textsize.cx + textextra + taboff + taboff;
  398.   if (toff+tabsize+2*taboff > tabsrect.bottom){     // no room for this one
  399.     tabsize = 0;
  400.     goto exit;
  401.   }
  402.  
  403.   if (tabloc == LOC_LEFT){
  404.     col0 = tabsrect.right + 4;
  405.     col1 = col0-5;
  406.     col2 = col1-halfwidth;
  407.     col3 = col1-tabswidth;
  408.     xdir = -1;
  409.     textrect = TRect(col3, toff+taboff, col1-2, toff+taboff+textsize.cx+10);
  410.   } else {              // LOC_RIGHT
  411.     col0 = tabsrect.left - 5;
  412.     col1 = col0+5;
  413.     col2 = col1+halfwidth;
  414.     col3 = col1+tabswidth;
  415.     xdir = 1;
  416.     textrect = TRect(col1, toff+taboff+2, col3-2, toff+taboff+textsize.cx+10);
  417.   }
  418.  
  419.   if (erasetabs){               // erase as we draw
  420.     mydc.SelectObject(*bgbrush);
  421.     FASTRECT(mydc, col2, toff+1, xdir*(halfwidth+3), tabsize+1);
  422.   }
  423.  
  424.   mydc.SelectObject(*framepen);
  425.   mydc.SelectObject(*facebrush);
  426.  
  427.   // draw tab "tabnum"
  428.   if ((tabnum == activetab) || (! rgnnum)) {
  429.     TBrush *endbrush = shadowbrush;
  430.     int delta = 0;
  431.     int mycol = col1;
  432.     if (tabnum == activetab) {
  433.       mydc.SelectObject(*tabbrush);
  434.             endbrush = tabbrush;
  435.             delta = 2;
  436.             mycol = col0;
  437.     }
  438.   points[0] = TPoint(mycol, toff-taboff-delta);
  439.   points[1] = TPoint(col3, toff+taboff);
  440.   points[2] = TPoint(col3, points[1].y+textsize.cx+textextra);
  441.   points[3] = TPoint(mycol, points[2].y+taboff+taboff+delta);
  442.   points[4] = points[0];
  443.   Polygon(mydc, points, 5);
  444.   mydc.SelectObject(*endbrush);
  445.   // draw top shadow line (or erase any such line for active tab)
  446.   FASTVLINE(mydc, points[0].x, points[0].y, points[3].y-points[0].y);
  447.   bp = 1;
  448.   } else {
  449.     points[0] = TPoint(col1, toff+taboff);
  450.     points[1] = TPoint(col2, toff);
  451.     points[2] = TPoint(col3, toff+taboff);
  452.     points[3] = TPoint(col3, points[2].y+textsize.cx+textextra);
  453.     points[4] = TPoint(col1, points[3].y+taboff+taboff);
  454.     bp = 2;
  455.     Polygon(mydc, points, 5);
  456.     mydc.SelectObject(*shadowbrush);
  457.     // draw top shadow line
  458.     FASTVLINE(mydc, points[0].x, points[0].y, points[4].y-points[0].y);
  459.     // draw part of tab shadow for previous tab
  460.     mydc.SelectObject(*shadowpen);
  461.     mydc.MoveTo(points[0].x+1, points[0].y);
  462.     mydc.LineTo(points[1].x, points[1].y+2);
  463.   }
  464.  
  465.   // draw tab shadow for this tab
  466.   mydc.SelectObject(*shadowpen);
  467.   mydc.MoveTo(points[bp].x+xdir, points[bp].y);
  468.   mydc.LineTo(points[bp+1].x+xdir, points[bp+1].y);
  469.   mydc.LineTo(points[bp+2].x-xdir, points[bp+2].y);
  470.  
  471.   // draw text
  472.   mydc.SelectObject(*framepen);
  473.   xval = textrect.right;                // vert text is wierd...
  474.   yval = textrect.top + (textrect.Height() - textsize.cx)/2;
  475.   mydc.TextOut(xval, yval, tabname, strlen(tabname));
  476.  
  477. exit:
  478.   mydc.RestoreFont();
  479.   return(tabsize);
  480. }
  481. //----------------------------------------------------------------------------
  482. void TNotebook::DrawTabs(TDC &mydc)
  483. {
  484.   int tabnum = firsttab;
  485.   int tsize, toff;
  486.  
  487.   if (tabhorz)
  488.     toff = tabsrect.left + 22;
  489.   else
  490.     toff = tabsrect.top + 22;
  491.  
  492.   rgncnt = 0;
  493.  
  494.   while (1) {
  495.     if (tabhorz)
  496.             tsize = DrawHorzTab(mydc, tabnum, rgncnt, toff);
  497.     else
  498.             tsize = DrawVertTab(mydc, tabnum, rgncnt, toff);
  499.     if (! tsize)
  500.             break;
  501.     toffs[rgncnt++] = toff;
  502.     toff += tsize;
  503.     if (rgncnt >= MAXTABSSHOWN)
  504.       break;
  505.     if (++tabnum >= tabcnt)
  506.       break;
  507.   }
  508.  
  509.   if (erasetabs) {                      // erase as we draw
  510.     if (tabhorz)
  511.             EraseLastHorz(mydc, toff);
  512.     else
  513.             EraseLastVert(mydc, toff);
  514.   }
  515. }
  516. //----------------------------------------------------------------------------
  517. void TNotebook::EraseLastVert(TDC &mydc, int toff)
  518. {
  519.   int tabswidth = tabsrect.Width();
  520.   POINT points[5];
  521.   int halfwidth = tabswidth/2;
  522.   int col0, col1, col2, col3;
  523.   int taboff = 4;
  524.  
  525.   if (tabloc == LOC_RIGHT) {
  526.     col0 = tabsrect.left;
  527.     col1 = col0 + 1;
  528.     col2 = col0 + halfwidth;
  529.     col3 = col0 + tabswidth + 2;
  530.   } else {
  531.     col0 = tabsrect.right;
  532.     col1 = col0 - 1;
  533.     col2 = col0 - halfwidth;
  534.     col3 = col0 - (tabswidth + 2);
  535.   }
  536.  
  537.   mydc.SelectStockObject(NULL_PEN);
  538.   mydc.SelectObject(*bgbrush);
  539.   toff += 2;
  540.  
  541.   points[0] = TPoint(col1, toff+taboff);
  542.   points[1] = TPoint(col2, toff);
  543.   points[2] = TPoint(col3, toff);
  544.   points[3] = TPoint(col3, tabsrect.bottom+2);
  545.   points[4] = TPoint(col1, tabsrect.bottom+2);
  546.  
  547.   Polygon(mydc, points, 5);
  548.   erasetabs = FALSE;
  549. }
  550. //----------------------------------------------------------------------------
  551. void TNotebook::EraseLastHorz(TDC &mydc, int toff)
  552. {
  553.   int tabsheight = tabsrect.Height();
  554.   POINT points[5];
  555.   int halfheight = tabsheight/2;
  556.   int row0, row1, row2, row3;
  557.   int taboff = 4;
  558.  
  559.   if (tabloc == LOC_BOTTOM) {
  560.     row0 = tabsrect.top;
  561.     row1 = row0 + 1;
  562.     row2 = row0 + halfheight;
  563.     row3 = row0 + tabsheight + 2;
  564.   } else {
  565.     row0 = tabsrect.bottom;
  566.     row1 = row0 - 1;
  567.     row2 = row0 - halfheight;
  568.     row3 = row0 - (tabsheight + 2);
  569.   }
  570.  
  571.   mydc.SelectStockObject(NULL_PEN);
  572.   mydc.SelectObject(*bgbrush);
  573.   toff += 2;
  574.  
  575.   points[0] = TPoint(toff+taboff, row1);
  576.   points[1] = TPoint(toff, row2);
  577.   points[2] = TPoint(toff, row3);
  578.   points[3] = TPoint(tabsrect.right+2, row3);
  579.   points[4] = TPoint(tabsrect.right+2, row1);
  580.  
  581.   Polygon(mydc, points, 5);
  582.   erasetabs = FALSE;
  583. }
  584. //----------------------------------------------------------------------------
  585. void TNotebook::DrawBackground(TDC &mydc, TRect &myrect, int paintcontrol)
  586. {
  587.   if (paintcontrol == NBC_PAINTALL)
  588.     mydc.FillRect(myrect, *bgbrush);
  589.   else
  590.     erasetabs = TRUE;
  591. }
  592. //----------------------------------------------------------------------------
  593. void TNotebook::DrawTabLines(TDC &mydc, TRect &myrect, BOOL shadowline)
  594. {
  595.   int width = myrect.right - myrect.left;
  596.   int height = myrect.bottom - myrect.top;
  597.   int tabstart, row, col, dir;
  598.  
  599.   if (tabhorz) {
  600.     tabstart = tabsrect.left;
  601.     if (tabloc == LOC_BOTTOM) {
  602.             dir = 1;
  603.             row = myrect.top;
  604.     } else {
  605.             row = myrect.bottom-1;
  606.             dir = -1;
  607.     }
  608.     mydc.SelectObject(*framebrush);
  609.     FASTHLINE(mydc, myrect.left, row, width);
  610.     FASTVLINE(mydc, tabstart, row, dir*2);
  611.     FASTHLINE(mydc, tabstart, row+dir*2, myrect.right-tabstart);
  612.     FASTVLINE(mydc, tabstart+3, row+dir*2, dir*2);
  613.     FASTHLINE(mydc, tabstart+3, row+dir*4, myrect.right-tabstart-3);
  614.     mydc.SelectObject(*default_tabbrush);
  615.     FASTHLINE(mydc, tabstart+1, row+dir*1, myrect.right-tabstart-1);
  616.     FASTHLINE(mydc, tabstart+4, row+dir*3, myrect.right-tabstart-4);
  617.     if (shadowline) {
  618.       mydc.SelectObject(*shadowbrush);
  619.       FASTHLINE(mydc, tabstart+5, row+dir*5, myrect.right-tabstart-5);
  620.     }
  621.   } else {              // left or right
  622.     tabstart = tabsrect.top;
  623.  
  624.     if (tabloc == LOC_LEFT){
  625.             col = myrect.right-1;
  626.             dir = -1;
  627.     } else {
  628.             col = myrect.left;
  629.             dir = 1;
  630.     }
  631.     mydc.SelectObject(*framebrush);
  632.     FASTVLINE(mydc, col, myrect.top, height);
  633.     FASTHLINE(mydc, col, tabstart, dir*2);
  634.     FASTVLINE(mydc, col+dir*2, tabstart, myrect.bottom-tabstart);
  635.     FASTHLINE(mydc, col+dir*2, tabstart+3, dir*2);
  636.     FASTVLINE(mydc, col+dir*4, tabstart+3, myrect.bottom-tabstart-3);
  637.     mydc.SelectObject(*default_tabbrush);
  638.     FASTVLINE(mydc, col+dir, tabstart+1, myrect.bottom-tabstart-1);
  639.     FASTVLINE(mydc, col+dir*3, tabstart+4, myrect.bottom-tabstart-4);
  640.     if (shadowline) {
  641.       mydc.SelectObject(*shadowbrush);
  642.       FASTVLINE(mydc, col+dir*5, tabstart+5, myrect.bottom-tabstart-5);
  643.     }
  644.   }
  645. }
  646. //----------------------------------------------------------------------------
  647. void TNotebook::CalcTabRects()
  648. {
  649.   int nleft, ntop, nright, nbottom, nwidth, nheight;
  650.   int hwidth, hheight, vwidth, vheight, tsblong, tsbshort;
  651.  
  652.   nleft = nbcrect.left;
  653.   ntop = nbcrect.top;
  654.   nright = nbcrect.right;
  655.   nbottom = nbcrect.bottom;
  656.   nwidth = nbcrect.right - nbcrect.left;
  657.   nheight = nbcrect.bottom - nbcrect.top;
  658.  
  659.   // tab scrollbar's size is fixed to match font (doesn't shrink with window)
  660.   if (tabhorz)
  661.     tsbshort = 5 + nheight/3;
  662.   else
  663.     tsbshort = 5 + nwidth/3;
  664.   tsblong = 1 + 5*(tsbshort-2);
  665.  
  666.   if (hscrollon) {
  667.     hwidth = hsbrect.Width();
  668.     hheight = hsbrect.Height();
  669.   } else
  670.     hheight = hwidth = 0;
  671.  
  672.   if (vscrollon) {
  673.     vwidth = vsbrect.Width();
  674.     vheight = vsbrect.Height();
  675.   } else
  676.     vwidth = vheight = 0;
  677.  
  678.   switch (tabloc) {
  679.     case LOC_LEFT:
  680.         tsbrect = TRect(nleft+3, ntop+3, nleft+3+tsbshort, ntop+3+tsblong);
  681.             tabsrect = TRect(nleft+5, tsbrect.bottom-16, nright-5,
  682.             nbottom-(5+hheight));
  683.             break;
  684.  
  685.     case LOC_RIGHT:
  686.         tsbrect = TRect(nleft+3, ntop+3, nleft+3+tsbshort, ntop+3+tsblong);
  687.             tabsrect = TRect(nleft+5, tsbrect.bottom-16, nright-5,
  688.             nbottom-(vheight+5));
  689.             break;
  690.  
  691.     case LOC_TOP:
  692.         tsbrect = TRect(nleft+4, ntop+3, nleft+4+tsblong, ntop+3+tsbshort);
  693.             tabsrect = TRect(tsbrect.right-16, ntop+6, nright-(5+vwidth),
  694.             nbottom-5);
  695.             break;
  696.  
  697.     case LOC_BOTTOM:
  698.         tsbrect = TRect(nleft+4, ntop+9, nleft+4+tsblong,
  699.             ntop+9+tsbshort);
  700.             tabsrect = TRect(tsbrect.right-16, ntop+5, nright-(hwidth+5),
  701.             nbottom-6);
  702.             break;
  703.   }
  704. }
  705. //----------------------------------------------------------------------------
  706. void TNotebook::ComputeSizes()
  707. {
  708.   int cleft, ctop, cright, cbottom, cwidth, cheight;
  709.   int vswidth, hsheight;
  710.  
  711.   if ((! HWindow) || (clientrect == clientprev))        // no size change
  712.     return;
  713.   clientprev = clientrect;
  714.  
  715.   if (vscrollon)
  716.     vswidth = GetSystemMetrics(SM_CXVSCROLL);
  717.   else
  718.     vswidth = 0;
  719.   if (hscrollon)
  720.     hsheight = GetSystemMetrics(SM_CYHSCROLL);
  721.   else
  722.     hsheight = 0;
  723.  
  724.   cleft = clientrect.left;
  725.   ctop = clientrect.top;
  726.   cright = clientrect.right;
  727.   cbottom = clientrect.bottom;
  728.   cwidth = clientrect.right - clientrect.left;
  729.   cheight = clientrect.bottom - clientrect.top;
  730.  
  731.   // calculate rects: nbcrect, hsbrect, vsbrect, tsbrect, tabsrect
  732.   // remember: overlap standalone scrollbars with surround win borders
  733.   switch (tabloc){
  734.     case LOC_LEFT:
  735.             nbcrect = TRect(cleft-nbcheight, ctop, cleft, cbottom+hsheight);
  736.             if (hscrollon)
  737.               hsbrect = TRect(cleft-1, cbottom, cright+1, cbottom+hsheight);
  738.             if (vscrollon)
  739.               vsbrect = TRect(cright, ctop-1, cright+vswidth, cbottom+1);
  740.             CalcTabRects();
  741.             break;
  742.  
  743.     case LOC_TOP:
  744.             nbcrect = TRect(cleft, ctop-nbcheight, cright+vswidth, ctop);
  745.             if (hscrollon)
  746.               hsbrect = TRect(cleft-1, cbottom, cright+1, cbottom+hsheight);
  747.             if (vscrollon)
  748.               vsbrect = TRect(cright, ctop-1, cright+vswidth, cbottom+1);
  749.             CalcTabRects();
  750.             break;
  751.  
  752.     case LOC_RIGHT:
  753.             nbcrect = TRect(cright, ctop, cright+nbcheight, cbottom);
  754.             if (hscrollon)
  755.               hsbrect = TRect(cleft-1, cbottom, cright+1, cbottom+hsheight);
  756.             if (vscrollon)
  757.               vsbrect = TRect(cright+3, ctop+3*cheight/4, cright+3+vswidth,
  758.                       cbottom-2);
  759.             CalcTabRects();
  760.             break;
  761.  
  762.     case LOC_BOTTOM:
  763.             nbcrect = TRect(cleft, cbottom, cright, cbottom+nbcheight);
  764.             if (hscrollon)
  765.               hsbrect = TRect(cleft+3*cwidth/4, cbottom+7, cright-2,
  766.                       cbottom+7+hsheight);
  767.             if (vscrollon)
  768.               vsbrect = TRect(cright, ctop-1, cright+vswidth, cbottom+1);
  769.             CalcTabRects();
  770.             break;
  771.   }
  772.  
  773.   if (winhscroll)
  774.     winhscroll->ChangeRect(hsbrect, FALSE);
  775.   if (winvscroll)
  776.     winvscroll->ChangeRect(vsbrect, FALSE);
  777.   if (tabhscroll)
  778.     tabhscroll->ChangeRect(tsbrect, FALSE);
  779.   if (tabvscroll)
  780.     tabvscroll->ChangeRect(tsbrect, FALSE);
  781. }
  782. //----------------------------------------------------------------------------
  783. uint TNotebook::EvNCCalcSize(bool calcValidRects,
  784.     NCCALCSIZE_PARAMS far& calcSize)
  785. {
  786.   UINT status;
  787.   RECT far *rp;
  788.   int vswidth, hsheight;
  789.   TPoint wtopleft;
  790.  
  791.   // get upperleft corner of window in screen
  792.   rp = &calcSize.rgrc[0];       // window rect in screen coords
  793.   wtopleft = TPoint(rp->left, rp->top);
  794.  
  795.   status = TWindow::EvNCCalcSize(calcValidRects, calcSize);
  796.   rp = &calcSize.rgrc[0];       // client rect in screen coords
  797.  
  798.   if (! IsIconic()){
  799.     // change size of client window to allow for our area & scrollbars
  800.     // subtrack "1" from scrollbar sizes (overlap last line with win border)
  801.     vswidth = GetSystemMetrics(SM_CXVSCROLL) - 1;
  802.     hsheight = GetSystemMetrics(SM_CYHSCROLL) - 1;
  803.  
  804.     switch (tabloc) {
  805.             case LOC_LEFT:
  806.               rp->left += nbcheight;
  807.               if (vscrollon)
  808.                       rp->right -= vswidth;
  809.               if (hscrollon)
  810.                       rp->bottom -= hsheight;
  811.               break;
  812.  
  813.             case LOC_TOP:
  814.               rp->top += nbcheight;
  815.               if (vscrollon)
  816.                       rp->right -= vswidth;
  817.               if (hscrollon)
  818.                       rp->bottom -= hsheight;
  819.               break;
  820.  
  821.             case LOC_RIGHT:
  822.               rp->right -= nbcheight;
  823.               if (hscrollon)
  824.                       rp->bottom -= hsheight;
  825.               break;
  826.  
  827.             case LOC_BOTTOM:
  828.               rp->bottom -= nbcheight;
  829.               if (vscrollon)
  830.                       rp->right -= vswidth;
  831.               break;
  832.     }
  833.     if (rp->bottom < rp->top)
  834.             rp->bottom = rp->top;
  835.     if (rp->right < rp->left)
  836.             rp->right = rp->left;
  837.  
  838.     if (defer_ncpaint >= 0)
  839.             defer_ncpaint++;    // skip next ncpaint
  840.   }
  841.  
  842.   clientrect = TRect(*rp);
  843.   clientrect -= wtopleft;               // win-relative client rect
  844.  
  845.   return(status);
  846. }
  847. //----------------------------------------------------------------------------
  848. void TNotebook::ActivateTab(int tabnum)
  849. {
  850.   TRect myrect;
  851.   int oldactive, r;
  852.  
  853.   if (activetab != tabnum){
  854.     oldactive = activetab;
  855.     activetab = tabnum;
  856.  
  857.     Parent->SendMessage(NB_TABCHANGED, activetab, NULL);
  858.     if (IsIconic())
  859.             return;
  860.  
  861.     // repaint lines
  862.     TWindowDC mydc(*this);
  863.     DrawTabLines(mydc, nbcrect, FALSE);
  864.  
  865.     // repaint old tab and tab before it as nonactive
  866.     r = oldactive - firsttab - 1;
  867.     if ((r >= 0) && (r < rgncnt)) {
  868.             if (tabhorz)
  869.               DrawHorzTab(mydc, oldactive-1, r, toffs[r]);
  870.             else
  871.               DrawVertTab(mydc, oldactive-1, r, toffs[r]);
  872.     }
  873.     if ((r+1 >= 0) && (r+1 < rgncnt)) {
  874.             if (tabhorz)
  875.               DrawHorzTab(mydc, oldactive, r+1, toffs[r+1]);
  876.             else
  877.               DrawVertTab(mydc, oldactive, r+1, toffs[r+1]);
  878.     }
  879.  
  880.     // paint new active tab
  881.     r = activetab - firsttab;
  882.     if ((r >= 0) && (r < rgncnt)) {
  883.             if (tabhorz)
  884.               DrawHorzTab(mydc, activetab, r, toffs[r]);
  885.             else
  886.               DrawVertTab(mydc, activetab, r, toffs[r]);
  887.     }
  888.   }
  889. }
  890. //----------------------------------------------------------------------------
  891. void TNotebook::ScrollTabs(int delta)
  892. {
  893.   int oldfirst;
  894.  
  895.   oldfirst = firsttab;
  896.   firsttab += delta;
  897.  
  898.   if (firsttab < 0)
  899.     firsttab = 0;
  900.   else if (firsttab > tabcnt-1)
  901.     firsttab = tabcnt-1;
  902.  
  903.   if (firsttab != oldfirst) {
  904.     if (tabhscroll)
  905.             tabhscroll->SetScrollPos(firsttab, TRUE);
  906.     if (tabvscroll)
  907.             tabvscroll->SetScrollPos(firsttab, TRUE);
  908.     PaintNBC(NBC_PAINTTABS);
  909.   }
  910. }
  911. //----------------------------------------------------------------------------
  912. BOOL TNotebook::MyLButtonDown(UINT hitTest, TPoint& screenPt)
  913. {
  914.   int i;
  915.   BOOL match;
  916.   HRGN myrgn;
  917.  
  918.   TPoint winpt = screenPt - GetWindowRect().TopLeft();  // win coords
  919.  
  920.   if (nbcrect.Contains(winpt)) {
  921.     // see if mouse is on tab hscrollbar
  922.     if ((tabhscroll) && (tabhscroll->MyLButtonDown(hitTest, winpt)))
  923.             return(TRUE);
  924.     // see if mouse is on tab vscrollbar
  925.     if ((tabvscroll) && (tabvscroll->MyLButtonDown(hitTest, winpt)))
  926.             return(TRUE);
  927.  
  928.     // see if mouse down is in tabs
  929.     for (i=rgncnt-1; i >= 0; i--) {
  930.             myrgn = CreatePolygonRgn(tabpoints[i], 5, fillmode);
  931.             match = PtInRegion(myrgn, winpt.x, winpt.y);
  932.             DeleteObject(myrgn);
  933.             if (match) {
  934.               ActivateTab(firsttab+i);
  935.               return(TRUE);
  936.             }
  937.     }
  938.   }
  939.  
  940.   // see if mouse is on window hscrollbar
  941.   if ((hscrollon) && (winhscroll->MyLButtonDown(hitTest, winpt)))
  942.     return(TRUE);
  943.  
  944.   // see if mouse is on window vscrollbar
  945.   if ((vscrollon) && (winvscroll->MyLButtonDown(hitTest, winpt)))
  946.     return(TRUE);
  947.  
  948.   return(FALSE);
  949. }
  950. //----------------------------------------------------------------------------
  951. void TNotebook::EvNCLButtonDown(UINT hitTest, TPoint& screenPt)
  952. {
  953.   if (MyLButtonDown(hitTest, screenPt))
  954.     return;
  955.   TWindow::EvNCLButtonDown(hitTest, screenPt);
  956. }
  957. //----------------------------------------------------------------------------
  958. void TNotebook::EvNCLButtonDblClk(UINT hitTest, TPoint& screenPt)
  959. {
  960.   if (MyLButtonDown(hitTest, screenPt))
  961.     return;
  962.   TWindow::EvNCLButtonDblClk(hitTest, screenPt);
  963. }
  964. //----------------------------------------------------------------------------
  965. void TNotebook::EvMouseMove(UINT hitTest, TPoint& clientpt)
  966. {
  967.   // convert from client to windows coords
  968.   TPoint screenpt = clientpt;
  969.   ClientToScreen(screenpt);
  970.   TPoint winpt = screenpt - GetWindowRect().TopLeft();  // win coords
  971.  
  972.   // see if mouse has been captured by tab hscrollbar
  973.   if ((tabhscroll) && (tabhscroll->MyMouseMove(hitTest, winpt)))
  974.     return;
  975.   // see if mouse has been captured by tab vscrollbar
  976.   if ((tabvscroll) && (tabvscroll->MyMouseMove(hitTest, winpt)))
  977.     return;
  978.  
  979.   // see if mouse has been captured by window hscrollbar
  980.   if ((hscrollon) && (winhscroll->MyMouseMove(hitTest, winpt)))
  981.     return;
  982.   // see if mouse has been captured by window vscrollbar
  983.   if ((vscrollon) && (winvscroll->MyMouseMove(hitTest, winpt)))
  984.     return;
  985.  
  986.   TWindow::EvNCMouseMove(hitTest, clientpt);
  987. }
  988. //----------------------------------------------------------------------------
  989. void TNotebook::EvLButtonUp(UINT hitTest, TPoint& clientpt)
  990. {
  991.   // convert from client to windows coords
  992.   TPoint screenpt = clientpt;
  993.   ClientToScreen(screenpt);
  994.   TPoint winpt = screenpt - GetWindowRect().TopLeft();  // win coords
  995.  
  996.   // see if mouse has been captured by tab hscrollbar
  997.   if ((tabhscroll) && (tabhscroll->MyLButtonUp(hitTest, winpt)))
  998.     return;
  999.   // see if mouse has been captured by tab vscrollbar
  1000.   if ((tabvscroll) && (tabvscroll->MyLButtonUp(hitTest, winpt)))
  1001.     return;
  1002.  
  1003.   // see if mouse has been captured by window hscrollbar
  1004.   if ((hscrollon) && (winhscroll->MyLButtonUp(hitTest, winpt)))
  1005.     return;
  1006.  
  1007.   // see if mouse has been captured by window vscrollbar
  1008.   if ((vscrollon) && (winvscroll->MyLButtonUp(hitTest, winpt)))
  1009.     return;
  1010.  
  1011.   TWindow::EvNCLButtonUp(hitTest, clientpt);
  1012. }
  1013. //----------------------------------------------------------------------------
  1014. void TNotebook::EvGetMinMaxInfo(MINMAXINFO far& minmaxinfo)
  1015. {
  1016.   TWindow::EvGetMinMaxInfo(minmaxinfo);
  1017.   minmaxinfo.ptMinTrackSize.x += (nbcheight+2);
  1018.   minmaxinfo.ptMinTrackSize.y += (nbcheight+2);
  1019. }
  1020. //----------------------------------------------------------------------------
  1021. void TNotebook::SetTabCnt(int Tabcnt, int Firsttab, int Activetab)
  1022. {
  1023.   tabcnt = Tabcnt;
  1024.   firsttab = Firsttab;
  1025.   ActivateTab(Activetab);
  1026.   if (tabhscroll){
  1027.     tabhscroll->SetScrollRange(0, tabcnt, FALSE);
  1028.     tabhscroll->SetScrollPos(activetab, TRUE);
  1029.   }
  1030.   if (tabvscroll){
  1031.     tabvscroll->SetScrollRange(0, tabcnt, FALSE);
  1032.     tabvscroll->SetScrollPos(activetab, TRUE);
  1033.   }
  1034.   PaintNBC(NBC_PAINTTABS);
  1035. }
  1036. //----------------------------------------------------------------------------
  1037. bool TNotebook::EvNCCreate(CREATESTRUCT far& createStruct)
  1038. {
  1039.   long wstyle;
  1040.   BOOL status;
  1041.  
  1042.   // we will draw hscroll and vscroll if needed; tell windows not to bother
  1043.   wanthscroll = ((createStruct.style & WS_HSCROLL) != 0);
  1044.   wantvscroll = ((createStruct.style & WS_VSCROLL) != 0);
  1045.  
  1046.   // reset WS_HSCROLL and WH_VSCROLL in both style locations "just in case..."
  1047.   createStruct.style &= ~(WS_HSCROLL | WS_VSCROLL);
  1048.   wstyle = GetWindowLong(GWL_STYLE);
  1049.   wstyle &= ~(WS_HSCROLL | WS_VSCROLL);
  1050.   SetWindowLong(GWL_STYLE, wstyle);
  1051.  
  1052.   status = TWindow::EvNCCreate(createStruct);
  1053.   CreateScrollBars();
  1054.   return(status);
  1055. }
  1056. //----------------------------------------------------------------------------
  1057. void TNotebook::EvSize(UINT sizeType, TSize& newsize)
  1058. {
  1059.   TWindow::EvSize(sizeType, newsize);
  1060.   ComputeSizes();
  1061.   if (! defer_ncpaint) {
  1062.     defer_ncpaint = 1;
  1063.     ForceResize(TRUE);
  1064.   }
  1065. }
  1066. //----------------------------------------------------------------------------
  1067. LRESULT TNotebook::NWHscroll(WPARAM wparam, LPARAM lparam)
  1068. {
  1069.   int thumbpos = LOWORD(lparam);
  1070.   int ctrlid = HIWORD(lparam);
  1071.  
  1072.   if (ctrlid != ID_TABSB)
  1073.     return(0);
  1074.  
  1075.   switch (wparam) {
  1076.     case SB_LINELEFT:
  1077.             ScrollTabs(-1);
  1078.             break;
  1079.  
  1080.     case SB_LINERIGHT:
  1081.             ScrollTabs(1);
  1082.             break;
  1083.  
  1084.     case SB_PAGELEFT:
  1085.             if (rgncnt < 2)
  1086.               ScrollTabs(-1);
  1087.             else
  1088.               ScrollTabs(-(rgncnt-1));
  1089.             break;
  1090.  
  1091.     case SB_PAGERIGHT:
  1092.             if (rgncnt < 2)
  1093.               ScrollTabs(1);
  1094.             else
  1095.               ScrollTabs(rgncnt-1);
  1096.             break;
  1097.  
  1098.     case SB_THUMBPOSITION:
  1099.             ScrollTabs(thumbpos-firsttab);
  1100.             break;
  1101.   }
  1102.  
  1103.   return(0);
  1104. }
  1105. //----------------------------------------------------------------------------
  1106. void TNotebook::CreateScrollBars()
  1107. {
  1108.   if (tabhorz){
  1109.     tabhscroll = new THScroll(this, 0, 0, 1, 1, ID_TABSB, 0, tabcnt-1, 0,
  1110.           TRUE, FALSE, TRUE);
  1111.   } else {
  1112.     tabvscroll = new TVScroll(this, 0, 0, 1, 1, ID_TABSB, 0, tabcnt-1, 0,
  1113.           TRUE, FALSE, TRUE);
  1114.   }
  1115.  
  1116.   if (wanthscroll) {
  1117.     winhscroll = new THScroll(this, 0, 0, 1, 1, ID_WINHSB, 0, 100, 0,
  1118.           FALSE, TRUE, FALSE);
  1119.     hscrollon = TRUE;
  1120.   }
  1121.   if (wantvscroll) {
  1122.     winvscroll = new TVScroll(this, 0, 0, 1, 1, ID_WINVSB, 0, 100, 0,
  1123.           FALSE, TRUE, FALSE);
  1124.     vscrollon = TRUE;
  1125.   }
  1126. }
  1127. //----------------------------------------------------------------------------
  1128. void TNotebook::EvSysColorChange()
  1129. {
  1130.   DeletePaintObjects();
  1131.   BuildPaintObjects();
  1132.  
  1133.   if (tabhscroll)
  1134.     tabhscroll->SysColorChange();
  1135.   if (tabvscroll)
  1136.     tabvscroll->SysColorChange();
  1137.   if (winhscroll)
  1138.     winhscroll->SysColorChange();
  1139.   if (winvscroll)
  1140.     winvscroll->SysColorChange();
  1141.  
  1142.   TWindow::EvSysColorChange();
  1143. }
  1144. //----------------------------------------------------------------------------
  1145. int TNotebook::GetScrollPos(int bar)
  1146. {
  1147.   if ((bar == SB_HORZ) && (winhscroll))
  1148.     return(winhscroll->GetScrollPos());
  1149.   else if ((bar == SB_VERT) && (winvscroll))
  1150.     return(winvscroll->GetScrollPos());
  1151.  
  1152.   return(0);
  1153. }
  1154. //----------------------------------------------------------------------------
  1155. void TNotebook::GetScrollRange(int bar, int &low, int &high)
  1156. {
  1157.   if ((bar == SB_HORZ) && (winhscroll))
  1158.     winhscroll->GetScrollRange(low, high);
  1159.   else if ((bar == SB_VERT) && (winvscroll))
  1160.     winvscroll->GetScrollRange(low, high);
  1161. }
  1162. //----------------------------------------------------------------------------
  1163. int TNotebook::SetScrollPos(int bar, int pos, BOOL redraw)
  1164. {
  1165.   if ((bar == SB_HORZ) && (winhscroll))
  1166.     return(winhscroll->SetScrollPos(pos, redraw));
  1167.   else if ((bar == SB_VERT) && (winvscroll))
  1168.     return(winvscroll->SetScrollPos(pos, redraw));
  1169.  
  1170.   return(0);
  1171. }
  1172. //----------------------------------------------------------------------------
  1173. void TNotebook::SetScrollRange(int bar, int  minPos, int  maxPos, BOOL redraw)
  1174. {
  1175.   BOOL showit = (minPos != maxPos);
  1176.  
  1177.   if ((bar == SB_HORZ) && (winhscroll)){
  1178.     if (hscrollon != showit) {
  1179.             hscrollon = showit;
  1180.             winhscroll->ShowScrollBar(showit);
  1181.             ForceResize(FALSE);
  1182.     }
  1183.     winhscroll->SetScrollRange(minPos, maxPos, redraw);
  1184.   } else if ((bar == SB_VERT) && (winvscroll)) {
  1185.     if (vscrollon != showit){
  1186.             vscrollon = showit;
  1187.             winvscroll->ShowScrollBar(showit);
  1188.             ForceResize(FALSE);
  1189.     }
  1190.     winvscroll->SetScrollRange(minPos, maxPos, redraw);
  1191.   }
  1192. }
  1193. //----------------------------------------------------------------------------
  1194. void TNotebook::ForceResize(BOOL repaint)
  1195. {
  1196.   // force a RECALC SIZE and possibly REPAINT of non-client area thru
  1197.   // following wierd code...
  1198.  
  1199.   TRect wrect;
  1200.   int width, height;
  1201.  
  1202.   wrect = GetWindowRect();
  1203.   TPoint tl = wrect.TopLeft();
  1204.   TPoint br = wrect.BottomRight();
  1205.   Parent->ScreenToClient(tl);
  1206.   Parent->ScreenToClient(br);
  1207.  
  1208.   width = br.x - tl.x;
  1209.   height = br.y - tl.y;
  1210.  
  1211.   MoveWindow(tl.x, tl.y, width, height+1, TRUE);
  1212.   if (repaint)
  1213.     defer_ncpaint = -1;         // do ncpaint but don't call myself
  1214.   MoveWindow(tl.x, tl.y, width, height, TRUE);
  1215.   if (repaint)
  1216.     defer_ncpaint = 0;
  1217. }
  1218. //----------------------------------------------------------------------------
  1219. void TNotebook::BuildBgBrush()
  1220. {
  1221.   struct {
  1222.     BITMAPINFOHEADER hdr;
  1223.     RGBQUAD colors[2];
  1224.   } bmi;
  1225.  
  1226.   HBITMAP mybitmap;
  1227.   TWindowDC mydc(*this);
  1228.   unsigned char bits[8*sizeof(DWORD)];
  1229.   COLORREF color;
  1230.   HBRUSH hbrush;
  1231.  
  1232.   bmi.hdr.biSize = sizeof(BITMAPINFOHEADER);
  1233.   bmi.hdr.biWidth = 8;
  1234.   bmi.hdr.biHeight = 8;
  1235.   bmi.hdr.biPlanes = 1;
  1236.   bmi.hdr.biBitCount = 1;
  1237.   bmi.hdr.biSizeImage = 0;
  1238.   bmi.hdr.biCompression = BI_RGB;
  1239.   bmi.hdr.biClrUsed = 0;
  1240.   bmi.hdr.biClrImportant = 0;
  1241.  
  1242.   memset(bits, 0, sizeof(bits));
  1243.   bits[0 * sizeof(DWORD)] = 0xAA;
  1244.   bits[2 * sizeof(DWORD)] = 0xAA;
  1245.   bits[4 * sizeof(DWORD)] = 0xAA;
  1246.   bits[6 * sizeof(DWORD)] = 0xAA;
  1247.   bits[1 * sizeof(DWORD)] = 0x55;
  1248.   bits[3 * sizeof(DWORD)] = 0x55;
  1249.   bits[5 * sizeof(DWORD)] = 0x55;
  1250.   bits[7 * sizeof(DWORD)] = 0x55;
  1251.  
  1252.   color = GetSysColor(COLOR_BTNFACE);
  1253.   bmi.colors[0].rgbRed = GetRValue(color);
  1254.   bmi.colors[0].rgbGreen = GetGValue(color);
  1255.   bmi.colors[0].rgbBlue = GetBValue(color);
  1256.   bmi.colors[0].rgbReserved = 0;
  1257.  
  1258.   color = GetSysColor(COLOR_BTNHIGHLIGHT);
  1259.   bmi.colors[1].rgbRed = GetRValue(color);
  1260.   bmi.colors[1].rgbGreen = GetGValue(color);
  1261.   bmi.colors[1].rgbBlue = GetBValue(color);
  1262.   bmi.colors[1].rgbReserved = 0;
  1263.  
  1264.   mybitmap = ::CreateDIBitmap(mydc, &bmi.hdr, CBM_INIT, bits,
  1265.     (LPBITMAPINFO)&bmi, DIB_RGB_COLORS);
  1266.   hbrush = ::CreatePatternBrush(mybitmap);
  1267.   bgbrush = new TBrush(hbrush);
  1268.   ::DeleteObject(mybitmap);
  1269. }
  1270. //----------------------------------------------------------------------------
  1271.