Groupbox - change border colour - RowPosition error - vb.net

I have this code to change border colour of Groupboxes. It adds custom groupbox to my Toolbox and I can change border colour, but every time I start debugging I get this error: InvalidArgument=Value of "-2147483648" is not valid for 'RowPosition'.. As I read online, this error is produced when there is some bad code in project. Anybody knows how I should deal with this ?
Public Class GroupBox_Color
Inherits GroupBox
Private _borderColor As Color
Public Sub New()
MyBase.New()
Me._borderColor = Color.Blue
End Sub
Public Property BorderColor() As Color
Get
Return Me._borderColor
End Get
Set(ByVal value As Color)
Me._borderColor = value
End Set
End Property
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
Dim tSize As Size = TextRenderer.MeasureText(Me.Text, Me.Font)
Dim borderRect As Rectangle = Me.DisplayRectangle
borderRect.Y = (borderRect.Y + (tSize.Height / 2))
borderRect.Height = (borderRect.Height - (tSize.Height / 2))
ControlPaint.DrawBorder(e.Graphics, borderRect, Me._borderColor,
ButtonBorderStyle.Solid)
Dim textRect As Rectangle = Me.DisplayRectangle
textRect.X = (textRect.X + 6)
textRect.Width = tSize.Width
textRect.Height = tSize.Height
e.Graphics.FillRectangle(New SolidBrush(Me.BackColor), textRect)
e.Graphics.DrawString(Me.Text, Me.Font, New SolidBrush(Me.ForeColor), textRect)
End Sub
End Class

Related

Custom Toggle Control "Checked" Property Does Not Save (Or Restore) With My.Settings()

