Create a shaped control.

One thing that a lot of VB Classic programmers tend to miss is the ability to create a Transparent control by simply setting a MaskColor. Well True Transparency cannot be achieved in vb.net. (OK, so you can set the WS_TRANSPARENT flag in CreateParams, but there's a major bug with zOrder, so I am discounting that option.)
You can create a control with ControlStyles.SupportsTransparentBackColor set to True and ControlStyles.Opaque set to False and this will cause the Background to be painted by the controls parent. The problem here is that you cannot see the control beneath the Transparent area of your control.
The alternative is to set a region for the control. The code below is a base for a shaped control. Just set a BackgroundImage and a MaskColor and the control will shape itself.

23 May 2005 - Updated

If any of you have used this example before, you will have noticed that it did not handle complex shapes too well.
A little digging around showed me that the reason for this was that there is a limit to how many rectangles can be added to a region before a stackoverflow exception is raised. I played around a little and found that the same problem did not occur when adding rectangles to a graphics path, but updating the graphicspath whilst iterating through the image pixels turned out to be very slow.
I scratched my head for a little while and decided that I could easily create a rectangle of two or more adjoining rectangles within a row, but that joining rectangles of similar size and location between rows was a little more complex.
To help me to decide on a solution I opened up MSPaint and created the image to the left. With this image the solution seemed very simple. All I needed to do was reference the base of a rectangle and then when completing a rectangle I could easily check if the rectangle fitted in the bottom row of a rectangle immediately above it.
Now you can see that in this simple 8x2 pixel image, with red representing the MaskColor, the original method added 10 rectangles. This was cut down to 4 rectangles by simply combining pixels within a row, and then further reduced to 3 rectangles when combining rectangles in adjoining rows.
Whilst I was updating I also added an AutoMask property which, if set to True, will automatically set the MaskColor to the color of the bottom-left pixel.

Now using this method it is possible to further improve the control by serializing the ArrayList of rectangles and do away with the need to iterate through the image before assigning a region. This will result in improved load time, and I am leaving that as a project for you.
Of course, there is no reason that you could not apply exactly the same method to a form.

  • VB Code
  • C# Code

Create a PanelManager.

I see and hear requests to remove the tabs from the tabcontrol so often that I decided to create a simple Tabless TabControl.
Select a ManagedPanel at design time and you will see a DesignerVerb which allows you to select the PanelManager Control.
You can then change the selected panel via the property browser, so once you're used to using it, designtime is no problem at all.

  • VB Code
  • C# Code

Note: You'll need to add a reference to System.Design.dll.


Create a simple rounded Panel.

When we Draw to a Graphics object we can set AntiAlias so as to make the edges of complex shapes look smooth. This is done by altering the color of some of the pixels on and around the edge so that the jagged edges appear smooth. When we create a region from a complex shape though, the recoloured pixels outside of the region are lost and as there is no way to trim the edges of the pixels (they are always square) our regions appear jagged. A simple solution to this is to put a pseudo transparent 1 pixel border around the control when shaping it. I doubt very much that you will notice this border, but it will greatly improve the appearance of the edges of your shaped control.
Because the Control in this example has rounded edges, it is not suitable for the AutoScrol property as the ScrollBars will be Clipped. For this reason the Control Inherits from Control and because we want to use it as a Container we have assigned the ParentControlDesigner to the Class.

  • VB Code
  • C# Code