How often have you wanted to display some information that's tabular in nature in a program, and found your choices limited by the available Windows controls? There's the lowly listbox, which is limited to a single column per row. Then there's the more advanced List View, which allows multiple columns but is a horrendous pain in the ass to program.
The answer to the above might be "not very often" or even "never", but supposing it only came up even only once or twice: wouldn't it be nice if there was another choice of control here?
Well, NoC Laboratories, GmbH is pleased to announce the release of our mcLB2 control ("mick-ell-bee"--it's Scottish). It's a multi-column listbox that's easy to program and very flexible.
Here's a sample, using default fonts but custom colors
mcLB1.jpg:
Complete source and a testbed program attached below.
mcLB2 is a display-only control: all interaction with it is through the programming interface (all via SendMessage()). You set the number of columns and then can add and delete rows and set the text for each column in each row. You can select column headers. You have control over the formatting of all elements: the fonts used for each column, the font for the header, the text and background colors for the header and for each column. (This is all set at control creation time and can't be changed dynamically thereafter.)
Here's another sample, with a custom font for the center column:
mcLB2.jpg
Please play around with this, maybe use it in a program of your own, and let me know what you think. It's pretty much finished, but I'm open to suggestions. As I said, it's display-only, and I don't think I see it becoming a responsive control where you can select items by clicking on them. That could be done, and is already incorporated in mcLB2's predecessor, mcLB, which is a horizontal multi-column listbox that allows selection.
It's really intended for tabular info display. And the display can be updated dynamically at any time.
(To use it, just link mcLB2.obj with your code. Be sure to include mcLB2.inc in your code. And you'll need to call InitmcLB2() before creating a control with CreateWindowEx().)
I remember over 20 years ago using ListBox style LBS_USETABSTOPS with message LB_SETTABSTOPS for columns.
A few queries about the include file
mcLB2_COLINFO STRUCT
colWidth DD ?
colFontPtr DD ?
colBgColor DD ? ;-1 for default.
colTextColor DD ? ; " " "
colAlign DD ?
hdrTextPtr DD ?
mcLB2_COLINFO ENDS
colFontPtr is this a pointer to a LOGFONT? Or a HFONT?
colBgColor and colTextColor are these RGB? Or HBRUSHes?
And a petty one, to fit in with the naming style InitmcLB2 should be mcLB2_Init
Is it based on a standard ListBox? I remember they used to have a 32K item limit...
Quote from: sinsi on May 19, 2025, 02:11:52 PMA few queries about the include file
mcLB2_COLINFO STRUCT
colWidth DD ?
colFontPtr DD ?
colBgColor DD ? ;-1 for default.
colTextColor DD ? ; " " "
colAlign DD ?
hdrTextPtr DD ?
mcLB2_COLINFO ENDS
colFontPtr is this a pointer to a LOGFONT? Or a HFONT?
Handle to a font.
QuotecolBgColor and colTextColor are these RGB? Or HBRUSHes?
RGB colors.
QuoteAnd a petty one, to fit in with the naming style InitmcLB2 should be mcLB2_Init
You're probably right. Whether it'll get changed is anybody's guess ...
QuoteIs it based on a standard ListBox? I remember they used to have a 32K item limit...
Nope. Completely hand-rolled. No item limit that I know of, as I'm doing dynamic memory allocation (you can check the source to see how this works).
Quote from: TimoVJL on May 19, 2025, 01:47:26 PMI remember over 20 years ago using ListBox style LBS_USETABSTOPS with message LB_SETTABSTOPS for columns.
Yeah, you can kinda-sorta make a regular listbox multicolumn. But mine is the real deal.
OK, tried a thrash test by clicking Populate Control over and over until something broke...
First, all OK, then maybe 20 or so clicks later rows were added with no text, later (another 20 clicks?) the column headers' text disappeared, eventually
(5640.62e0): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=00000000 ecx=00000000 edx=000d0000 esi=11011220 edi=0060e9c0
eip=76c7a06e esp=004ff1f8 ebp=004ff29c iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010246
gdi32full!ScriptStringAnalyse+0x61e:
76c7a06e 0fb783a0000000 movzx eax,word ptr [ebx+0A0h] ds:002b:000000a0=????
Thanks for the stress test. Ugh, now I need to do some debugging.
I'm guessing maybe a memory-allocation problem, but it also might just be some kind of boundary condition.
There's one problem here
; Biggerize the heap:
INVOKE HeapReAlloc, _HeapHandle, HEAP_REALLOC_IN_PLACE_ONLY,
[EBX].$mcs2.itemHeapBase, $itemAllocSize
ADD [EBX].$mcs2.itemHeapAvail, $itemAllocSize
Forgot to do the addition for the new size of the block in HeapReAlloc, so it doesn't ever make the block bigger.
You should also probably check that it succeeds, realloc_in_place will only get so big before the block needs to be moved to expand.
The TextHeap realloc has that failure check which is probably why the text stops appearing after so many lines, the in_place HeapRealloc fails and thus _Text2Heap returns null pointers from then on.
Storing offsets to things in these heaps rather than direct pointers would remove neccesity of IN_PLACE since then it won't matter where the block is, the offset will remain the same,
Quote from: adeyblue on May 20, 2025, 06:35:22 AMThere's one problem here
; Biggerize the heap:
INVOKE HeapReAlloc, _HeapHandle, HEAP_REALLOC_IN_PLACE_ONLY,
[EBX].$mcs2.itemHeapBase, $itemAllocSize
ADD [EBX].$mcs2.itemHeapAvail, $itemAllocSize
Forgot to do the addition for the new size of the block in HeapReAlloc, so it doesn't ever make the block bigger.
Duh. Brain fart there: was thinking that the reallocation would increase the total allocation by that amount. (It don't work that way.) Thanks.