I added a custom control to my project, which is a toggle switch that inherits the functionality of a checkbox. The problem I am facing is when I try to create an Application Setting to bind the control to, it does not save (or restore, I don't really know which) the Checked: property. To be more clear, no exception is thrown. The toggle works as designed, however it does not save the state of whether it was checked or not when relaunching the program. It just defaults back to its assigned state that was set in the designer. It's just not saving the fact that it was checked or unchecked when closing or relaunching the program. The My.Settings() code is fine, I've tested it with a checkbox and it saved and restored correctly. The problem lies in the Toggle.vb Class file I'd assume. Here is the source:
Imports System.ComponentModel
Imports System.Drawing.Drawing2D
Namespace CustomControls.RJControls
Public Class RJToggleButton
Inherits CheckBox
'Fields
Private onBackColorField As Color = Color.FromArgb(128, 255, 128)
Private onToggleColorField As Color = Color.White
Private offBackColorField As Color = Color.Black
Private offToggleColorField As Color = Color.White
Private solidStyleField As Boolean = True
'Properties
<Category("RJ Code Advance")>
Public Property OnBackColor As Color
Get
Return onBackColorField
End Get
Set(ByVal value As Color)
onBackColorField = value
Me.Invalidate()
End Set
End Property
<Category("RJ Code Advance")>
Public Property OnToggleColor As Color
Get
Return onToggleColorField
End Get
Set(ByVal value As Color)
onToggleColorField = value
Me.Invalidate()
End Set
End Property
<Category("RJ Code Advance")>
Public Property OffBackColor As Color
Get
Return offBackColorField
End Get
Set(ByVal value As Color)
offBackColorField = value
Me.Invalidate()
End Set
End Property
<Category("RJ Code Advance")>
Public Property OffToggleColor As Color
Get
Return offToggleColorField
End Get
Set(ByVal value As Color)
offToggleColorField = value
Me.Invalidate()
End Set
End Property
<Browsable(False)>
Public Overrides Property Text As String
Get
Return MyBase.Text
End Get
Set(ByVal value As String)
End Set
End Property
<Category("RJ Code Advance")>
<DefaultValue(True)>
Public Property SolidStyle As Boolean
Get
Return solidStyleField
End Get
Set(ByVal value As Boolean)
solidStyleField = value
Me.Invalidate()
End Set
End Property
'Constructor
Public Sub New()
Me.MinimumSize = New Size(45, 22)
End Sub
'Methods
Private Function GetFigurePath() As GraphicsPath
Dim arcSize As Integer = Me.Height - 1
Dim leftArc As Rectangle = New Rectangle(0, 0, arcSize, arcSize)
Dim rightArc As Rectangle = New Rectangle(Me.Width - arcSize - 2, 0, arcSize, arcSize)
Dim path As GraphicsPath = New GraphicsPath()
path.StartFigure()
path.AddArc(leftArc, 90, 180)
path.AddArc(rightArc, 270, 180)
path.CloseFigure()
Return path
End Function
Protected Overrides Sub OnPaint(ByVal pevent As PaintEventArgs)
Dim toggleSize As Integer = Me.Height - 5
pevent.Graphics.SmoothingMode = SmoothingMode.AntiAlias
pevent.Graphics.Clear(Me.Parent.BackColor)
If Me.Checked Then 'ON
'Draw the control surface
If solidStyleField Then
pevent.Graphics.FillPath(New SolidBrush(onBackColorField), GetFigurePath())
Else
pevent.Graphics.DrawPath(New Pen(onBackColorField, 2), GetFigurePath())
End If
'Draw the toggle
pevent.Graphics.FillEllipse(New SolidBrush(onToggleColorField), New Rectangle(Me.Width - Me.Height + 1, 2, toggleSize, toggleSize)) 'OFF
Else
'Draw the control surface
If solidStyleField Then
pevent.Graphics.FillPath(New SolidBrush(offBackColorField), GetFigurePath())
Else
pevent.Graphics.DrawPath(New Pen(offBackColorField, 2), GetFigurePath())
End If
'Draw the toggle
pevent.Graphics.FillEllipse(New SolidBrush(offToggleColorField), New Rectangle(2, 2, toggleSize, toggleSize))
End If
End Sub
End Class
End Namespace
The binding code:
Private Sub FormMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Toggle1.Checked = My.Settings.ToggleState
End Sub
Private Sub Toggle1_CheckedChanged(sender As Object, e As EventArgs) Handles Toggle1.CheckedChanged
My.Settings.ToggleState = Toggle1.Checked
My.Settings.Save()
End Sub
My Settings:
Name: ToggleState, Type: Boolean, Scope: User, Value: True
Since I am barely a novice when it comes to coding, is there someway I can make the toggle function exactly as a checkbox, or allow it's state to be saved with My.Settings()? What am I missing to add that functionality to the toggle?
Environment: VB, .NET 6.0, Visual Basic 2022
When creating the new Application Setting, the type Boolean was assigned, and the Value assigned was True. In the form Designer, the Checked Property was also set to True. It seemed the Setting Value True or False would set the Toggle's default checked state. The Checked Value in the designer had to be set to false, in order to allow the New Setting to function properly with My.Settings().

Changing 'lamp' Colour Indicator within the Graphical User Interface (Visual Studio 2019)

I would like to change the colour within a single circular indicator within a Graphical User Interface, so that it shows when an action is completed or when it fails ['two tone green/red LED']. I've looked through the inbuilt presets within the Toolbox but have been unable find anything.
I would therefore be grateful for any assistance.
I've found this code on the msdn.microsoft.com forum, which changes the colour of the centre of the 'dot' when you press the RadioButton.
Private Sub RadioButton_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles RadioButton1.Paint, RadioButton2.Paint
If DirectCast(sender, RadioButton).Checked Then
e.Graphics.FillEllipse(Brushes.Red, New RectangleF(2.5, 4.7, 7.2, 7.2))
End If
So have incorporated it into my code, its not at all elegant and there is clearly room for improvement, but it does work.
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
If My.Computer.Network.Ping("192.168.0.1") Then
RadioButton1.ForeColor = Color.Green
RadioButton1.ForeColor = Color.Black
Else
RadioButton1.ForeColor = Color.Red
RadioButton1.ForeColor = Color.Black
End If
End Sub
Private Sub RadioButton_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles RadioButton1.Paint
If My.Computer.Network.Ping("192.168.0.1") Then
e.Graphics.FillEllipse(Brushes.Green, New RectangleF(2.5, 4.7, 7.2, 7.2))
Else
e.Graphics.FillEllipse(Brushes.Red, New RectangleF(2.5, 4.7, 7.2, 7.2))
End If
End Sub
Explanation: when the 'Test Network' button is pressed it sends out a network ping, and depending upon the return the Network RadioButton 'dot' changes colour to either Green or Red,
Here's ON/OFF LED control.
Add a new class to your project, name it say OnOffLed.vb, copy the code below and paste it in the new class.
Imports System.Windows.Forms
Imports System.Drawing
Imports System.Drawing.Drawing2D
Public Class OnOffLed
Inherits Panel
Public Enum LedState
[On]
Off
End Enum
Sub New()
SetStyle(ControlStyles.AllPaintingInWmPaint Or
ControlStyles.OptimizedDoubleBuffer Or
ControlStyles.ResizeRedraw Or
ControlStyles.UserPaint, True)
UpdateStyles()
End Sub
Private _state As LedState = LedState.Off
Public Property State As LedState
Get
Return _state
End Get
Set(value As LedState)
_state = value
Invalidate()
End Set
End Property
Private _onText As String
Public Property OnText As String
Get
Return _onText
End Get
Set(value As String)
_onText = value
Invalidate()
End Set
End Property
Private _offText As String
Public Property OffText As String
Get
Return _offText
End Get
Set(value As String)
_offText = value
Invalidate()
End Set
End Property
Protected Overrides Sub OnPaint(e As PaintEventArgs)
Dim rec As New Rectangle(2, 2, Height - 5, Height - 5)
Dim recText As New Rectangle(Height + 2, 1, Width - (Height - 2), Height)
Dim G As Graphics = e.Graphics
G.SmoothingMode = SmoothingMode.AntiAlias
G.Clear(Parent.BackColor)
If _state = LedState.On Then
Dim cb As New ColorBlend With {
.Colors = {Color.Green, Color.DarkGreen, Color.Green},
.Positions = {0, 0.5, 1}
}
Using lgb As New LinearGradientBrush(rec, Color.Empty, Color.Empty, 90.0F) With {.InterpolationColors = cb}
G.FillEllipse(lgb, rec)
End Using
Else
Dim cb As New ColorBlend With {
.Colors = {Color.Red, Color.DarkRed, Color.Red},
.Positions = {0, 0.5, 1}
}
Using lgb As New LinearGradientBrush(rec, Color.Empty, Color.Empty, 90.0F) With {.InterpolationColors = cb}
G.FillEllipse(lgb, rec)
End Using
End If
G.TextRenderingHint = Drawing.Text.TextRenderingHint.ClearTypeGridFit
Using br As New SolidBrush(ForeColor)
Using sf As New StringFormat With {.Alignment = StringAlignment.Near, .LineAlignment = StringAlignment.Center}
G.DrawString(If(_state = LedState.On, _onText, _offText), Font, br, recText, sf)
End Using
End Using
End Sub
End Class
Rebuild your project.
In the ToolBox under your project's component tab, you'll find the new control. OnOffLed. Drop it in your form as you drop any other control.
You can toggle the state through the State property, set different text if you need that for each state through the OnText and OffText properties.
Usage Example:
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
If My.Computer.Network.Ping("192.168.2.01") Then
OnOffLed1.State = OnOffLed.LedState.On
Else
OnOffLed1.State = OnOffLed.LedState.Off
End If
End Sub
Good luck.

How to change background color of DataGridViewComboBoxColumn items at run time?

I need to set the "red" color of some elements (like capacity>20) in my DataGridViewComboBoxColumn so I tried to get this result in my combo1
from this site:
https://social.msdn.microsoft.com/Forums/vstudio/en-US/eb870646-1da3-4217-9de0-5a398b967af2/how-to-change-background-color-of-combobox-items-at-run-time
I already populated it and it worked well. I tried to modify this class but it did not work
Class CustomComboDataGridViewColumn : Inherits DataGridViewComboBoxColumn
Protected Overrides Sub OnDrawItem(e As DrawItemEventArgs)
MyBase.OnDrawItem(e)
Dim item As CComboboxItem = DirectCast(Me.Items(e.Index), CComboboxItem)
Using ForeBrush As Brush = New SolidBrush(item.Forecolor)
Using BackBrush As Brush = New SolidBrush(item.Backcolor)
e.Graphics.FillRectangle(BackBrush, e.Bounds)
e.Graphics.TranslateTransform(0, e.Bounds.Y)
e.Graphics.DrawString(item.ToString, Me.Font, ForeBrush, 0, 0)
End Using
End Using
End Sub
Class CComboboxItem
Public Sub New(Value As Object, Color As Color, BackColor As Color)
Me.Value = Value
Me.Forecolor = Color
Me.Backcolor = BackColor
End Sub
Public Property Value As Object = Nothing
Public Property Forecolor As Color = Color.Black
Public Property Backcolor As Color = Color.Black
OnDrawItem is not included in this class DataGridViewComboBoxColumn

Grid I can paint on

So I am trying to create an application to ease creation of pixel arts (school project), what I've done so far is draw a grid in a panel, next step would be to allow the user to click on a cell and have it painted, but I can't manage to make it work, here's the code I have:
Private Sub drawGrid(g As Graphics, rows As Integer, columns As Integer)
Dim originPoint As Point = New Point(10, 2)
Dim size As Size = New Size(64, 64)
Dim left As Integer = originPoint.X
Dim up As Integer = originPoint.Y
Dim right As Integer = originPoint.X + (columns * size.Width)
Dim down As Integer = originPoint.Y + (rows * size.Height)
For y As Integer = up To down + 1 Step size.Height
Dim pt1 As New Point(left, y)
Dim pt2 As New Point(right, y)
g.DrawLine(Pens.Black, pt1, pt2)
Next
For x As Integer = left To right + 1 Step size.Width
Dim pt1 As New Point(x, up)
Dim pt2 As New Point(x, down)
g.DrawLine(Pens.Black, pt1, pt2)
Next
End Sub
This draws a grid with the amount of columns and rows the user wants, but I've been struggling to allow painting
What I've been thinking is: dispose this code, and create a 'pixel' class, create the amount of 'pixel' objects based on user rows and columns, and draw each one individually, then just change each 'pixel's' color
This is a Grid class that allows setting the color of its cells.
The Grid cell are referenced using a List(Of List(Of Class)).
The Cell class Object contains is a simple Rectagle property that measures the size of the cell, and a Color property, which allows to set the color of the single cell:
Friend Class GridCell
Public Property Cell() As Rectangle
Public Property CellColor() As Color
End Class
You can define:
The size of the Grid → ColoredGrid.GridSize = new Size(...)
The number of Columns and Rows → ColoredGrid.GridColumnsRows = new Size(...)
The position of the Grid inside the Canvas → ColoredGrid.GridPosition = New Point(...)
The color of the Grid → ColoredGrid.GridColor = Color.Gray
The BackGround color of the cells → ColoredGrid.CellColor = Color.FromArgb(32, 32, 32)
The color of a selected cell → ColoredGrid.SelectedCellColor = Color.OrangeRed
The Grid class holds a reference to the control which will be used as the Canvas for the grid painting. This reference is set in the class contructor.
The Grid registers the Canvas control Paint() and MouseClick() events to respond to the related actions automatically.
When a Mouse Click is detected on the Canvas surface, the MouseEventArgs e.Location property reports the coordinates where the Click occurred.
To identify the Grid Cell where this action is performed, the GetUpdateCell() method inspects the List(Of List(Of GridCell)) using a simple LINQ SelectMany() and identified the Cell rectangle that contains the Mouse Click coordinates (expressed as a Point() value).
This identification is performed simply checking whether the Cell Rectangle.Contains(Point()).
When the cell is identified, the Canvas Invalidate() method is called, specifing the area to repaint.
This area corresponds to the Cell Rectangle, so only this section is repainted when a Cell is colored, to save resources and time.
To test it, create a Panel and a Button in a Form:
Imports System.Drawing
'This Grid object in defined at Form Class scope
Public ColoredGrid As ColorGrid
'Button used to trigger the Grid painting
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If ColoredGrid IsNot Nothing Then
ColoredGrid.Dispose()
End If
ColoredGrid = New ColorGrid(Panel1)
ColoredGrid.GridSize = New Size(300, 300)
ColoredGrid.GridColumnsRows = New Size(10, 10)
ColoredGrid.GridPosition = New Point(10, 10)
ColoredGrid.GridColor = Color.White
ColoredGrid.CellColor = Color.FromArgb(32, 32, 32)
ColoredGrid.SelectedCellColor = Color.OrangeRed
ColoredGrid.BuildGrid()
End Sub
This is a visual sample that shows how it works:
This is the main Grid class.
The ColorGrid Class supports IDisposable, because it registers the described events. These must be unregistered when the Class is not used anymore. Weird things can happen if you don't.
Public Class ColorGrid
Implements IDisposable
Private Grid As List(Of List(Of GridCell))
Private CurrentGridSize As New Size(100, 100)
Private GridColRows As New Size(10, 10)
Private CellSize As New Size(10, 10)
Private MouseCell As Point = Point.Empty
Private Canvas As Control = Nothing
Private UpdateCell As Boolean = False
Private NewGrid As Boolean = False
Public Sub New(DrawingControl As Control)
If DrawingControl IsNot Nothing Then
Me.Canvas = DrawingControl
AddHandler Me.Canvas.Paint, New PaintEventHandler(AddressOf Me.ControlPaint)
AddHandler Me.Canvas.MouseClick, New MouseEventHandler(AddressOf Me.MouseHandler)
Me.GridPosition = New Point(10, 10)
Me.CellColor = Color.FromArgb(32, 32, 32)
End If
End Sub
Public Property GridPosition() As Point
Public Property CellColor() As Color
Public Property SelectedCellColor() As Color
Public Property GridColor() As Color
Public Property GridSize() As Size
Get
Return Me.CurrentGridSize
End Get
Set(value As Size)
Me.CurrentGridSize = value
SetCellSize()
End Set
End Property
Public Property GridColumnsRows() As Size
Get
Return Me.GridColRows
End Get
Set(value As Size)
Me.GridColRows = value
SetCellSize()
End Set
End Property
Private Property RefreshCell() As GridCell
Friend Class GridCell
Public Property Cell() As Rectangle
Public Property CellColor() As Color
End Class
Private Sub SetCellSize()
Me.CellSize = New Size((Me.CurrentGridSize.Width \ Me.GridColRows.Width),
(Me.CurrentGridSize.Height \ Me.GridColRows.Height))
If Me.CellSize.Width < 4 Then Me.CellSize.Width = 4
If Me.CellSize.Height < 4 Then Me.CellSize.Height = 4
End Sub
Public Sub BuildGrid()
If Me.Canvas Is Nothing Then Return
Me.Grid = New List(Of List(Of GridCell))()
For row As Integer = 0 To GridColumnsRows.Height - 1
Dim RowCells As New List(Of GridCell)()
For col As Integer = 0 To GridColumnsRows.Width - 1
RowCells.Add(New GridCell() With {
.Cell = New Rectangle(New Point(Me.GridPosition.X + (col * Me.CellSize.Width),
Me.GridPosition.Y + (row * Me.CellSize.Height)),
Me.CellSize),
.CellColor = Me.CellColor})
Next
Me.Grid.Add(RowCells)
Next
Me.NewGrid = True
Me.Canvas.Invalidate()
End Sub
Private Sub ControlPaint(o As Object, e As PaintEventArgs)
If Me.NewGrid Then
e.Graphics.Clear(Me.Canvas.BackColor)
Me.NewGrid = False
End If
Me.Grid.
SelectMany(Function(rowcells) rowcells).
Select(Function(colcell)
If Me.UpdateCell Then
Using brush As New SolidBrush(Me.RefreshCell.CellColor)
e.Graphics.FillRectangle(brush, Me.RefreshCell.Cell.X + 1, Me.RefreshCell.Cell.Y + 1,
Me.RefreshCell.Cell.Width - 1, Me.RefreshCell.Cell.Height - 1)
End Using
Me.UpdateCell = False
Return Nothing
Else
Using pen As New Pen(Me.GridColor)
e.Graphics.DrawRectangle(pen, colcell.Cell)
End Using
Using brush As New SolidBrush(colcell.CellColor)
e.Graphics.FillRectangle(brush, colcell.Cell.X + 1, colcell.Cell.Y + 1,
colcell.Cell.Width - 1, colcell.Cell.Height - 1)
End Using
End If
Return colcell
End Function).TakeWhile(Function(colcell) colcell IsNot Nothing).ToList()
End Sub
Private Sub MouseHandler(o As Object, e As MouseEventArgs)
Me.RefreshCell = GetUpdateCell(e.Location)
Me.RefreshCell.CellColor = Me.SelectedCellColor
Dim CellColorArea As Rectangle = Me.RefreshCell.Cell
CellColorArea.Inflate(-1, -1)
Me.UpdateCell = True
Me.Canvas.Invalidate(CellColorArea)
End Sub
Private Function GetUpdateCell(CellPosition As Point) As GridCell
Return Me.Grid.
SelectMany(Function(rowcells) rowcells).
Select(Function(gridcell) gridcell).
Where(Function(gridcell) gridcell.Cell.Contains(CellPosition)).
First()
End Function
Public Sub Dispose() Implements IDisposable.Dispose
If Me.Canvas IsNot Nothing Then
RemoveHandler Me.Canvas.Paint, AddressOf Me.ControlPaint
RemoveHandler Me.Canvas.MouseClick, AddressOf Me.MouseHandler
Me.Grid = Nothing
End If
End Sub
End Class

Custom Control Display Issue

I have created this class in visual Basic it works fine but there is a slight design issue. As you can see there is this small bumb, how can I fix this? And also, how can I fix the spacing between the content Box and the selection menu.
Public Class VerticallTabControll
Inherits TabControl
Sub New()
SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.OptimizedDoubleBuffer Or ControlStyles.ResizeRedraw Or ControlStyles.UserPaint, True)
DoubleBuffered = True
SizeMode = TabSizeMode.Fixed
ItemSize = New Size(30, 170)
End Sub
Protected Overrides Sub CreateHandle()
MyBase.CreateHandle()
Alignment = TabAlignment.Left
End Sub
Protected Overrides Sub OnPaint(e As PaintEventArgs)
Dim selected As New SolidBrush(Color.FromArgb(0, 122, 204))
Dim notSelected As New SolidBrush(Color.FromArgb(63, 63, 70))
Dim B As New Bitmap(Width, Height)
Dim G As Graphics = Graphics.FromImage(B)
G.Clear(Color.FromArgb(63, 63, 70))
For i = 0 To TabCount - 1
Dim TabRectangle As Rectangle = GetTabRect(i)
If i = SelectedIndex Then
'// if tab is selected
G.FillRectangle(selected, TabRectangle)
Else
'// tab is not selected
G.FillRectangle(notSelected, TabRectangle)
End If
'Line Test
'Dim start As New Point(10, 31 * (i + 1))
'Dim ende As New Point(160, 31 * (i + 1))
'G.DrawLine(Pens.White, start, ende)
G.DrawString(TabPages(i).Text, Font, Brushes.White, TabRectangle, New StringFormat With {.Alignment = StringAlignment.Center, .LineAlignment = StringAlignment.Center})
Next
e.Graphics.DrawImage(B.Clone, 0, 0)
G.Dispose() : B.Dispose() : selected.Dispose() : notSelected.Dispose()
MyBase.OnPaint(e)
e.Dispose()
End Sub
End Class
You can try overriding the DisplayRectangle property to adjust the interior space accordingly:
Public Overrides ReadOnly Property DisplayRectangle As Rectangle
Get
Return New Rectangle(MyBase.DisplayRectangle.Left,
MyBase.DisplayRectangle.Top - 2,
MyBase.DisplayRectangle.Width + 2,
MyBase.DisplayRectangle.Height + 4)
End Get
End Property