I wonder, do we all get to that point where our own code, written days or weeks or months or maybe even years back, makes us ask the question, “How the fuck did I do that?”
Everything here refers to my RomyView application.
Take for instance, my conversion progress dialog. This is part of my video converter class library.
At design time, it looks like this:
But at run-time, it looks like this:
Ignoring the colours being different, which is part of my custom Themes implementation, the noticeable difference is that somehow my custom code that paints shadows for buttons and the panel ran, even in the forms designer, but not for the ComboBox. Why?
It turns out that along the way I created quite a complex forms inheritance hierarchy, and this dialog inherits from Romy.Controls.BaseDialog, which inherits from Romy.Controls.BaseForm. And my base form class implements a paint handler like so:
What that says is, for all derived forms that don’t set InheritedDrawShadows false, for all buttons, panels, thumbnails and property grids (excluding certain derived custom types that I especially created not to have shadows), and unless the control is an instance of my Thumbnail control using a specific optimization that allows a Thumbnail just to draw an Image and nothing else, draw the damn shadow. This code is the reason that certain shadows are drawn even in the designer.
And now I remember, I didn’t add ComboBoxes to that code because I might not always want them to have shadows. In fact, usually they shouldn’t have. But I added an OnPaint handler to the progress dialog for that one.
OK. Now it makes sense. It also explains why the dialog below, part of my image filters dialogs class library in the solution, looks the same at design time and run-time:
But that doesn’t explain what happened here… This dialog, also part of the same class library, doesn’t do any of my drawing at design time:
But at run-time, it’s behaving as it should be:
Actually, this reveals a limitation of my base class paint handler. It can only paint shadows for certain types of controls that are dropped directly onto the form.
Oops. And how did I make it draw the shadows above? With this horrible hack:
While this code works, it is rather flimsy. Controls in different containers will not inherit the intended behaviour at all.
So what did I do wrong?
While the approach was heading in the right direction, my implementation is, well, backwards. Instead of trying to paint every type I could think of from the forms, and going as far as deriving specific types that should not inherit the intended behaviour, I should have created types specifically to inherit the intended behaviour. That is, create derived Buttons and so on that should always paint shadows, no matter what their containers might be. It would have involved less code, and been easier to read as well.
I hope that this might point out to somebody else who is heading down the wrong road (or heading up the right road instead of down) that they need to rethink their design. These things are easy to get wrong while you are coding in that zone deep in the code…
Note: Obviously Graphics.DrawShadow is an extension method and is irrelevant to the point of this article.