How do I put something in front of an image? - vb.net

Using VB.net VS2010 and Winforms, I am simply trying to add both a picturebox and a label to a panel, but the label will not go in front of the picture box. How can I set the label as the foremost object? Using the code below, the label always ends up behind the picturebox.
Public Class MyTab
Inherits System.Windows.Forms.Panel
Public myText As New Label
Public tab_top_left as New Picturebox
Public Sub New(ByVal tab_object As tab_properties_object)
With tab_top_left
.BackgroundImage = My.Resources.tab_top_left
.Parent = Me
.Location = New Point(0, 0)
.SendToBack()
.Width = 20
.Height = 19
.Name = "tab_top_left"
End With
Dim TextString As String = tab_object.top_tab_text
myText.Font = CustomFont.GetInstance(Main.main_font_size_up3, FontStyle.Regular)
myText.ForeColor = Color.FromArgb(255, 0, 0, 0)
myText.BackColor = Color.FromArgb(255, 204, 204, 204)
myText.Text = TextString
myText.Location = New Point(0, 0)
myText.Width = 200
myText.Height = 40
myText.UseCompatibleTextRendering = True
myText.BorderStyle = BorderStyle.None
myText.Name = "tab_" & myText.Text
myText.Parent = Me
myText.BringToFront()
Me.Width = myText.Left + textSize.Width + 15
Me.Height = 40
Me.Name = "_" & TextString
Me.Location = New Point(0, 0)
End Sub
End Class

Related

Access added (sub) control in VB .NET

With this code I dynamicly add a panel with two panels inside (a header and a data panel). Within the Data panel there is also a label that I like to access.
Now I like to access the label inside the data panel but can't reach it with:
test_label.text = "this a second test"
Here the dynamicaly added panels
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim newPanelMain As Panel = New Panel With {
.Location = New Point(200, 500),
.Name = "test",
.Size = New Size(500, 500)
}
Dim newPanelHeader As Panel = New Panel With {
.Name = newPanelMain.Name & "_header",
.BackColor = Color.Orange,
.Dock = DockStyle.Top,
.Height = 50
}
newPanelMain.Controls.Add(newPanelHeader)
Dim newPanelData As Panel = New Panel With {
.Name = newPanelMain.Name & "_data",
.Dock = DockStyle.Fill,
.BorderStyle = BorderStyle.FixedSingle
}
newPanelMain.Controls.Add(newPanelData)
Dim newPanelSize As Panel = New Panel With {
.Name = newPanelMain.Name & (("_size")),
.BackColor = Color.Red,
.Height = 20,
.Width = 20,
.Location = New Point(newPanelData.Width - 20, newPanelData.Height - 20)
}
newPanelData.Controls.Add(newPanelSize)
Dim newLabel As Label = New Label With {
.Text = "This is a test",
.Name = newPanelMain.Name & (("_label")),
.Location = New Point(0, 0),
.AutoSize = True
}
newPanelData.Controls.Add(newLabel)
Me.Controls.Add(newPanelMain)
End Sub
Declare newLabel as a member variable:
Private newLabel As Label
So you can use this code:
Me.newLabel = New Label With {
.Text = "This is a test",
.Name = newPanelMain.Name & (("_label")),
.Location = New Point(0, newPanelHeader.Height + 10),
.AutoSize = True
}
newPanelData.Controls.Add(Me.newLabel)
And then change its .Text property using:
Me.newLabel.Text = "this a second test"
In a different situation (e.g. if you have multiple Labels created at runtime) remember that you can use Control.ControlCollection class:
CType(CType(Me.Controls("test"), Panel).Controls("test_data"), Panel).Controls("test_label").Text = "this is a third test"

Swap positions between three Panels

