Discussion:
SIF_DISABLENOSCROLL
(too old to reply)
none
2012-06-07 05:17:25 UTC
Permalink
Hi,

I am using the "CGridCtrl" class from thecodeproject.com, which is fairly
widely used. It is quite buggy but can be beaten into shape if you are
persistent enough. I only mention that I'm using it to point out that
there's a ton of code that I didn't write, so there might be a hidden bug
that I just haven't found.

It's a grid control for doing spreadsheet-type stuff. It automatically
shows scroll bars when the grid doesn't fit in the window's client area.
I'm having some really bizarre problems with the scroll bars -- and
apparently, I'm not the first, because the source is littered with comments
like "changed this to avoid infinite loop" wherever the scroll bars are
involved. And still, I occaisionally see infinite loops when scrolling
around the grid...

So, what I thought I would do is just force the scroll bars to always be
shown, but disabled when not needed. That would eliminate the constant
showing/hiding of the bars, which causes the client area to shrink/expand,
which causes the grid to recalculate its size, and so on and so on.

All I did was find all calls to CWnd::SetScrollInfo() and added the
SIF_DISABLENOSCROLL to the SCROLLINFO's fMask member. For good measure, I
also added it to any calls to CWnd::GetScrollInfo(), but the documentation
seems to say that it's ignored there.

The end result is that the scroll bars are always shown, sometimes
disabled, on *most* systems. On some systems (both XP and Win 7), though,
only the horizontal bar is shown and the vertical bar just disappears as if
I hadn't specified the SIF_DISABLENOSCROLL flag.

Any idea what I might be doing wrong, or what might be lurking somewhere in
the CGridCtrl code that is overriding my flag? I've searched the code
thoroughly for SetScrollInfo() calls and even "SIF_..." and there aren't
any matches.

Thanks.
none
2012-06-07 16:37:53 UTC
Permalink
I experimented with this problem and I've found that scroll bars in MFC
(or possibly just in Windows) are finicky. I guess that's why the
CGridCtrl source is so ugly where it deals with scroll bars.

I found that if the scroll bar is drawn at least once, *enabled* with
the SIF_DISABLENOSCROLL flag, then it behaves like you would expect.
But if it is drawn first with a range/page setting that would cause it
to be *diabled* and the SIF_DISABLENOSCROLL flag is specified, it will
disappear.

So, to workaround, my code looks like this:

-----------------------------------------------------------------------

SCROLLINFO si;
si.cbSize = sizeof(SCROLLINFO);

// Windows bug:
// The scroll bars must be drawn at least once, enabled and visible,
// before being drawn disabled and visible, or they will sometimes
// default to being hidden
if (!m_scrollbars_initialized)
{
si.fMask = SIF_ALL | SIF_DISABLENOSCROLL;

// Reasonable default values
si.nMin = 0;
si.nMax = 100;
si.nPage = 10;
si.nPos = 0;
si.nTrackPos = 0;

SetScrollInfo(SB_BOTH, &si);

// Set flag, no need to do this again
m_scrollbars_initialized = true;
}

si.fMask = SIF_ALL | SIF_DISABLENOSCROLL;
si.nMin = 0;
si.nMax = grid_v_size;
si.nPage = client_height;
si.nPos = current_v_scroll_pos;
si.nTrackPos = current_v_scroll_pos;

SetScrollInfo(SB_VERT, &si);

si.fMask = SIF_ALL | SIF_DISABLENOSCROLL;
si.nMin = 0;
si.nMax = grid_h_size;
si.nPage = client_width;
si.nPos = current_h_scroll_pos;
si.nTrackPos = current_h_scroll_pos;

SetScrollInfo(SB_HORZ, &si);

-----------------------------------------------------------------------

Maybe that will help someone running into the same problem.

Loading...