The new vbAccelerator Site - more VB and .NET Code and Controls
Source Code
3 Code Libraries &nbsp
&nbsp

Find and Fixing a Bug in SSUBTMR

Basic - You Shoot Yourself In The Foot, but it takes so long for the bullet to reach your foot that you forget why you started in the first place.

"The introduction of the AddressOf operator to VB5 allows you to subclass, although it is not nearly as simple as it ought to be. The SSUBTMR.DLL component is a stable and consistent way of working around difficulties in subclassing."

That's how SSUBTMR.DLL is introduced on the site. It holds true now as it did then, except in the first release there was a bug in it just waiting to happen, and I was the lucky person to make it happen with the new vbAccelerator Toolbar and Rebar controls (Or maybe you were? I can't apologise enough. Send your rant!).

I can't start without thanking Jim Parzych for pointing out the problem. Also, I should note that although this component was based on SUBTMR.DLL designed by Bruce McKinney, author of Hardcore Visual Basic the bug is all my own fault (although coincidentally I found and fixed a bug in the original. What goes around...)

The problem
When multiple controls subclassed the same message on the same window, the SSUBTMR code didn't check if it had already called the default window procedure for the message.

As a Consequence...
Consider the case of the vbAccelerator Rebar/Toolbar control in a form, where there is one Rebar control and one Toolbar. Both the toolbar and rebar control must subclass the WM_NOTIFY message, and this message is sent to the parent of the control.

The rebar has to capture WM_NOTIFY to detemine if its height has changed, and the toolbar captures it to determine whether buttons or dropdowns have been clicked. Everything works fine so far because the Rebar and Toolbar are both implemented within the same OCX, and therefore share the same version of the subclasser. But it starts to go pear-shaped when you add another external common control to the form with the Rebar and Toolbar on.

All the common controls use WM_NOTIFY messaging to the parent form. So when you do anything to a common control which raises an event (for example, clicking on a item in a ListView) a WM_NOTIFY is sent. Both the toolbar and rebar intercept this message.

So consider the case when a form contains a rebar, a toolbar and a COMCTL32.OCX ListView. Note that the rebar/toolbar requires that the toolbar's subclass is set up first and the rebar second. This is what happens when you cause an event in the ListView:

  • Clicking a ListView causes the ListView to raise a WM_NOTIFY message. This is sent to the Parent of the ListView, which is the form the ListView is located on (note it is irrelevant whether the Container of the ListView is another control, because the Parent is always going to evaluate to the form).
  • The subclasser intercepts the message because the toolbar and rebar also need to check WM_NOTIFY messages sent to the parent form. It (correctly) identifies that the message wants to be sent firstly to the toolbar and then to the rebar.
  • The subclasser calls the default window procedure (correct) and then passes the message to the toolbar (correct). Note that the toolbar ignores this message because it determines from the NMHDR structure associated with all WM_NOTIFY messages that the message is not associated with its own hWnd. This is also correct.
  • Then the subclasser calls the default window procedure again (WRONG,WRONG, WRONG!!!!!) before passing the message to the rebar correctly. Again, the rebar ignores the message as the message is sent from a different hWnd to the rebar.
So if you do anything to a Common Control (ListView, TreeView, Progress Bar, UpDown, Slider, Tab, Pager, Animation...) the event will apparently occur twice. This gets even worse if you add a second toolbar to the rebar - the events occur three times... As you can have an unlimited number of toolbars the problem clearly can't be worked around in any sensible way in code because the number of events you get is the number of rebars (always 1) plus the number of toolbars (0 to n where n is only really restricted by screen space. Word 8 is very nice, but are we sure we need 14+ toolbars?).

The Solution
The solution is obvious, although of course solutions always are once you know what the problem is. I now cannot believe it was not implemented from the start and feel someone should take me to a dark room and proceed to beat me vigorously with a printed copy of the MSDN documentation on subclassing. But that is enough already about my personal problems and predilictions.

It is implemented by a setting a boolean flag in the subclass procedure to determine whether the default window procedure has been called already and then NOT CALLING IT AGAIN...

So Why Hasn't This Been a Problem Yet?
The thing is, SSUBTMR.DLL is a production component and I have distributed it in many live applications (I don't just distribute any old thing on this site, honest, and if you'd seen the code in the components alluded to in some of the 'coming soon' notes of the Source Code sections you would know exactly why!). There haven't been any problems in over a year of operation (that's not entirely true, but anything that has gone wrong hasn't been caused by the DLLs or controls...)

Anyway, the reason is actually that whilst SSUBTMR allowed multiple messages on the same window to be subclassed, whenever this occurred in a real life application of my controls, SSUBTMR.DLL always ran in the same process space as the DLL doing the subclassing. And because in-process DLLs and OCXs share the same module, the problem never arose. And of course, when I designed the Rebar/Toolbar control, my idea was to do away with COMCTL32.OCX forever if you could do without it - so I never tested it with a ListView. How stupid am I?

Get the Fix
SSUBTMR is a binary compatible component so the new version will run without problems with any controls you've downloaded before. The new version is available for download at Subclassing without the crashes.

Back to top

Back to Source Code Overview





This document was put together whilst listening to the following CDs:
  • Aluminium Tunes: Switched on Volume 3 by Sterelab (Duophonic LP, 1998)
    Stereolab's third collection of rare/previously unreleased songs.
  • Kill At Will by Ice Cube. (4th and Broadway EP, 1990)
    I can't find it in myself to dislike this record.
  • Surfer Rosa by The Pixies (4AD LP, 1984)
    A band at the height of its powers.
  • On by Aphex Twin (Warp 12, 1993)
    I finally found this amongst a set of PC magazine cover CDs. How sad is that? The drum beats on this record are created from distorted sine-waves and hitting metal objects, thus fulfiling my number one criteria for creating good music.
  • Space Invaders are Smoking Grass by I-F (Interdimensional Transmissions 12, 1997)
    Complete and utter rubbish. I like it a lot.
&nbsp

AboutContributeSend FeedbackPrivacy

Copyright 1998-1999, Steve McMahon ( steve@vbaccelerator.com). All Rights Reserved.
Last updated: 14 October 1998