I have three panel type objects (A, B, and C), which have been dynamically generated within another panel type control.
My question is, how can I exchange panel B to the position of panel A and panel A to the position of panel B? This will be triggered by a click on a ToolStripMenuItem.
What I had thought, was to go through the arrangement of panels to know who exists and from there to work them, is that correct?
For Each obj As Control In Panel1.Controls
MsgBox(obj.Name)
Next
This is the code that I use to move to right:
Private Sub ToolStripMenuItem1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripMenuItem1.Click
Dim clickedPanel = DirectCast(DirectCast(DirectCast(sender, ToolStripMenuItem).Owner, ContextMenuStrip).SourceControl, Panel)
clickedPanel.Location = New Point((clickedPanel.Location.X + 120), clickedPanel.Location.Y)
End Sub
This is the code I use to generate objects dynamically:
Private Sub TileNavItem5_ElementClick(sender As Object, e As NavElementEventArgs) Handles TileNavItem5.ElementClick
Dim pos As Int32 = cInt(TextBox38.Text)
Dim poslabel As Int16 = cInt(TextBox42.Text)
Dim posY As Int16 = 330
Dim posX As Int16 = 3
Panel1.AutoScrollPosition = New Point(0, 0)
Dim pb As New Panel With
{
.Width = 120,
.Height = 460,
.Top = 10,
.Left = 10,
.BorderStyle = BorderStyle.FixedSingle,
.BackgroundImage = Image.FromFile("C:\example.bmp"),
.BackgroundImageLayout = ImageLayout.Stretch,
.ContextMenuStrip = CntxtMnuStrpSection,
.Name = "Panel" & Val(TextBox37.Text)
}
AddHandler pb.Click, AddressOf myClickHandler_b
Dim labela As New Label With {
.AutoSize = True,
.Location = New Point((poslabel), 12),
.Text = "Section " & CInt(TextBox37.Text),
.ForeColor = Color.White,
.BackColor = Color.Transparent,
.Font = New Font(Me.Font, FontStyle.Bold),
.Name = "Label" & CInt(TextBox37.Text)
}
pb.Location = New Point(0, 0)
pb.Location = New Point(pos, 20)
Panel1.Controls.Add(pb)
pb.Controls.Add(labela)
For j = 1 To 4
Dim pbdoors As New Panel With
{
.Width = 114,
.Height = 98,
.Top = 10,
.Left = 10,
.BorderStyle = BorderStyle.FixedSingle,
.BackgroundImageLayout = ImageLayout.Stretch,
.ContextMenuStrip = CntxtMnuStrpUnit,
.Name = "Unit" & Val(TextBox37.Text) & j
}
AddHandler pbdoors.Click, AddressOf myClickHandler_doors
pbdoors.Location = New Point(posX, posY)
pb.Controls.Add(pbdoors)
posY = (posY - 100)
Next
Panel1.AutoScrollPosition = New Point(Panel1.HorizontalScroll.Maximum, Panel1.VerticalScroll.Maximum)
TextBox37.Text = CInt(TextBox37.Text) + 1
TextBox38.Text = Val(TextBox38.Text) + 120
End Sub
You just need to find the controls. Swapping is the easy part.
Finding controls is also easy if you use Control.Controls.Find(String, Boolean). But you must at least know the control's name.
The difficulty comes in here
' TextBox37.Text = CInt(TextBox37.Text) + 1 ' implicit conversion from int to string
TextBox37.Text = (CInt(TextBox37.Text) + 1).ToString()
where you must find the control by name and you have built some integer into the name. Can you keep track of how many times 1 is added to TextBox37.Text?
If you can, you can pass it into this function, and the swapping will be performed
Private Sub swap(index1 As Integer, index2 As Integer)
' build the panel names
Dim p1Name = $"Panel{index1}"
Dim p2Name = $"Panel{index2}"
' find the panels
Dim p1 = DirectCast(Panel1.Controls.Find(p1Name, True).FirstOrDefault(), Panel)
If p1 Is Nothing Then Throw New ArgumentException("index1")
Dim p2 = DirectCast(Panel1.Controls.Find(p2Name, True).FirstOrDefault(), Panel)
If p2 Is Nothing Then Throw New ArgumentException("index2")
' swap the panels
Dim temp = p2.Location
p2.Location = p1.Location
p1.Location = temp
End Sub
swap(1, 2) will swap panel 1 with 2. swap(4, 6) will swap the panel 4 with 6. This logic is not included in your question (i.e. how many times is TileNavItem5_ElementClick called?), so you know better how to incorporate it. I hope it works for you.

Add an extra control to a button in VB.Net

