wxListCtrl column widths when vertical scrollbars are enabled

49 views
Skip to first unread message

jon bird

unread,
Aug 5, 2022, 4:41:30 AM8/5/22
to wx-u...@googlegroups.com
Hi,

I seem to have encountered a slight issue where wxListCtrl columns are
not quite sized correctly when scrollbars come into play. Initially I
thought this was down to using wxLIST_AUTOSIZE instead of
wxLIST_AUTOSIZE_USEHEADER (as per the discussion around TRAC ticket
#10326), that seemed to initially improve things but was still seeing
occasions when I was getting a horizontal scrollbar appear unexpectedly.

After a bit of further digging, it seems that everything is fitting
correctly until there are more items in the list that then require a
vertical scrollbar to be enabled. At which point a horizontal
scrollbar is also enabled - just enough to scroll a character or two
into view.

My guess would be that the sizing logic isn't compensating for this
condition - taking into account the width of the vertical scrollbar.

This is on MSW, using wxWidgets 3.1.5, using a non-virtual listtrl
where all the items are populated at the point the window is
constructed.

Rgs,

Jon.

--
--
== jon bird - software engineer
== <reply to address _may_ be invalid, real mail below>
== <reduce rsi, stop using the shift key>
== posted as: news 'at' onasticksoftware 'dot' co 'dot' uk

Vadim Zeitlin

unread,
Aug 7, 2022, 1:20:24 PM8/7/22
to wx-u...@googlegroups.com
On Fri, 5 Aug 2022 09:41:07 +0100 jon bird wrote:

jb> I seem to have encountered a slight issue where wxListCtrl columns are
jb> not quite sized correctly when scrollbars come into play. Initially I
jb> thought this was down to using wxLIST_AUTOSIZE instead of
jb> wxLIST_AUTOSIZE_USEHEADER (as per the discussion around TRAC ticket
jb> #10326),

I think that ticket was about the generic version only and nothing done
there should have affected wxMSW version.

jb> My guess would be that the sizing logic isn't compensating for this
jb> condition - taking into account the width of the vertical scrollbar.
jb>
jb> This is on MSW, using wxWidgets 3.1.5, using a non-virtual listtrl
jb> where all the items are populated at the point the window is
jb> constructed.

I don't think we can do much about what the native control does, but to
even try doing it, we'd need, as always, a way of reproducing the problem.
If you can do it in the listctrl sample, with minimal changes, please open
a new issue and attach your changes to it.

Thanks,
VZ

--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/

jon bird

unread,
Jan 8, 2023, 11:51:59 AM1/8/23
to wx-u...@googlegroups.com
On Fri, 5 Aug 2022 09:41:07 +0100
jon bird <ne...@onasticksoftware.co.uk> wrote:

> Hi,
>
> I seem to have encountered a slight issue where wxListCtrl columns are
> not quite sized correctly when scrollbars come into play. Initially I
> thought this was down to using wxLIST_AUTOSIZE instead of
> wxLIST_AUTOSIZE_USEHEADER (as per the discussion around TRAC ticket
> #10326), that seemed to initially improve things but was still seeing
> occasions when I was getting a horizontal scrollbar appear
> unexpectedly.
>
> After a bit of further digging, it seems that everything is fitting
> correctly until there are more items in the list that then require a
> vertical scrollbar to be enabled. At which point a horizontal
> scrollbar is also enabled - just enough to scroll a character or two
> into view.
>
> My guess would be that the sizing logic isn't compensating for this
> condition - taking into account the width of the vertical scrollbar.
>
> This is on MSW, using wxWidgets 3.1.5, using a non-virtual listtrl
> where all the items are populated at the point the window is
> constructed.
>
I posted the above a few months back, didn't take it any further at the
time because it wasn't a big issue and I had more important stuff to
do. However I have bumped into (or related to) the issue a couple of
times since and have delved a bit further.

In my latest encounter, it's a slightly different scenario, here I have
a small (headerless) list control with two columns. I want each column
to occupy 50% of the total available width. I set this up when the
dialog is constructed as follows:

wxSize SelectorSize(m_MultiDetails->GetClientSize());

m_MultiDetails->SetColumnWidth(MultiLViewColTitle,
(float)SelectorSize.GetX() / 2 );
m_MultiDetails->SetColumnWidth(MultiLViewColArtist,
(float)SelectorSize.GetX() / 2 );

At this point the list control is empty, as items are added everything
works as expected until there is not enough visible area to display all
items - at which point a vertical scroll bar is added AND a horizontal
scrollbar (in effect the same behaviour as described in my original
post).

Having thought about it, this behaviour makes sense: at the point the
vertical scrollbar is added, the horizontal client area has been
reduced, hence the inclusion of the x-axis scrollbar (I'm not totally
convinced it is the desired behaviour when the column width is set via
wxLIST_AUTOSIZE but in this case, where I've manually set them, it
does).

Since this isn't the behaviour I want, I planned to deal with it
by checking for when the vertical scrollbar gets enabled as part of the
logic that gets invoked when a new item is added - essentially by
calling wxWindow::HasScrollbar (on the wxListCtrl). I can then resize
the column widths accordingly. But this _always_ returns false even if
a vertical scrollbar is present. Here's the code which implements this:

bool wxWindowBase::CanScroll(int orient) const
{
return (m_windowStyle &
(orient == wxHORIZONTAL ? wxHSCROLL : wxVSCROLL)) != 0;
}

bool wxWindowBase::HasScrollbar(int orient) const
{
// if scrolling in the given direction is disabled, we can't have
the
// corresponding scrollbar no matter what
if ( !CanScroll(orient) )
return false;

const wxSize sizeVirt = GetVirtualSize();
const wxSize sizeClient = GetClientSize();

return orient == wxHORIZONTAL ? sizeVirt.x > sizeClient.x
: sizeVirt.y > sizeClient.y;
}

As can be seen, this totally relies on the window style being set with
the appropriate scrollbar, always returning false if not. Hence it's
never going to yield correct information on a control which
dynamically enables/disables scrollbars.

My initial workaround attempt was to bypass that initial check and see
what the computation that would then be performed would yield but
GetClientSize and GetVirtualSize always come back with the same numbers
so the result likewise comes back false. This same logic appears to be
in play with the latest 3.2.1 release.

My current workaround has been to use native Win32 code which does then
yield the expected result:

SCROLLBARINFO ScrollBarInfo;

ScrollBarInfo.cbSize = sizeof(SCROLLBARINFO);
if (::GetScrollBarInfo(AudioQueueListBox->GetHWND(), OBJID_VSCROLL,
&ScrollBarInfo))
{
if (!(ScrollBarInfo.rgstate[0] & STATE_SYSTEM_INVISIBLE))
ScrollState = true ;
}

I think something like this needs to be included as part of the scroll
detection logic however I've got zero experience on GTK and the like so
don't know what that would look like for those.

Vadim Zeitlin

unread,
Jan 9, 2023, 6:08:50 PM1/9/23
to wx-u...@googlegroups.com
On Sun, 8 Jan 2023 16:51:43 +0000 jon bird wrote:

jb> In my latest encounter, it's a slightly different scenario, here I have
jb> a small (headerless) list control with two columns. I want each column
jb> to occupy 50% of the total available width. I set this up when the
jb> dialog is constructed as follows:
jb>
jb> wxSize SelectorSize(m_MultiDetails->GetClientSize());
jb>
jb> m_MultiDetails->SetColumnWidth(MultiLViewColTitle,
jb> (float)SelectorSize.GetX() / 2 );
jb> m_MultiDetails->SetColumnWidth(MultiLViewColArtist,
jb> (float)SelectorSize.GetX() / 2 );

An ugly but very simple solution is to just always leave enough space for
the vertical scrollbar by subtracting extra GetMetric(wxSYS_VSCROLL_X) from
the width here.

jb> Since this isn't the behaviour I want, I planned to deal with it
jb> by checking for when the vertical scrollbar gets enabled as part of the
jb> logic that gets invoked when a new item is added - essentially by
jb> calling wxWindow::HasScrollbar (on the wxListCtrl). I can then resize
jb> the column widths accordingly. But this always returns false even if
jb> a vertical scrollbar is present.

Yes, having all scrollbar-related methods in wxWindow is very misleading,
as they're only used for the scrolling implemented at wx level and never
used by the native controls. Generally speaking we probably can't fix it,
but we could override CanScroll() in wxListCtrl to always return true. If
this is enough to make HasScrollbar() work, I would be for doing it
already.

IMO even better would be to generate an event notifying about the
scrollbar (dis)appearance, but I don't know if this can be implemented for
all platforms (or even one of them, for that matter).

Regards,

jon bird

unread,
Jan 11, 2023, 3:09:02 PM1/11/23
to wx-u...@googlegroups.com
On Tue, 10 Jan 2023 00:08:47 +0100
Vadim Zeitlin <va...@wxwidgets.org> wrote:

> On Sun, 8 Jan 2023 16:51:43 +0000 jon bird wrote:
>
> jb> In my latest encounter, it's a slightly different scenario, here
> jb> I have a small (headerless) list control with two columns. I want
> jb> each column to occupy 50% of the total available width. I set
> jb> this up when the dialog is constructed as follows:
> jb>
> jb> wxSize SelectorSize(m_MultiDetails->GetClientSize());
> jb>
> jb> m_MultiDetails->SetColumnWidth(MultiLViewColTitle,
> jb> (float)SelectorSize.GetX() / 2 );
> jb> m_MultiDetails->SetColumnWidth(MultiLViewColArtist,
> jb> (float)SelectorSize.GetX() / 2 );
>
> An ugly but very simple solution is to just always leave enough
> space for the vertical scrollbar by subtracting extra
> GetMetric(wxSYS_VSCROLL_X) from the width here.
>
Yes, I'd used this approach in another instance but in this case, where
the listview in question is quite small, space is at a premium so it's
less than ideal.

> jb> Since this isn't the behaviour I want, I planned to deal with it
> jb> by checking for when the vertical scrollbar gets enabled as part
> jb> of the logic that gets invoked when a new item is added -
> jb> essentially by calling wxWindow::HasScrollbar (on the
> jb> wxListCtrl). I can then resize the column widths accordingly. But
> jb> this always returns false even if a vertical scrollbar is
> jb> present.
>
> Yes, having all scrollbar-related methods in wxWindow is very
> misleading, as they're only used for the scrolling implemented at wx
> level and never used by the native controls. Generally speaking we
> probably can't fix it, but we could override CanScroll() in
> wxListCtrl to always return true. If this is enough to make
> HasScrollbar() work, I would be for doing it already.
>
It would be better, imho to use the code fragment I put in my original
post, that (at least for MSW) would give the correct result rather than
simply returning true.

> IMO even better would be to generate an event notifying about the
> scrollbar (dis)appearance, but I don't know if this can be
> implemented for all platforms (or even one of them, for that matter).
>
Agreed and in an ideal world, columns set to wxLIST_AUTOSIZE would then
automatically adjust themselves to avoid the generation of the
horizontal scrollbar. However, whilst it's a little bit of a faff, if
HasScrollbar() does return the correct status, this can be handled ok
in the application code. It's the fact that at present I'm needing to
include platform specific code in there to accomplish it, with the added
downside that since I don't know how to do the same in gtk, I can't get
the desired behaviour under Linux.

Vadim Zeitlin

unread,
Jan 11, 2023, 7:56:50 PM1/11/23
to wx-u...@googlegroups.com
On Wed, 11 Jan 2023 20:08:47 +0000 jon bird wrote:

jb> It would be better, imho to use the code fragment I put in my original
jb> post, that (at least for MSW) would give the correct result rather than
jb> simply returning true.

Yes, I guess this would indeed be an improvement. Would you be interested
in making a PR with this change?

Ideal would be to also add a test (even if a MSW-only one) as currently we
don't test this function at all...

jon bird

unread,
Jan 13, 2023, 1:38:38 PM1/13/23
to wx-u...@googlegroups.com
On Thu, 12 Jan 2023 01:56:46 +0100
Vadim Zeitlin <va...@wxwidgets.org> wrote:

> On Wed, 11 Jan 2023 20:08:47 +0000 jon bird wrote:
>
> jb> It would be better, imho to use the code fragment I put in my
> jb> original post, that (at least for MSW) would give the correct
> jb> result rather than simply returning true.
>
> Yes, I guess this would indeed be an improvement. Would you be
> interested in making a PR with this change?
>
> Ideal would be to also add a test (even if a MSW-only one) as
> currently we don't test this function at all...
>
Yes, if you point me in the right direction, I'll see what I can do.

Vadim Zeitlin

unread,
Jan 13, 2023, 1:52:18 PM1/13/23
to wx-u...@googlegroups.com
On Fri, 13 Jan 2023 18:38:23 +0000 jon bird wrote:

jb> On Thu, 12 Jan 2023 01:56:46 +0100
jb> Vadim Zeitlin <va...@wxwidgets.org> wrote:
jb>
jb> > On Wed, 11 Jan 2023 20:08:47 +0000 jon bird wrote:
jb> >
jb> > jb> It would be better, imho to use the code fragment I put in my
jb> > jb> original post, that (at least for MSW) would give the correct
jb> > jb> result rather than simply returning true.
jb> >
jb> > Yes, I guess this would indeed be an improvement. Would you be
jb> > interested in making a PR with this change?
jb> >
jb> > Ideal would be to also add a test (even if a MSW-only one) as
jb> > currently we don't test this function at all...
jb> >
jb> Yes, if you point me in the right direction, I'll see what I can do.

The change in the code should be straightforward enough, but please let
me know if you have any questions. As for the tests, this could go into the
existing tests/window/setsize.cpp file, I think, which would need to be
extended with a test case for this.

Please also see https://www.wxwidgets.org/develop/how-to-submit-patches/
if you hadn't done this before and, again, please ask (here or on wx-dev)
if you have any questions.

TIA!

jon bird

unread,
Jan 15, 2023, 2:52:31 PM1/15/23
to wx-u...@googlegroups.com
On Fri, 13 Jan 2023 19:52:14 +0100
Vadim Zeitlin <va...@wxwidgets.org> wrote:

> On Fri, 13 Jan 2023 18:38:23 +0000 jon bird wrote:
>
[...]

> jb> >
> jb> Yes, if you point me in the right direction, I'll see what I can
> jb> do.
>
> The change in the code should be straightforward enough, but please
> let me know if you have any questions. As for the tests, this could
> go into the existing tests/window/setsize.cpp file, I think, which
> would need to be extended with a test case for this.
>
> Please also see
> https://www.wxwidgets.org/develop/how-to-submit-patches/ if you
> hadn't done this before and, again, please ask (here or on wx-dev) if
> you have any questions.
>
Excellent, thanks for that. Got a fair bit on right now so probably
won't be for a few weeks but I'll definitely have a go.
Reply all
Reply to author
Forward
0 new messages