Introduction
If you have ever used Application.EnableVisualSyles
and a TabControl
you must have noticed that Microsoft has left out theme support for the TabPage
s. It is well known to get around this problem while using a UXTheme wrapper to draw the theme background onto the TabPage
. However, one day I went to place a GroupBox
control onto a UXThemed TabControl
and then I noticed that the GroupBox
did not fully take up the application's visual theme either, and it wasn't as easy to fix as with the TabPage
.
While searching the internet I found some C# code on a .NET newsgroup and converted it to VB, however there were a few overflows which occurred and when adding controls onto the GroupBox
they had a solid black background, took parts of the background from other parts of the screen or created a giant hole in the application and you were able to see the desktop.
A big Thank You goes to Ying-Shen Yu for posting the original code in C#.
Using the code
The control first overrides the BackColor
property to allow a transparent background to be set for the GroupBox
. This is required for the Label
on the top of the GroupBox
. Secondly, we catch the Windows message for WM_PAINTBKGRD
and replace it with our custom drawing code. Finally, we override the OnPaint
methods so that the child controls draw properly inside the GroupBox
.
Namespace Controls
Public Class GroupBox
Inherits System.Windows.Forms.GroupBox
Public Overrides Property BackColor() As Color
Get
Return MyBase.BackColor
End Get
Set(ByVal Value As Color)
MyBase.SetStyle(ControlStyles.SupportsTransparentBackColor, True)
MyBase.SetStyle(ControlStyles.UserPaint, True)
MyBase.BackColor = Value
End Set
End Property
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If (m.Msg = 20) And (Me.FlatStyle = FlatStyle.System) Then
MyBase.SetStyle(ControlStyles.SupportsTransparentBackColor, True)
MyBase.SetStyle(ControlStyles.UserPaint, True)
Dim g As Graphics = Graphics.FromHdcInternal(m.WParam)
OnPaintBackground(New PaintEventArgs(g, New Rectangle(0, 0, _
Width, Height)))
g.Dispose()
MyBase.SetStyle(ControlStyles.SupportsTransparentBackColor, False)
MyBase.SetStyle(ControlStyles.UserPaint, False)
Exit Sub
End If
MyBase.WndProc(m)
End Sub
Protected Overrides Sub OnPaintBackground(ByVal pevent _
As System.Windows.Forms.PaintEventArgs)
System.Windows.Forms.Themes.UxTheme.DrawThemeParentBackground(Me, _
pevent.Graphics, pevent.ClipRectangle)
End Sub
Protected Overrides Sub OnPaint(ByVal e As _
System.Windows.Forms.PaintEventArgs)
System.Windows.Forms.Themes.UxTheme.DrawThemeParentBackground(Me, _
e.Graphics, New Rectangle(0, 0, e.ClipRectangle.Width, _
e.ClipRectangle.Height))
End Sub
End Class
End Namespace
Using the control is no different from using a normal GroupBox
control (in fact, this control inherits the GroupBox
control and overrides some of the functions).
Dim oGroupBox as New Controls.GroupBox
oGroupBox.Text = "Test Group"
Dim oLabel As New System.Windows.Forms.Label
oLabel.Text = "Test Label"
oLabel.BackColor = Color.Transparent
oLabel.Location = New Point(5, 5)
oLabel.AutoSize = True
oGroupBox.Controls.Add(oLabel)
Points of interest
I had a rather strange experience getting the child controls to draw the backgrounds properly, I had random results ranging from an almost transparent application, to half the controls drawing properly. This was fixed by overriding the OnPaint
method of the GroupBox
and replacing it with the UXTheme
drawing routine.
If you look up Graphics.FromHdcInternal
on MSDN, it says "Do Not Use!" Oops :)
History
- 14th December 2004 - Initial version.