I have a code that creates 30 buttons at run time on a form which works excellently
For i = 0 To 30
btn = New Button
Dim old As Padding = btn.Margin
Dim old2 As Padding = btn.Padding
btn.Tag = "X1"
btn.Name = "Drane"
btn.Text = "The power of trying"
btn.Width = 95
btn.Height = 120
btn.Margin = New Padding(10, 10, 10, 10)
btn.Padding = New Padding(0, 4, 0, 2)
btn.TextAlign = ContentAlignment.BottomCenter
btn.ImageAlign = ContentAlignment.TopCenter
btn.Font = New Font("Lucida Sans Unicode", 11)
btn.ForeColor = Color.Black
btn.BackColor = Color.White
Next i
Now I'm trying to add an extra control to hold the ids for buttons that I created at run time
btn.id = i
which would hold the ids of each particular button so I can get the value in other functions in my application. I know I have to add this somehow as a control but I just don't know how.
Please any help will be greatly appreciated in resolving this
This will extend the Button class and add an ID property.
Public Class ButtonMod
Inherits Button
Public Property ID As Integer
End Class
Then you just create them in a loop as you were doing already:
For i As Integer = 1 To 30
Dim btn As New ButtonMod
Dim old As Padding = btn.Margin
Dim old2 As Padding = btn.Padding
btn.Tag = "X1"
btn.Name = "Drane"
btn.Text = "The power of trying"
btn.Width = 95
btn.Height = 120
btn.Margin = New Padding(10, 10, 10, 10)
btn.Padding = New Padding(0, 4, 0, 2)
btn.TextAlign = ContentAlignment.BottomCenter
btn.ImageAlign = ContentAlignment.TopCenter
btn.Font = New Font("Lucida Sans Unicode", 11)
btn.ForeColor = Color.Black
btn.BackColor = Color.White
btn.ID = i
Next

Why do I need a function for this Visual Basic code?

