Privacy Policy

Best viewed with:
Mick Dohertys' .net Tips and Tricks - Tips / Custom Controls
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 (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

Create a Custom Slider Control.

All too often I see examples of custom controls which unnecessarily add child controls. For instance, a custom trackbar control may have a label or panel added to act as the scrolling thumb tab. In this instance that's not so bad as it only creates one extra window handle, but where several such child controls are added the user will see what is percieved as flicker as each window is individually painted one after the other. No amount of doublebuffering will cure this.

Since we need to respond to mouse, keyboard or code change events and then calculate the exact bounds of the child control, it really makes no sense to add the extra control. We may as well apply those bounds to a rectangle instead, and then paint within this rectangle (don't have to paint a Rectangle just need to paint inside it).

The following example shows how to define and use a rectangle for this purpose. I have tried to make it behave just like a standard System.Windows.Forms.Trackbar control, but have made no offort to have it look like one. Hopefully, you'll be able to apply the same principles to other custom controls, perhaps using some of the many control renderers to simulate "lite" controls.

  • VB Code
  • C# Code

I'll leave you the task of making it look pretty.

Create a Control with Non Client Area

The following code defines the base code for painting a true non client area in a custom control. It paints the sizegrip rectangle in the correct place when both scrollbars are visible. You should Inherit this control and override the OnPaintNonClient method to draw the border as you wish. Your users can also use the PaintNonClient method to do some additional custom painting. For simplicity, this class does not include Non Client Mouse interactions, but this will be demonstrated in the next example which inherits from this class.

  • VB Code
  • C# Code

Adding Non Client Mouse Events to Non Client Control

The following class inherits from the one in the article above and adds NonClientMouse Events.

  • VB Code
  • C# Code