What is the best way to detect & store a listbox user setup?

I want to be able to detect a users preference for column widths and reflect that back next time the app is run. I want to keep the auto stretch facility provided by the * column width. Ideally I’d like a columnwidthchanged event, but can’t see that.

You can detect width changes in CellBackgroundPaint.

Have a look at CColumnResize at http://einhugur.com/Html/free3rd.html. It should be adaptable to a listbox with a bit of work.

Hi Wayne,

At save time, I store in the text file:

line 1: the Heading strings (Tab separated),
line 2: the ListBox.ColumnWidths string (as is at save time),
line 3: the ListBox background colours using the &h format I think)

then I store the ListBox contents.

At load time, I read the three first lines and store them in a variable,
Then I check how many Tab in the Heading String,
Set the ListBox number of Columns,
Set the Header Strings (in that order),
Store theColumnWidths string
And, at last store the Background colors in the two global properties used for that.

Nota: I save the Background colors in a Prefs files (for default values)



In all my applications I use a small SQlite database to save and restore user preferences such as window positions and sizes, language, etc. This info is saved during the close events for each window and the application itself, where appropriate, and read in during the open event. I keep the database in SpecialFolder.ApplicationData so that each user can keep his or her preferences separately.

The Columnwidths string doesn’t seem to get updated by a user resizing the headers… it seems to return what was set up at design time.

I’m currently trying to work around this now, as when trying the ‘table to pdf’ example supplied for DynaPDFMBS
it gets many things ‘wrong’

Tim’s suggestion is the best one. This displays each column size in the first row, updated real time :

Function CellBackgroundPaint(g As Graphics, row As Integer, column As Integer) As Boolean me.cell(0,column) = str(g.width) End Function

Just set properties to use these values out of the event. An integer array seeming most appropriate.

I had to trim down my CellBackgroundPaint code in order to make a listbox more responsive and more smoothly scrolling.

Therefor I decided to add a timer, which I start in the MouseDown event handler of the listbox, when it occurs in the header area (y < Me.HeaderHeight). I stop the timer in the listbox’s MouseExit.

I save the current ColumnWidths in a property and in the timer’s action event handler I compare and save a changed value.

Like this I can save and restore the user’s preferred ColumnWidths without overloading my CellBackgroundPaint handler (which I still need for other stuff)

Another way to do it is to run special code only when both row and column are zero.

But I’d only collect and compare column widths there, having set them in Open first.

Et ceterum censeo: There should be a ColumnResized event handler to be added to listbox …

Thank you all for your assistance. I’ll continue playing & see what I can sort out.

You can get the actual width of any of the columns in the listbox using

ColWidth1 = Listbox1.Column(x).WidthActual

If you do this for all of the columns, you could save the values and restore to the same columnwidths when the program reopens.

If your concern is only saving and restoring the values, then use ColumnWidthActual and track which columns are “*” vs fixed width. If you need the information in real time, then CellBackgroundPaint will allow you to react to resizing as it happens.

Note that the sum of the column(n).widthactual values will not equal the width of the listbox control.
And if the headers have been manually resized, the columnwidths string won’t match what you see.

What about Auto saving the information when the window is closed or deactivated, or on a timed basis?

That’s true. There is no guarantee that all of the columns are even being displayed in the visual part of the listbox. That’s why listboxes can have horizontal scroll bars. The listbox may have a display width of, say, 600 with 10 columns each 100 units wide. In this case, you’d still want to save all of the column widths for the later restart.

I do not have that. In fact, when I ask something like

MyColWidth = LB.ColumnWidths

I can (most of the time I) get decimal values (yes, 44.12 for example !) when I define integer values.


care to explain why you store these data in a DB file instead in a simple text file (1 kind of property a line) ?

My problem is not so much finding the column widths, but determining which columns should be dynamically set after the user resizes a column. It seems that as soon as a user sets a column width all column widths are set in stone. Resizing the window with the listbox locked right & left no longer works well.

Listbox.ColumnWidths seems to result in an algorithm where the most narrow column has 1* and all the other columns have a multiplier of this. All column(x).widthactuals change and I haven’t reliably worked out how to determine which column has been resized.

Let me dig in my code. As far as I remember I had to fiddle around with this.