I am trying to figure out the functions for an application that you order donuts and coffee through. There is no box to input quantities. The type of doughnuts are selected using radio buttons grouped in combo boxes as is the type of coffee. The user ordering does not input any information. That application calculates according to the selected radio buttons. There is also a 3% sales tax.
The donuts are as follows:
Glazed are $0.65, Sugar $0.65, Chocolate are $0.85, and Filled are $1.00.
The coffee costs:
Regular is $1.00 and cappuccino is $2.50.
How do I write a function for each one? I would think I would just write one function that calculates the donut, coffee and sales tax. I am not sure what I am supposed to include if there is only one possible choice for each case. I thought that I could just write a bunch of constants since nothing changed and do an If statement but the assignment is asking for functions.
This is what I have so far for the doughnuts.
Private Function GetDonutPrice(ByVal strDonut As String) As Double
Dim dblDonutPrice As Double
'Calculates and returns the price of donuts
If strDonut = "G" Or strDonut = "S" Then
dblDonutPrice = 0.65
ElseIf strDonut = "C" Then
dblDonutPrice = 0.85
Else
strDonut = "F"
dblDonutPrice = 1.0
End If
Return dblDonutPrice
End Function
And then for the btnCalc_Click I coded this:
Private Sub btnCalc_Click(sender As Object, e As EventArgs)
'Displays donut and cappucino subtotal, taxes and price
Dim strDonutPrice As String
Dim dblDonutPrice As Double
If radGlazed.Checked Then
strDonutPrice = "G"
ElseIf radSugar.Checked Then
strDonutPrice = "S"
ElseIf radChoc.Checked Then
strDonutPrice = "C"
ElseIf radFilled.Checked strDonutPrice = "F"
End If
' get the donut price '
dblDonutPrice = GetDonutPrice(strDonutPrice)
End Sub
And I get an error in dblDonutPrice = GetDonutPrice(strDonutPrice)
It sounds like you need a function that receives the type and quantity of doughnuts and does the math and returns the cost. And the same for the coffee. So you will have three functions total. The coffee, the doughnuts, and the main one that take the input of what is order and how many, calls the other functions, adds it up, and then does the sales tax
Something like this maybe.
Private Sub cmdAddItUp_Click(sender As System.Object, e As System.EventArgs) Handles cmdAddItUp.Click
Dim iQuantity1 as integer
Dim dDoughnutCost as double
'Get the data to send to doughnuts
iQuantity1 = val(TextBox1.Text)
iQuantity2 = val(TextBox2.Text)
etc.
'Get the doughnuts cost
dDoughnutCost = Doughtnuts(iQuantity1, iQuantity2, iQuantity3)
'Do the same for the coffee
dCoffeeCost = Coffees(iQuantity1, iQuantity2, iQuantity3)
'Add it up
dSubTotal = dDoughnutCost + dCoffeeCost
'Calculate tax
dTotal = Tax(dSubTotal)
'Now you have the total, do something with it. Display it maybe!
End Sub
Private Function Doughtnuts(iQuantity1 As Integer, iQuantity2 As Integer, iQuantity3 As Integer) As Double
'Do the math
End Function
Private Function Coffees(iQuantity1 As Integer, iQuantity2 As Integer, iQuantity3 As Integer) As Double
'Do the math
End Function
Private Function Tax(dSubtotal As Double) As Double
'Calculate tax
End Function
Hope that helps get you started. Good luck with your schooling.
I made some assumptions on your UI. Rather than placing the items as radio buttons in a ComboBox, I placed all of the doughnuts and coffees into a respective GroupBox. The concepts of this answer will still apply, however you'll just have to be mindful that this is not directly drop-in and go.
Here's the way I laid out the UI:
I have placed the RadioButtons for the items inside a FlowLayoutPanel inside of a GroupBox. I also placed labels into a TableLayoutPanel to provide the total amounts.
The most important part is how I named the RadioButton controls for the items being listed. In the code behind file I used the names of the RadioButton controls to check which Item was being modified. I could have populated the RadioButton controls at run time to ensure that everything lined up, but that was more work and it's not difficult to do if you use GetType(MyEnum).GetNames() in the Me.Load event of the form to create new RadioButtons with the correct name, text, and adding the proper event handlers to the radio buttons.
If you'd like to see how this works, add a new form to your Project and call it DoughnutsAndCoffee. Here is the designer file and the Code behind:
Code Behind:
Public Class DoughnutsAndCoffee
Private SelectedItems As New List(Of Items)
Public Event ItemsChanged()
Public Sub UpdateTotal() Handles Me.ItemsChanged
Dim subTotal As Decimal = 0D
For Each item As Items In SelectedItems
subTotal += Prices.GetPrice(item)
Next
Dim TaxTotal As Decimal = subTotal * Prices.Tax_Rate
Dim total As Decimal = subTotal + TaxTotal
Me.SubTotal_Label.Invoke(Sub() Me.SubTotal_Label.Text = subTotal.ToString("C2"))
Me.Tax_Label.Invoke(Sub() Me.Tax_Label.Text = TaxTotal.ToString("C2"))
Me.Total_Label.Invoke(Sub() Me.Total_Label.Text = total.ToString("C2"))
End Sub
Private Sub RadioButton_CheckedChanged(sender As Object, e As EventArgs) Handles Cappuccino_RadioButton.CheckedChanged, Chocolate_RadioButton.CheckedChanged, Filled_RadioButton.CheckedChanged, Glazed_RadioButton.CheckedChanged, Regular_RadioButton.CheckedChanged, Sugar_RadioButton.CheckedChanged
Dim senderRB As RadioButton = DirectCast(sender, RadioButton)
Dim selectedItem As String = (From item As String In GetType(Items).GetEnumNames Where senderRB.Name.Contains(item) Select item).FirstOrDefault
If selectedItem <> String.Empty Then
Dim Item As Items = DirectCast([Enum].Parse(GetType(Items), selectedItem), Items)
If senderRB.Checked Then
Me.SelectedItems.Add(Item)
RaiseEvent ItemsChanged()
Else
If Me.SelectedItems.Contains(Item) Then
Me.SelectedItems.Remove(Item)
RaiseEvent ItemsChanged()
End If
End If
End If
End Sub
Private Sub DoughnutsAndCoffee_Shown(sender As Object, e As EventArgs) Handles Me.Shown
RaiseEvent ItemsChanged()
End Sub
End Class
Public Structure Prices
Public Const Tax_Rate As Decimal = 0.03D
Public Const Glazed As Decimal = 0.65D
Public Const Sugar As Decimal = 0.65D
Public Const Chocolate As Decimal = 0.85D
Public Const Filled As Decimal = 1D
Public Const Regular As Decimal = 1D
Public Const Cappuccino As Decimal = 2.5D
Public Shared Function GetPrice(item As Items) As Decimal
Dim itemStr As String = [Enum].GetName(GetType(Items), item)
Return GetType(Prices).GetField(itemStr).GetValue(Nothing)
End Function
End Structure
Public Enum Items
Glazed
Sugar
Chocolate
Filled
Regular
Cappuccino
End Enum
Designer File:
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class DoughnutsAndCoffee
Inherits System.Windows.Forms.Form
'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.Glazed_RadioButton = New System.Windows.Forms.RadioButton()
Me.Sugar_RadioButton = New System.Windows.Forms.RadioButton()
Me.Chocolate_RadioButton = New System.Windows.Forms.RadioButton()
Me.Filled_RadioButton = New System.Windows.Forms.RadioButton()
Me.Regular_RadioButton = New System.Windows.Forms.RadioButton()
Me.Cappuccino_RadioButton = New System.Windows.Forms.RadioButton()
Me.TableLayoutPanel1 = New System.Windows.Forms.TableLayoutPanel()
Me.Total_Label = New System.Windows.Forms.Label()
Me.Label5 = New System.Windows.Forms.Label()
Me.Tax_Label = New System.Windows.Forms.Label()
Me.Label3 = New System.Windows.Forms.Label()
Me.SubTotal_Label = New System.Windows.Forms.Label()
Me.Label1 = New System.Windows.Forms.Label()
Me.FlowLayoutPanel2 = New System.Windows.Forms.FlowLayoutPanel()
Me.FlowLayoutPanel1 = New System.Windows.Forms.FlowLayoutPanel()
Me.Coffee_GroupBox = New System.Windows.Forms.GroupBox()
Me.Doughnuts_GroupBox = New System.Windows.Forms.GroupBox()
Me.TableLayoutPanel1.SuspendLayout()
Me.FlowLayoutPanel2.SuspendLayout()
Me.FlowLayoutPanel1.SuspendLayout()
Me.Coffee_GroupBox.SuspendLayout()
Me.Doughnuts_GroupBox.SuspendLayout()
Me.SuspendLayout()
'
'Glazed_RadioButton
'
Me.Glazed_RadioButton.AutoSize = True
Me.Glazed_RadioButton.Location = New System.Drawing.Point(3, 3)
Me.Glazed_RadioButton.Name = "Glazed_RadioButton"
Me.Glazed_RadioButton.Size = New System.Drawing.Size(58, 17)
Me.Glazed_RadioButton.TabIndex = 9
Me.Glazed_RadioButton.Text = "Glazed"
Me.Glazed_RadioButton.UseVisualStyleBackColor = True
'
'Sugar_RadioButton
'
Me.Sugar_RadioButton.AutoSize = True
Me.Sugar_RadioButton.Location = New System.Drawing.Point(3, 26)
Me.Sugar_RadioButton.Name = "Sugar_RadioButton"
Me.Sugar_RadioButton.Size = New System.Drawing.Size(53, 17)
Me.Sugar_RadioButton.TabIndex = 10
Me.Sugar_RadioButton.Text = "Sugar"
Me.Sugar_RadioButton.UseVisualStyleBackColor = True
'
'Chocolate_RadioButton
'
Me.Chocolate_RadioButton.AutoSize = True
Me.Chocolate_RadioButton.Location = New System.Drawing.Point(3, 49)
Me.Chocolate_RadioButton.Name = "Chocolate_RadioButton"
Me.Chocolate_RadioButton.Size = New System.Drawing.Size(73, 17)
Me.Chocolate_RadioButton.TabIndex = 11
Me.Chocolate_RadioButton.Text = "Chocolate"
Me.Chocolate_RadioButton.UseVisualStyleBackColor = True
'
'Filled_RadioButton
'
Me.Filled_RadioButton.AutoSize = True
Me.Filled_RadioButton.Location = New System.Drawing.Point(3, 72)
Me.Filled_RadioButton.Name = "Filled_RadioButton"
Me.Filled_RadioButton.Size = New System.Drawing.Size(49, 17)
Me.Filled_RadioButton.TabIndex = 12
Me.Filled_RadioButton.Text = "Filled"
Me.Filled_RadioButton.UseVisualStyleBackColor = True
'
'Regular_RadioButton
'
Me.Regular_RadioButton.AutoSize = True
Me.Regular_RadioButton.Location = New System.Drawing.Point(3, 3)
Me.Regular_RadioButton.Name = "Regular_RadioButton"
Me.Regular_RadioButton.Size = New System.Drawing.Size(62, 17)
Me.Regular_RadioButton.TabIndex = 13
Me.Regular_RadioButton.Text = "Regular"
Me.Regular_RadioButton.UseVisualStyleBackColor = True
'
'Cappuccino_RadioButton
'
Me.Cappuccino_RadioButton.AutoSize = True
Me.Cappuccino_RadioButton.Location = New System.Drawing.Point(3, 26)
Me.Cappuccino_RadioButton.Name = "Cappuccino_RadioButton"
Me.Cappuccino_RadioButton.Size = New System.Drawing.Size(82, 17)
Me.Cappuccino_RadioButton.TabIndex = 14
Me.Cappuccino_RadioButton.Text = "Cappuccino"
Me.Cappuccino_RadioButton.UseVisualStyleBackColor = True
'
'TableLayoutPanel1
'
Me.TableLayoutPanel1.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
Me.TableLayoutPanel1.AutoSize = True
Me.TableLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink
Me.TableLayoutPanel1.ColumnCount = 2
Me.TableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
Me.TableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
Me.TableLayoutPanel1.Controls.Add(Me.Total_Label, 1, 2)
Me.TableLayoutPanel1.Controls.Add(Me.Label5, 0, 2)
Me.TableLayoutPanel1.Controls.Add(Me.Tax_Label, 1, 1)
Me.TableLayoutPanel1.Controls.Add(Me.Label3, 0, 1)
Me.TableLayoutPanel1.Controls.Add(Me.SubTotal_Label, 1, 0)
Me.TableLayoutPanel1.Controls.Add(Me.Label1, 0, 0)
Me.TableLayoutPanel1.Location = New System.Drawing.Point(67, 133)
Me.TableLayoutPanel1.Name = "TableLayoutPanel1"
Me.TableLayoutPanel1.RowCount = 3
Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
Me.TableLayoutPanel1.Size = New System.Drawing.Size(140, 57)
Me.TableLayoutPanel1.TabIndex = 9
'
'Total_Label
'
Me.Total_Label.Anchor = System.Windows.Forms.AnchorStyles.Left
Me.Total_Label.AutoSize = True
Me.Total_Label.Location = New System.Drawing.Point(80, 41)
Me.Total_Label.Margin = New System.Windows.Forms.Padding(10, 3, 10, 3)
Me.Total_Label.Name = "Total_Label"
Me.Total_Label.Size = New System.Drawing.Size(39, 13)
Me.Total_Label.TabIndex = 5
Me.Total_Label.Text = "Label6"
'
'Label5
'
Me.Label5.Anchor = System.Windows.Forms.AnchorStyles.Left
Me.Label5.AutoSize = True
Me.Label5.Location = New System.Drawing.Point(10, 41)
Me.Label5.Margin = New System.Windows.Forms.Padding(10, 3, 10, 3)
Me.Label5.Name = "Label5"
Me.Label5.Size = New System.Drawing.Size(31, 13)
Me.Label5.TabIndex = 4
Me.Label5.Text = "Total"
'
'Tax_Label
'
Me.Tax_Label.Anchor = System.Windows.Forms.AnchorStyles.Left
Me.Tax_Label.AutoSize = True
Me.Tax_Label.Location = New System.Drawing.Point(80, 22)
Me.Tax_Label.Margin = New System.Windows.Forms.Padding(10, 3, 10, 3)
Me.Tax_Label.Name = "Tax_Label"
Me.Tax_Label.Size = New System.Drawing.Size(39, 13)
Me.Tax_Label.TabIndex = 3
Me.Tax_Label.Text = "Label4"
'
'Label3
'
Me.Label3.Anchor = System.Windows.Forms.AnchorStyles.Left
Me.Label3.AutoSize = True
Me.Label3.Location = New System.Drawing.Point(10, 22)
Me.Label3.Margin = New System.Windows.Forms.Padding(10, 3, 10, 3)
Me.Label3.Name = "Label3"
Me.Label3.Size = New System.Drawing.Size(25, 13)
Me.Label3.TabIndex = 2
Me.Label3.Text = "Tax"
'
'SubTotal_Label
'
Me.SubTotal_Label.Anchor = System.Windows.Forms.AnchorStyles.Left
Me.SubTotal_Label.AutoSize = True
Me.SubTotal_Label.Location = New System.Drawing.Point(80, 3)
Me.SubTotal_Label.Margin = New System.Windows.Forms.Padding(10, 3, 10, 3)
Me.SubTotal_Label.Name = "SubTotal_Label"
Me.SubTotal_Label.Size = New System.Drawing.Size(39, 13)
Me.SubTotal_Label.TabIndex = 1
Me.SubTotal_Label.Text = "Label2"
'
'Label1
'
Me.Label1.Anchor = System.Windows.Forms.AnchorStyles.Left
Me.Label1.AutoSize = True
Me.Label1.Location = New System.Drawing.Point(10, 3)
Me.Label1.Margin = New System.Windows.Forms.Padding(10, 3, 10, 3)
Me.Label1.Name = "Label1"
Me.Label1.Size = New System.Drawing.Size(50, 13)
Me.Label1.TabIndex = 0
Me.Label1.Text = "SubTotal"%0

