We help IT Professionals succeed at work.

Problem using TScroller if unit !=1

moczar
moczar asked
on
Medium Priority
357 Views
Last Modified: 2013-12-03
I develop a program under Windows95 using Borland C++ 5.00 and OWL5.0.
The scroll box (thumb) desn't scroll the whole range if the unit parameter (e.g. YUnit) of TScroller differs from 1, but the arrows at the end of the scrollbar work correctly. Furthermore if the range parameter (YRange) is a little value (e.g. 6) the scrollbar doesn't appear. See the sample program of BC++ 5.00 in the examples\owl\classes\scroller directory.
Does anybody know a solution for my problem? Thanks.
Comment
Watch Question

Author

Commented:
Edited text of question

Commented:
You have to make your window scrollable :

put in your constructor follow :

{
...

Attr.tyle |= WS_HSCROLL | WS_VSCROLL ;
Sceoller = TScroller ( ... ) ;

...
}


It works fro me in 100% of cases.

Hope it helps

Author

Commented:
This is a code fragment of the Borland OWL sample program (examples\owl\classes\scroller\scrollex.cpp). It generates the described error for me.

const int XUnits = 7;
const int YUnits = 16;
const int XRange = 80;
const int YRange = 6; //60; was originally

// class TScrollWindow
class TScrollWindow : public TWindow {
  public:
    TScrollWindow(TWindow* parent = 0, const char* title = 0);
    void Paint(TDC& dc, bool, TRect&);
};

// Constructor for a TScrollWindow, sets scroll styles and
// constructs the Scroller object.

TScrollWindow::TScrollWindow(TWindow* parent, const char* title)
:
  TWindow(parent, title)
{
  Attr.Style |= WS_VSCROLL | WS_HSCROLL;
  Scroller = new TScroller(this, XUnits, YUnits, XRange, YRange);
}


Commented:
You cannot just change ranges like that and expect it to work properly.  Keep in mind that TScroller does not care what is in the window.  YOU are responsible for resetting the scrollers range and units every time the user resizes the window, etc.  If you set the range to 6 it's going to let you hit the down arrow 5 times and that's it. If you don't get all the way to the bottom of what you're trying to display it's your own fault.

Author

Commented:
Thank you for the answer. But it is not the content of the window  I have problems with. I have problem with the scrollbar itself.

Problem 1.: If the YRange is a small value (e.g. 6) the scrollbar doesn't appear. Why?

Problem 2.: If the YRange is a bigger value (e.g.60) the scrollbar appears and the arrows at its end work correctly, that is you can hit the down arrow 59 times. However if you don't scroll the window with the arrows but with the thumb (the scroll rectangle) it scrolls less, about 47 steps. In other words, the arrows at the end of it work properly, but dragging the thumb rectangle and pulling it from one end of the scrollbar to the other doesn't provide as big scrolling as the arrows did. Why?

There are errors in implementation of TScroller in OWL (namely in TScroller::SetPageSize()).
It is not work correctly if XUnit (YUnit)!=1.

Problem1:
If you set YRange=6, YUnit=8, TScroller set range value for window's scroll bar as 6, page size as 8. It is standard Windows behavior with these values to hide scroll bar.

Problem2:
There are two class members in TScroller,  XTotalUnits and YTotalUnits. You need to set them also. But as I said TScroller will not work correctly even in this case.

I had to write my own NScroller (descendant from TScroller) to fix this problem and to use variable-length thumb.

 May be better way for you to set  XUnit=YUnit=1, but use XLine & YLine instead.

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts

Author

Commented:
Thank you for your answer.
The 'XUnit==YUnit=1 XLine,YLine' solution didn't conduce me to fix the Problem2. Would you describe me more detailed how to fix this problem using a descendant from TScroller, please!
Thank you.
I used window with MM_ISOTROPIC map mode and various set of SetWindowExt&SetViewPortExt to display bitmap with different zoom value (5...3000%). But in following code I have stripped lines that handle zoom job.
I suppose your window has MM_TEXT map mode (1 device unit = 1 logical unit).

You can compare NScroller code with
TScroller source (BC5\SOURCE\OWL\scroller.cpp).

Write me if you have any questions.

//---------------------------------------------------------------------------
// NScroller class
//---------------------------------------------------------------------------
class NScroller : public TScroller
{
   public:
      NScroller(TWindow* win) : TScroller(win,1,1,0,0) { }
      void SetPageSize();
      void SetSBarRange() { }   // Override parent's function!
      void SetRange(long xRange,long yRange);
};
//---------------------------------------------------------------------------
void NScroller::SetPageSize()
{
   if(Window && Window->GetHandle()) {
      TPoint p(Window->GetClientRect().Size());
      if(p.x<1) p.x=1;
      if(p.y<1) p.y=1;

      // Number of bitmap's pixels to scroll when user press arrow
      // on scroll bar
      XLine=YLine=1;

      // Range to scroll, must be less then XTotalUnits (bitmap's width)
      XRange=XTotalUnits+1-p.x;
      YRange=YTotalUnits+1-p.y;

      // Page size equal width (height) of  window's client area
      XPage=p.x;
      YPage=p.y;

      Window->SetScrollPage(SB_HORZ,XPage,true);
      Window->SetScrollPage(SB_VERT,YPage,true);
      ScrollTo(XPos,YPos);
   }
}
//---------------------------------------------------------------------------
void NScroller::SetRange(long xRange,long yRange)
{
   XTotalUnits=xRange-1;
   YTotalUnits=yRange-1;
   if(Window && Window->GetHandle()) {
      int curMin,curMax;
      Window->GetScrollRange(SB_HORZ,curMin,curMax);
      int newMax=max(0,min(int(XTotalUnits),SHRT_MAX));
      if(newMax!=curMax || curMin!=0)
         Window->SetScrollRange(SB_HORZ,0,newMax,false);
      Window->GetScrollRange(SB_VERT,curMin,curMax);
      newMax=max(0,min(int(YTotalUnits),SHRT_MAX));
      if(newMax!=curMax || curMin!=0)
         Window->SetScrollRange(SB_VERT,0,newMax,false);
   }
   SetPageSize();
}

//---------------------------------------------------------------------------
// NView (bitmap's window) class functions
//---------------------------------------------------------------------------
NView::NView(...) : TMDIChild(parent)
{
   Attr.Style|=WS_VSCROLL|WS_HSCROLL;
   Scroller=new NScroller(this);
}
//---------------------------------------------------------------------------
bool NView::SetDib(TDib* newdib)
{

   // This function loads image into window
   // ...
   // Setting scroller range
   if(newdib==0)
      Scroller->SetRange(0,0);   // Hide scroll bar
   else
      Scroller->SetRange(dib->Width(),dib->Height());

   Invalidate();
   UpdateWindow();
}
//---------------------------------------------------------------------------
void NView::Paint(...)
{
   // ...
}
//---------------------------------------------------------------------------

Author

Commented:
Thank you very much, it works fine.
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.