VB.NET Custom Drawn Control Memory Usage

I have a lot of custom controls that change colour when the mouse hovers over them. Unfortunately, the memory usage sky rockets with repeated hovers. It starts off at about 14mb and shoots up to 100mb after quickly hovering over it for a few times.
Some code is shown below, this is the generation, drawing and invalidating of control. I believe the memory issue will lie in here somewhere. The memory used only seems to get released when the application is minimized.
Public Sub New()
' This call is required by the designer.
InitializeComponent()
SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.OptimizedDoubleBuffer Or ControlStyles.ResizeRedraw Or ControlStyles.UserPaint, True)
SetStyle(ControlStyles.Opaque, True)
' Add any initialization after the InitializeComponent() call.
Me.Invalidate()
End Sub
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
Dim BorderColour As Color = ColourSchemes.GetLighterColourFromTheme
Dim FillColour As Color = ColourSchemes.GetNormalColourFromTheme
Dim CheckFillColour As Color = ColourSchemes.GetNormalColourFromTheme(ColourSchemes.HiddenTheme.SilverInterface)
Dim OutlineCheckColour As Color = ColourSchemes.GetNormalColourFromTheme
Dim InnerRect As New Rectangle(New Point(0, 0), New Size(Me.Width - 1, Me.Height - 1))
If CTRLRule = CTRLStyle.Classic Or CTRLRule = CTRLStyle.ClassicWithColour Then
'CLASSIC STYLE
Dim XY As Integer = 0
If CTRLBoxSize = 0 Then
XY = CalculateCheckSquare()
Else
XY = CTRLBoxSize
End If
Dim CheckRect As New Rectangle(New Point(5, ((Me.Height - XY + 2)) / 2), New Size(XY - 4, XY - 4))
Dim TextHeight As Integer = TextRenderer.MeasureText(Text, Font).Height
Dim TextArea As New Rectangle(New Point(5 + XY + 5, (Me.Height - TextHeight) / 2), New Size(Me.Width - (7 + XY), TextHeight))
If CTRLRule = CTRLStyle.Classic Then
Select Case Switcher
Case StyleSwitcher.Normal
OutlineCheckColour = ColourSchemes.GetNormalColourFromTheme(ColourSchemes.HiddenTheme.SilverInterface)
CheckFillColour = ColourSchemes.GetNormalColourFromTheme(ColourSchemes.HiddenTheme.SilverInterface)
Case StyleSwitcher.Rollover
OutlineCheckColour = ColourSchemes.GetLighterColourFromStyle(ColourStyle)
CheckFillColour = ColourSchemes.GetLighterColourFromStyle(ColourStyle)
If Checked = True Then
OutlineCheckColour = ColourSchemes.GetNormalColourFromStyle(ColourStyle)
CheckFillColour = ColourSchemes.GetNormalColourFromStyle(ColourStyle)
End If
Case StyleSwitcher.Depressed
OutlineCheckColour = ColourSchemes.GetDarkerColourFromStyle(ColourStyle)
CheckFillColour = ColourSchemes.GetDarkerColourFromStyle(ColourStyle)
End Select
Else
Select Case Switcher
Case StyleSwitcher.Normal
OutlineCheckColour = ColourSchemes.GetNormalColourFromTheme(ColourSchemes.HiddenTheme.SilverInterface)
Case StyleSwitcher.Rollover
OutlineCheckColour = ColourSchemes.GetLighterColourFromStyle(ColourStyle)
Case StyleSwitcher.Depressed
OutlineCheckColour = ColourSchemes.GetDarkerColourFromStyle(ColourStyle)
End Select
If Checked = True Then
BorderColour = ColourSchemes.GetNormalColourFromStyle(ColourStyle)
CheckFillColour = ColourSchemes.GetNormalColourFromStyle(ColourStyle)
OutlineCheckColour = ColourSchemes.GetNormalColourFromStyle(ColourStyle)
End If
CheckFillColour = OutlineCheckColour
End If
e.Graphics.FillRectangle(New SolidBrush(FillColour), InnerRect)
e.Graphics.DrawRectangle(New Pen(BorderColour), InnerRect)
e.Graphics.DrawEllipse(New Pen(OutlineCheckColour, 2), CheckRect)
e.Graphics.DrawString(Text, Font, New SolidBrush(ColourSchemes.GetFontColourFromTheme), TextArea, New StringFormat With {.LineAlignment = StringAlignment.Center, .Alignment = StringAlignment.Near})
If Checked = True Then
Dim TSize As Integer = (CheckRect.Width / 6) 'WANT INNERDS TO FILL 3/4
e.Graphics.FillEllipse(New SolidBrush(CheckFillColour), New Rectangle(New Point(CheckRect.X + TSize, CheckRect.Y + TSize), New Size(CheckRect.Width - (TSize * 2), CheckRect.Height - (TSize * 2))))
End If
Else
'LIGHT STYLE
Dim LightPen As Color = ColourSchemes.GetLighterColourFromTheme
Dim LightPen2 As Color
Dim TextColour As Color = ColourSchemes.GetFontColourFromTheme
If CTRLRule = CTRLStyle.Light Then
LightPen2 = ColourSchemes.GetLighterColourFromTheme
Else
LightPen2 = ColourSchemes.GetNormalColourFromStyle(ColourStyle)
If Me.Checked = True Then
TextColour = ColourSchemes.GetNormalColourFromStyle(ColourStyle)
End If
End If
e.Graphics.DrawLine(New Pen(ColourSchemes.GetDarkerColourFromTheme, 3), New Point(0, Me.Height - 1), New Point(Me.Width, Me.Height - 1))
Dim ArrowH As Integer = Me.Height - ((Me.Height - 8) / 2)
If Me.Checked = True Then
e.Graphics.DrawLine(New Pen(LightPen2, 2), New Point(Me.Width - 30, Convert.ToSingle(ArrowH)), New Point(Me.Width - 20, Convert.ToSingle(ArrowH - 8)))
e.Graphics.DrawLine(New Pen(LightPen2, 2), New Point(Me.Width - 10, Convert.ToSingle(ArrowH)), New Point(Me.Width - 20, Convert.ToSingle(ArrowH - 8)))
Else
e.Graphics.DrawLine(New Pen(LightPen, 2), New Point(Me.Width - 20, Convert.ToSingle(ArrowH)), New Point(Me.Width - 30, Convert.ToSingle(ArrowH - 8)))
e.Graphics.DrawLine(New Pen(LightPen, 2), New Point(Me.Width - 20, Convert.ToSingle(ArrowH)), New Point(Me.Width - 10, Convert.ToSingle(ArrowH - 8)))
End If
e.Graphics.DrawString(Text, Font, New SolidBrush(TextColour), InnerRect, New StringFormat With {.Alignment = StringAlignment.Near, .LineAlignment = StringAlignment.Center})
End If
End Sub
Protected Overrides Sub OnMouseLeave(ByVal e As System.EventArgs)
MyBase.OnMouseLeave(e)
Switcher = StyleSwitcher.Normal
Me.Invalidate()
End Sub
Protected Overrides Sub OnMouseEnter(ByVal e As System.EventArgs)
MyBase.OnMouseEnter(e)
Switcher = StyleSwitcher.Rollover
Me.Invalidate()
End Sub
EDIT: Following #Hans Passant comment, I have changed the code around to make use of "using" statements. However, this seems to have no effect in runtime. The changed code is shown below (providing I interpreted the comment correctly)
e.Graphics.FillRectangle(New SolidBrush(FillColour), InnerRect)
e.Graphics.DrawRectangle(New Pen(BorderColour), InnerRect)
e.Graphics.DrawEllipse(New Pen(OutlineCheckColour, 2), CheckRect)
Using Brush As New SolidBrush(FillColour)
e.Graphics.FillRectangle(Brush, InnerRect)
End Using
Using Pen As New Pen(BorderColour, 1)
e.Graphics.DrawRectangle(Pen, InnerRect)
Pen.Color = OutlineCheckColour
Pen.Width = 2
e.Graphics.DrawEllipse(Pen, CheckRect)
End Using